app_queue.c 362 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2006, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief True call queues with optional send URL on answer
  21. *
  22. * \author Mark Spencer <markster@digium.com>
  23. *
  24. * \par Development notes
  25. * \note 2004-11-25: Persistent Dynamic Members added by:
  26. * NetNation Communications (www.netnation.com)
  27. * Kevin Lindsay <kevinl@netnation.com>
  28. *
  29. * Each dynamic agent in each queue is now stored in the astdb.
  30. * When asterisk is restarted, each agent will be automatically
  31. * readded into their recorded queues. This feature can be
  32. * configured with the 'persistent_members=<1|0>' setting in the
  33. * '[general]' category in queues.conf. The default is on.
  34. *
  35. * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
  36. *
  37. * \note These features added by David C. Troy <dave@toad.net>:
  38. * - Per-queue holdtime calculation
  39. * - Estimated holdtime announcement
  40. * - Position announcement
  41. * - Abandoned/completed call counters
  42. * - Failout timer passed as optional app parameter
  43. * - Optional monitoring of calls, started when call is answered
  44. *
  45. * Patch Version 1.07 2003-12-24 01
  46. *
  47. * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
  48. * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
  49. *
  50. * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
  51. * by Matthew Enger <m.enger@xi.com.au>
  52. *
  53. * \ingroup applications
  54. */
  55. /*! \li \ref app_queues.c uses configuration file \ref queues.conf
  56. * \addtogroup configuration_file
  57. */
  58. /*! \page queues.conf queues.conf
  59. * \verbinclude queues.conf.sample
  60. */
  61. /*** MODULEINFO
  62. <use type="module">res_monitor</use>
  63. <support_level>core</support_level>
  64. ***/
  65. #include "asterisk.h"
  66. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  67. #include <sys/time.h>
  68. #include <sys/signal.h>
  69. #include <netinet/in.h>
  70. #include <ctype.h>
  71. #include "asterisk/lock.h"
  72. #include "asterisk/file.h"
  73. #include "asterisk/channel.h"
  74. #include "asterisk/pbx.h"
  75. #include "asterisk/app.h"
  76. #include "asterisk/linkedlists.h"
  77. #include "asterisk/module.h"
  78. #include "asterisk/translate.h"
  79. #include "asterisk/say.h"
  80. #include "asterisk/features.h"
  81. #include "asterisk/musiconhold.h"
  82. #include "asterisk/cli.h"
  83. #include "asterisk/manager.h"
  84. #include "asterisk/config.h"
  85. #include "asterisk/monitor.h"
  86. #include "asterisk/utils.h"
  87. #include "asterisk/causes.h"
  88. #include "asterisk/astdb.h"
  89. #include "asterisk/devicestate.h"
  90. #include "asterisk/stringfields.h"
  91. #include "asterisk/astobj2.h"
  92. #include "asterisk/strings.h"
  93. #include "asterisk/taskprocessor.h"
  94. #include "asterisk/aoc.h"
  95. #include "asterisk/callerid.h"
  96. #include "asterisk/data.h"
  97. #include "asterisk/term.h"
  98. #include "asterisk/dial.h"
  99. #include "asterisk/stasis_channels.h"
  100. #include "asterisk/stasis_message_router.h"
  101. #include "asterisk/bridge_after.h"
  102. #include "asterisk/stasis_bridges.h"
  103. #include "asterisk/core_local.h"
  104. #include "asterisk/mixmonitor.h"
  105. #include "asterisk/core_unreal.h"
  106. #include "asterisk/bridge_basic.h"
  107. #include "asterisk/max_forwards.h"
  108. /*!
  109. * \par Please read before modifying this file.
  110. * There are three locks which are regularly used
  111. * throughout this file, the queue list lock, the lock
  112. * for each individual queue, and the interface list lock.
  113. * Please be extra careful to always lock in the following order
  114. * 1) queue list lock
  115. * 2) individual queue lock
  116. * 3) interface list lock
  117. * This order has sort of "evolved" over the lifetime of this
  118. * application, but it is now in place this way, so please adhere
  119. * to this order!
  120. */
  121. /*** DOCUMENTATION
  122. <application name="Queue" language="en_US">
  123. <synopsis>
  124. Queue a call for a call queue.
  125. </synopsis>
  126. <syntax>
  127. <parameter name="queuename" required="true" />
  128. <parameter name="options">
  129. <optionlist>
  130. <option name="C">
  131. <para>Mark all calls as "answered elsewhere" when cancelled.</para>
  132. </option>
  133. <option name="c">
  134. <para>Continue in the dialplan if the callee hangs up.</para>
  135. </option>
  136. <option name="d">
  137. <para>data-quality (modem) call (minimum delay).</para>
  138. </option>
  139. <option name="F" argsep="^">
  140. <argument name="context" required="false" />
  141. <argument name="exten" required="false" />
  142. <argument name="priority" required="true" />
  143. <para>When the caller hangs up, transfer the <emphasis>called member</emphasis>
  144. to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
  145. <para>NOTE: Any channel variables you want the called channel to inherit from the caller channel must be
  146. prefixed with one or two underbars ('_').</para>
  147. </option>
  148. <option name="F">
  149. <para>When the caller hangs up, transfer the <emphasis>called member</emphasis> to the next priority of
  150. the current extension and <emphasis>start</emphasis> execution at that location.</para>
  151. <para>NOTE: Any channel variables you want the called channel to inherit from the caller channel must be
  152. prefixed with one or two underbars ('_').</para>
  153. <para>NOTE: Using this option from a Macro() or GoSub() might not make sense as there would be no return points.</para>
  154. </option>
  155. <option name="h">
  156. <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
  157. </option>
  158. <option name="H">
  159. <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
  160. </option>
  161. <option name="n">
  162. <para>No retries on the timeout; will exit this application and
  163. go to the next step.</para>
  164. </option>
  165. <option name="i">
  166. <para>Ignore call forward requests from queue members and do nothing
  167. when they are requested.</para>
  168. </option>
  169. <option name="I">
  170. <para>Asterisk will ignore any connected line update requests or any redirecting party
  171. update requests it may receive on this dial attempt.</para>
  172. </option>
  173. <option name="r">
  174. <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
  175. </option>
  176. <option name="R">
  177. <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
  178. </option>
  179. <option name="t">
  180. <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
  181. </option>
  182. <option name="T">
  183. <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
  184. </option>
  185. <option name="w">
  186. <para>Allow the <emphasis>called</emphasis> user to write the conversation to
  187. disk via Monitor.</para>
  188. </option>
  189. <option name="W">
  190. <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
  191. disk via Monitor.</para>
  192. </option>
  193. <option name="k">
  194. <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
  195. the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
  196. </option>
  197. <option name="K">
  198. <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
  199. the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
  200. </option>
  201. <option name="x">
  202. <para>Allow the <emphasis>called</emphasis> user to write the conversation
  203. to disk via MixMonitor.</para>
  204. </option>
  205. <option name="X">
  206. <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
  207. disk via MixMonitor.</para>
  208. </option>
  209. </optionlist>
  210. </parameter>
  211. <parameter name="URL">
  212. <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
  213. </parameter>
  214. <parameter name="announceoverride" />
  215. <parameter name="timeout">
  216. <para>Will cause the queue to fail out after a specified number of
  217. seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
  218. <replaceable>retry</replaceable> cycle.</para>
  219. </parameter>
  220. <parameter name="AGI">
  221. <para>Will setup an AGI script to be executed on the calling party's channel once they are
  222. connected to a queue member.</para>
  223. </parameter>
  224. <parameter name="macro">
  225. <para>Will run a macro on the called party's channel (the queue member) once the parties are connected.</para>
  226. </parameter>
  227. <parameter name="gosub">
  228. <para>Will run a gosub on the called party's channel (the queue member)
  229. once the parties are connected. The subroutine execution starts in the
  230. named context at the s exten and priority 1.</para>
  231. </parameter>
  232. <parameter name="rule">
  233. <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
  234. </parameter>
  235. <parameter name="position">
  236. <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
  237. would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
  238. the caller third in the queue.</para>
  239. </parameter>
  240. </syntax>
  241. <description>
  242. <para>In addition to transferring the call, a call may be parked and then picked
  243. up by another user.</para>
  244. <para>This application will return to the dialplan if the queue does not exist, or
  245. any of the join options cause the caller to not enter the queue.</para>
  246. <para>This application does not automatically answer and should be preceeded
  247. by an application such as Answer(), Progress(), or Ringing().</para>
  248. <para>This application sets the following channel variables upon completion:</para>
  249. <variablelist>
  250. <variable name="QUEUESTATUS">
  251. <para>The status of the call as a text string.</para>
  252. <value name="TIMEOUT" />
  253. <value name="FULL" />
  254. <value name="JOINEMPTY" />
  255. <value name="LEAVEEMPTY" />
  256. <value name="JOINUNAVAIL" />
  257. <value name="LEAVEUNAVAIL" />
  258. <value name="CONTINUE" />
  259. </variable>
  260. <variable name="ABANDONED">
  261. <para>If the call was not answered by an agent this variable will be TRUE.</para>
  262. <value name="TRUE" />
  263. </variable>
  264. </variablelist>
  265. </description>
  266. <see-also>
  267. <ref type="application">Queue</ref>
  268. <ref type="application">QueueLog</ref>
  269. <ref type="application">AddQueueMember</ref>
  270. <ref type="application">RemoveQueueMember</ref>
  271. <ref type="application">PauseQueueMember</ref>
  272. <ref type="application">UnpauseQueueMember</ref>
  273. <ref type="function">QUEUE_VARIABLES</ref>
  274. <ref type="function">QUEUE_MEMBER</ref>
  275. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  276. <ref type="function">QUEUE_EXISTS</ref>
  277. <ref type="function">QUEUE_WAITING_COUNT</ref>
  278. <ref type="function">QUEUE_MEMBER_LIST</ref>
  279. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  280. </see-also>
  281. </application>
  282. <application name="AddQueueMember" language="en_US">
  283. <synopsis>
  284. Dynamically adds queue members.
  285. </synopsis>
  286. <syntax>
  287. <parameter name="queuename" required="true" />
  288. <parameter name="interface" />
  289. <parameter name="penalty" />
  290. <parameter name="options" />
  291. <parameter name="membername" />
  292. <parameter name="stateinterface" />
  293. </syntax>
  294. <description>
  295. <para>Dynamically adds interface to an existing queue. If the interface is
  296. already in the queue it will return an error.</para>
  297. <para>This application sets the following channel variable upon completion:</para>
  298. <variablelist>
  299. <variable name="AQMSTATUS">
  300. <para>The status of the attempt to add a queue member as a text string.</para>
  301. <value name="ADDED" />
  302. <value name="MEMBERALREADY" />
  303. <value name="NOSUCHQUEUE" />
  304. </variable>
  305. </variablelist>
  306. </description>
  307. <see-also>
  308. <ref type="application">Queue</ref>
  309. <ref type="application">QueueLog</ref>
  310. <ref type="application">AddQueueMember</ref>
  311. <ref type="application">RemoveQueueMember</ref>
  312. <ref type="application">PauseQueueMember</ref>
  313. <ref type="application">UnpauseQueueMember</ref>
  314. <ref type="function">QUEUE_VARIABLES</ref>
  315. <ref type="function">QUEUE_MEMBER</ref>
  316. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  317. <ref type="function">QUEUE_EXISTS</ref>
  318. <ref type="function">QUEUE_WAITING_COUNT</ref>
  319. <ref type="function">QUEUE_MEMBER_LIST</ref>
  320. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  321. </see-also>
  322. </application>
  323. <application name="RemoveQueueMember" language="en_US">
  324. <synopsis>
  325. Dynamically removes queue members.
  326. </synopsis>
  327. <syntax>
  328. <parameter name="queuename" required="true" />
  329. <parameter name="interface" />
  330. </syntax>
  331. <description>
  332. <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
  333. <para>This application sets the following channel variable upon completion:</para>
  334. <variablelist>
  335. <variable name="RQMSTATUS">
  336. <value name="REMOVED" />
  337. <value name="NOTINQUEUE" />
  338. <value name="NOSUCHQUEUE" />
  339. <value name="NOTDYNAMIC" />
  340. </variable>
  341. </variablelist>
  342. <para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
  343. </description>
  344. <see-also>
  345. <ref type="application">Queue</ref>
  346. <ref type="application">QueueLog</ref>
  347. <ref type="application">AddQueueMember</ref>
  348. <ref type="application">RemoveQueueMember</ref>
  349. <ref type="application">PauseQueueMember</ref>
  350. <ref type="application">UnpauseQueueMember</ref>
  351. <ref type="function">QUEUE_VARIABLES</ref>
  352. <ref type="function">QUEUE_MEMBER</ref>
  353. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  354. <ref type="function">QUEUE_EXISTS</ref>
  355. <ref type="function">QUEUE_WAITING_COUNT</ref>
  356. <ref type="function">QUEUE_MEMBER_LIST</ref>
  357. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  358. </see-also>
  359. </application>
  360. <application name="PauseQueueMember" language="en_US">
  361. <synopsis>
  362. Pauses a queue member.
  363. </synopsis>
  364. <syntax>
  365. <parameter name="queuename" />
  366. <parameter name="interface" required="true" />
  367. <parameter name="options" />
  368. <parameter name="reason">
  369. <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
  370. </parameter>
  371. </syntax>
  372. <description>
  373. <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
  374. This prevents any calls from being sent from the queue to the interface until it is
  375. unpaused with UnpauseQueueMember or the manager interface. If no queuename is given,
  376. the interface is paused in every queue it is a member of. The application will fail if the
  377. interface is not found.</para>
  378. <para>This application sets the following channel variable upon completion:</para>
  379. <variablelist>
  380. <variable name="PQMSTATUS">
  381. <para>The status of the attempt to pause a queue member as a text string.</para>
  382. <value name="PAUSED" />
  383. <value name="NOTFOUND" />
  384. </variable>
  385. </variablelist>
  386. <para>Example: PauseQueueMember(,SIP/3000)</para>
  387. </description>
  388. <see-also>
  389. <ref type="application">Queue</ref>
  390. <ref type="application">QueueLog</ref>
  391. <ref type="application">AddQueueMember</ref>
  392. <ref type="application">RemoveQueueMember</ref>
  393. <ref type="application">PauseQueueMember</ref>
  394. <ref type="application">UnpauseQueueMember</ref>
  395. <ref type="function">QUEUE_VARIABLES</ref>
  396. <ref type="function">QUEUE_MEMBER</ref>
  397. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  398. <ref type="function">QUEUE_EXISTS</ref>
  399. <ref type="function">QUEUE_WAITING_COUNT</ref>
  400. <ref type="function">QUEUE_MEMBER_LIST</ref>
  401. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  402. </see-also>
  403. </application>
  404. <application name="UnpauseQueueMember" language="en_US">
  405. <synopsis>
  406. Unpauses a queue member.
  407. </synopsis>
  408. <syntax>
  409. <parameter name="queuename" />
  410. <parameter name="interface" required="true" />
  411. <parameter name="options" />
  412. <parameter name="reason">
  413. <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
  414. </parameter>
  415. </syntax>
  416. <description>
  417. <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
  418. and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
  419. <para>This application sets the following channel variable upon completion:</para>
  420. <variablelist>
  421. <variable name="UPQMSTATUS">
  422. <para>The status of the attempt to unpause a queue member as a text string.</para>
  423. <value name="UNPAUSED" />
  424. <value name="NOTFOUND" />
  425. </variable>
  426. </variablelist>
  427. <para>Example: UnpauseQueueMember(,SIP/3000)</para>
  428. </description>
  429. <see-also>
  430. <ref type="application">Queue</ref>
  431. <ref type="application">QueueLog</ref>
  432. <ref type="application">AddQueueMember</ref>
  433. <ref type="application">RemoveQueueMember</ref>
  434. <ref type="application">PauseQueueMember</ref>
  435. <ref type="application">UnpauseQueueMember</ref>
  436. <ref type="function">QUEUE_VARIABLES</ref>
  437. <ref type="function">QUEUE_MEMBER</ref>
  438. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  439. <ref type="function">QUEUE_EXISTS</ref>
  440. <ref type="function">QUEUE_WAITING_COUNT</ref>
  441. <ref type="function">QUEUE_MEMBER_LIST</ref>
  442. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  443. </see-also>
  444. </application>
  445. <application name="QueueLog" language="en_US">
  446. <synopsis>
  447. Writes to the queue_log file.
  448. </synopsis>
  449. <syntax>
  450. <parameter name="queuename" required="true" />
  451. <parameter name="uniqueid" required="true" />
  452. <parameter name="agent" required="true" />
  453. <parameter name="event" required="true" />
  454. <parameter name="additionalinfo" />
  455. </syntax>
  456. <description>
  457. <para>Allows you to write your own events into the queue log.</para>
  458. <para>Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)</para>
  459. </description>
  460. <see-also>
  461. <ref type="application">Queue</ref>
  462. <ref type="application">QueueLog</ref>
  463. <ref type="application">AddQueueMember</ref>
  464. <ref type="application">RemoveQueueMember</ref>
  465. <ref type="application">PauseQueueMember</ref>
  466. <ref type="application">UnpauseQueueMember</ref>
  467. <ref type="function">QUEUE_VARIABLES</ref>
  468. <ref type="function">QUEUE_MEMBER</ref>
  469. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  470. <ref type="function">QUEUE_EXISTS</ref>
  471. <ref type="function">QUEUE_WAITING_COUNT</ref>
  472. <ref type="function">QUEUE_MEMBER_LIST</ref>
  473. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  474. </see-also>
  475. </application>
  476. <function name="QUEUE_VARIABLES" language="en_US">
  477. <synopsis>
  478. Return Queue information in variables.
  479. </synopsis>
  480. <syntax>
  481. <parameter name="queuename" required="true">
  482. <enumlist>
  483. <enum name="QUEUEMAX">
  484. <para>Maxmimum number of calls allowed.</para>
  485. </enum>
  486. <enum name="QUEUESTRATEGY">
  487. <para>The strategy of the queue.</para>
  488. </enum>
  489. <enum name="QUEUECALLS">
  490. <para>Number of calls currently in the queue.</para>
  491. </enum>
  492. <enum name="QUEUEHOLDTIME">
  493. <para>Current average hold time.</para>
  494. </enum>
  495. <enum name="QUEUECOMPLETED">
  496. <para>Number of completed calls for the queue.</para>
  497. </enum>
  498. <enum name="QUEUEABANDONED">
  499. <para>Number of abandoned calls.</para>
  500. </enum>
  501. <enum name="QUEUESRVLEVEL">
  502. <para>Queue service level.</para>
  503. </enum>
  504. <enum name="QUEUESRVLEVELPERF">
  505. <para>Current service level performance.</para>
  506. </enum>
  507. </enumlist>
  508. </parameter>
  509. </syntax>
  510. <description>
  511. <para>Makes the following queue variables available.</para>
  512. <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
  513. </description>
  514. <see-also>
  515. <ref type="application">Queue</ref>
  516. <ref type="application">QueueLog</ref>
  517. <ref type="application">AddQueueMember</ref>
  518. <ref type="application">RemoveQueueMember</ref>
  519. <ref type="application">PauseQueueMember</ref>
  520. <ref type="application">UnpauseQueueMember</ref>
  521. <ref type="function">QUEUE_VARIABLES</ref>
  522. <ref type="function">QUEUE_MEMBER</ref>
  523. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  524. <ref type="function">QUEUE_EXISTS</ref>
  525. <ref type="function">QUEUE_WAITING_COUNT</ref>
  526. <ref type="function">QUEUE_MEMBER_LIST</ref>
  527. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  528. </see-also>
  529. </function>
  530. <function name="QUEUE_MEMBER" language="en_US">
  531. <synopsis>
  532. Count number of members answering a queue.
  533. </synopsis>
  534. <syntax>
  535. <parameter name="queuename" required="false" />
  536. <parameter name="option" required="true">
  537. <enumlist>
  538. <enum name="logged">
  539. <para>Returns the number of logged-in members for the specified queue.</para>
  540. </enum>
  541. <enum name="free">
  542. <para>Returns the number of logged-in members for the specified queue that either can take calls or are currently wrapping up after a previous call.</para>
  543. </enum>
  544. <enum name="ready">
  545. <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
  546. </enum>
  547. <enum name="count">
  548. <para>Returns the total number of members for the specified queue.</para>
  549. </enum>
  550. <enum name="penalty">
  551. <para>Gets or sets queue member penalty. If
  552. <replaceable>queuename</replaceable> is not specified
  553. when setting the penalty then the penalty is set in all queues
  554. the interface is a member.</para>
  555. </enum>
  556. <enum name="paused">
  557. <para>Gets or sets queue member paused status. If
  558. <replaceable>queuename</replaceable> is not specified
  559. when setting the paused status then the paused status is set
  560. in all queues the interface is a member.</para>
  561. </enum>
  562. <enum name="ringinuse">
  563. <para>Gets or sets queue member ringinuse. If
  564. <replaceable>queuename</replaceable> is not specified
  565. when setting ringinuse then ringinuse is set
  566. in all queues the interface is a member.</para>
  567. </enum>
  568. </enumlist>
  569. </parameter>
  570. <parameter name="interface" required="false" />
  571. </syntax>
  572. <description>
  573. <para>Allows access to queue counts [R] and member information [R/W].</para>
  574. <para><replaceable>queuename</replaceable> is required for all read operations.</para>
  575. <para><replaceable>interface</replaceable> is required for all member operations.</para>
  576. </description>
  577. <see-also>
  578. <ref type="application">Queue</ref>
  579. <ref type="application">QueueLog</ref>
  580. <ref type="application">AddQueueMember</ref>
  581. <ref type="application">RemoveQueueMember</ref>
  582. <ref type="application">PauseQueueMember</ref>
  583. <ref type="application">UnpauseQueueMember</ref>
  584. <ref type="function">QUEUE_VARIABLES</ref>
  585. <ref type="function">QUEUE_MEMBER</ref>
  586. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  587. <ref type="function">QUEUE_EXISTS</ref>
  588. <ref type="function">QUEUE_WAITING_COUNT</ref>
  589. <ref type="function">QUEUE_MEMBER_LIST</ref>
  590. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  591. </see-also>
  592. </function>
  593. <function name="QUEUE_MEMBER_COUNT" language="en_US">
  594. <synopsis>
  595. Count number of members answering a queue.
  596. </synopsis>
  597. <syntax>
  598. <parameter name="queuename" required="true" />
  599. </syntax>
  600. <description>
  601. <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
  602. <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
  603. </description>
  604. <see-also>
  605. <ref type="application">Queue</ref>
  606. <ref type="application">QueueLog</ref>
  607. <ref type="application">AddQueueMember</ref>
  608. <ref type="application">RemoveQueueMember</ref>
  609. <ref type="application">PauseQueueMember</ref>
  610. <ref type="application">UnpauseQueueMember</ref>
  611. <ref type="function">QUEUE_VARIABLES</ref>
  612. <ref type="function">QUEUE_MEMBER</ref>
  613. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  614. <ref type="function">QUEUE_EXISTS</ref>
  615. <ref type="function">QUEUE_WAITING_COUNT</ref>
  616. <ref type="function">QUEUE_MEMBER_LIST</ref>
  617. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  618. </see-also>
  619. </function>
  620. <function name="QUEUE_EXISTS" language="en_US">
  621. <synopsis>
  622. Check if a named queue exists on this server
  623. </synopsis>
  624. <syntax>
  625. <parameter name="queuename" />
  626. </syntax>
  627. <description>
  628. <para>Returns 1 if the specified queue exists, 0 if it does not</para>
  629. </description>
  630. <see-also>
  631. <ref type="application">Queue</ref>
  632. <ref type="application">QueueLog</ref>
  633. <ref type="application">AddQueueMember</ref>
  634. <ref type="application">RemoveQueueMember</ref>
  635. <ref type="application">PauseQueueMember</ref>
  636. <ref type="application">UnpauseQueueMember</ref>
  637. <ref type="function">QUEUE_VARIABLES</ref>
  638. <ref type="function">QUEUE_MEMBER</ref>
  639. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  640. <ref type="function">QUEUE_EXISTS</ref>
  641. <ref type="function">QUEUE_WAITING_COUNT</ref>
  642. <ref type="function">QUEUE_MEMBER_LIST</ref>
  643. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  644. </see-also>
  645. </function>
  646. <function name="QUEUE_WAITING_COUNT" language="en_US">
  647. <synopsis>
  648. Count number of calls currently waiting in a queue.
  649. </synopsis>
  650. <syntax>
  651. <parameter name="queuename" />
  652. </syntax>
  653. <description>
  654. <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
  655. </description>
  656. <see-also>
  657. <ref type="application">Queue</ref>
  658. <ref type="application">QueueLog</ref>
  659. <ref type="application">AddQueueMember</ref>
  660. <ref type="application">RemoveQueueMember</ref>
  661. <ref type="application">PauseQueueMember</ref>
  662. <ref type="application">UnpauseQueueMember</ref>
  663. <ref type="function">QUEUE_VARIABLES</ref>
  664. <ref type="function">QUEUE_MEMBER</ref>
  665. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  666. <ref type="function">QUEUE_EXISTS</ref>
  667. <ref type="function">QUEUE_WAITING_COUNT</ref>
  668. <ref type="function">QUEUE_MEMBER_LIST</ref>
  669. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  670. </see-also>
  671. </function>
  672. <function name="QUEUE_MEMBER_LIST" language="en_US">
  673. <synopsis>
  674. Returns a list of interfaces on a queue.
  675. </synopsis>
  676. <syntax>
  677. <parameter name="queuename" required="true" />
  678. </syntax>
  679. <description>
  680. <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
  681. </description>
  682. <see-also>
  683. <ref type="application">Queue</ref>
  684. <ref type="application">QueueLog</ref>
  685. <ref type="application">AddQueueMember</ref>
  686. <ref type="application">RemoveQueueMember</ref>
  687. <ref type="application">PauseQueueMember</ref>
  688. <ref type="application">UnpauseQueueMember</ref>
  689. <ref type="function">QUEUE_VARIABLES</ref>
  690. <ref type="function">QUEUE_MEMBER</ref>
  691. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  692. <ref type="function">QUEUE_EXISTS</ref>
  693. <ref type="function">QUEUE_WAITING_COUNT</ref>
  694. <ref type="function">QUEUE_MEMBER_LIST</ref>
  695. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  696. </see-also>
  697. </function>
  698. <function name="QUEUE_MEMBER_PENALTY" language="en_US">
  699. <synopsis>
  700. Gets or sets queue members penalty.
  701. </synopsis>
  702. <syntax>
  703. <parameter name="queuename" required="true" />
  704. <parameter name="interface" required="true" />
  705. </syntax>
  706. <description>
  707. <para>Gets or sets queue members penalty.</para>
  708. <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
  709. </description>
  710. <see-also>
  711. <ref type="application">Queue</ref>
  712. <ref type="application">QueueLog</ref>
  713. <ref type="application">AddQueueMember</ref>
  714. <ref type="application">RemoveQueueMember</ref>
  715. <ref type="application">PauseQueueMember</ref>
  716. <ref type="application">UnpauseQueueMember</ref>
  717. <ref type="function">QUEUE_VARIABLES</ref>
  718. <ref type="function">QUEUE_MEMBER</ref>
  719. <ref type="function">QUEUE_MEMBER_COUNT</ref>
  720. <ref type="function">QUEUE_EXISTS</ref>
  721. <ref type="function">QUEUE_WAITING_COUNT</ref>
  722. <ref type="function">QUEUE_MEMBER_LIST</ref>
  723. <ref type="function">QUEUE_MEMBER_PENALTY</ref>
  724. </see-also>
  725. </function>
  726. <manager name="Queues" language="en_US">
  727. <synopsis>
  728. Queues.
  729. </synopsis>
  730. <syntax>
  731. </syntax>
  732. <description>
  733. <para>Show queues information.</para>
  734. </description>
  735. </manager>
  736. <manager name="QueueStatus" language="en_US">
  737. <synopsis>
  738. Show queue status.
  739. </synopsis>
  740. <syntax>
  741. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  742. <parameter name="Queue">
  743. <para>Limit the response to the status of the specified queue.</para>
  744. </parameter>
  745. <parameter name="Member">
  746. <para>Limit the response to the status of the specified member.</para>
  747. </parameter>
  748. </syntax>
  749. <description>
  750. <para>Check the status of one or more queues.</para>
  751. </description>
  752. </manager>
  753. <manager name="QueueSummary" language="en_US">
  754. <synopsis>
  755. Show queue summary.
  756. </synopsis>
  757. <syntax>
  758. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  759. <parameter name="Queue">
  760. <para>Queue for which the summary is requested.</para>
  761. </parameter>
  762. </syntax>
  763. <description>
  764. <para>Request the manager to send a QueueSummary event.</para>
  765. </description>
  766. </manager>
  767. <manager name="QueueAdd" language="en_US">
  768. <synopsis>
  769. Add interface to queue.
  770. </synopsis>
  771. <syntax>
  772. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  773. <parameter name="Queue" required="true">
  774. <para>Queue's name.</para>
  775. </parameter>
  776. <parameter name="Interface" required="true">
  777. <para>The name of the interface (tech/name) to add to the queue.</para>
  778. </parameter>
  779. <parameter name="Penalty">
  780. <para>A penalty (number) to apply to this member. Asterisk will distribute calls to members with higher penalties only after attempting to distribute calls to those with lower penalty.</para>
  781. </parameter>
  782. <parameter name="Paused">
  783. <para>To pause or not the member initially (true/false or 1/0).</para>
  784. </parameter>
  785. <parameter name="MemberName">
  786. <para>Text alias for the interface.</para>
  787. </parameter>
  788. <parameter name="StateInterface" />
  789. </syntax>
  790. <description>
  791. </description>
  792. </manager>
  793. <manager name="QueueRemove" language="en_US">
  794. <synopsis>
  795. Remove interface from queue.
  796. </synopsis>
  797. <syntax>
  798. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  799. <parameter name="Queue" required="true">
  800. <para>The name of the queue to take action on.</para>
  801. </parameter>
  802. <parameter name="Interface" required="true">
  803. <para>The interface (tech/name) to remove from queue.</para>
  804. </parameter>
  805. </syntax>
  806. <description>
  807. </description>
  808. </manager>
  809. <manager name="QueuePause" language="en_US">
  810. <synopsis>
  811. Makes a queue member temporarily unavailable.
  812. </synopsis>
  813. <syntax>
  814. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  815. <parameter name="Interface" required="true">
  816. <para>The name of the interface (tech/name) to pause or unpause.</para>
  817. </parameter>
  818. <parameter name="Paused" required="true">
  819. <para>Pause or unpause the interface. Set to 'true' to pause the member or 'false' to unpause.</para>
  820. </parameter>
  821. <parameter name="Queue">
  822. <para>The name of the queue in which to pause or unpause this member. If not specified, the member will be paused or unpaused in all the queues it is a member of.</para>
  823. </parameter>
  824. <parameter name="Reason">
  825. <para>Text description, returned in the event QueueMemberPaused.</para>
  826. </parameter>
  827. </syntax>
  828. <description>
  829. <para>Pause or unpause a member in a queue.</para>
  830. </description>
  831. </manager>
  832. <manager name="QueueLog" language="en_US">
  833. <synopsis>
  834. Adds custom entry in queue_log.
  835. </synopsis>
  836. <syntax>
  837. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  838. <parameter name="Queue" required="true" />
  839. <parameter name="Event" required="true" />
  840. <parameter name="Uniqueid" />
  841. <parameter name="Interface" />
  842. <parameter name="Message" />
  843. </syntax>
  844. <description>
  845. </description>
  846. </manager>
  847. <manager name="QueuePenalty" language="en_US">
  848. <synopsis>
  849. Set the penalty for a queue member.
  850. </synopsis>
  851. <syntax>
  852. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  853. <parameter name="Interface" required="true">
  854. <para>The interface (tech/name) of the member whose penalty to change.</para>
  855. </parameter>
  856. <parameter name="Penalty" required="true">
  857. <para>The new penalty (number) for the member. Must be nonnegative.</para>
  858. </parameter>
  859. <parameter name="Queue">
  860. <para>If specified, only set the penalty for the member of this queue. Otherwise, set the penalty for the member in all queues to which the member belongs.</para>
  861. </parameter>
  862. </syntax>
  863. <description>
  864. <para>Change the penalty of a queue member</para>
  865. </description>
  866. </manager>
  867. <manager name="QueueMemberRingInUse" language="en_US">
  868. <synopsis>
  869. Set the ringinuse value for a queue member.
  870. </synopsis>
  871. <syntax>
  872. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  873. <parameter name="Interface" required="true" />
  874. <parameter name="RingInUse" required="true" />
  875. <parameter name="Queue" />
  876. </syntax>
  877. <description>
  878. </description>
  879. </manager>
  880. <manager name="QueueRule" language="en_US">
  881. <synopsis>
  882. Queue Rules.
  883. </synopsis>
  884. <syntax>
  885. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  886. <parameter name="Rule">
  887. <para>The name of the rule in queuerules.conf whose contents to list.</para>
  888. </parameter>
  889. </syntax>
  890. <description>
  891. <para>List queue rules defined in queuerules.conf</para>
  892. </description>
  893. </manager>
  894. <manager name="QueueReload" language="en_US">
  895. <synopsis>
  896. Reload a queue, queues, or any sub-section of a queue or queues.
  897. </synopsis>
  898. <syntax>
  899. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  900. <parameter name="Queue">
  901. <para>The name of the queue to take action on. If no queue name is specified, then all queues are affected.</para>
  902. </parameter>
  903. <parameter name="Members">
  904. <para>Whether to reload the queue's members.</para>
  905. <enumlist>
  906. <enum name="yes" />
  907. <enum name="no" />
  908. </enumlist>
  909. </parameter>
  910. <parameter name="Rules">
  911. <para>Whether to reload queuerules.conf</para>
  912. <enumlist>
  913. <enum name="yes" />
  914. <enum name="no" />
  915. </enumlist>
  916. </parameter>
  917. <parameter name="Parameters">
  918. <para>Whether to reload the other queue options.</para>
  919. <enumlist>
  920. <enum name="yes" />
  921. <enum name="no" />
  922. </enumlist>
  923. </parameter>
  924. </syntax>
  925. <description>
  926. </description>
  927. </manager>
  928. <manager name="QueueReset" language="en_US">
  929. <synopsis>
  930. Reset queue statistics.
  931. </synopsis>
  932. <syntax>
  933. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  934. <parameter name="Queue">
  935. <para>The name of the queue on which to reset statistics.</para>
  936. </parameter>
  937. </syntax>
  938. <description>
  939. <para>Reset the statistics for a queue.</para>
  940. </description>
  941. </manager>
  942. <managerEvent language="en_US" name="QueueMemberStatus">
  943. <managerEventInstance class="EVENT_FLAG_AGENT">
  944. <synopsis>Raised when a Queue member's status has changed.</synopsis>
  945. <syntax>
  946. <parameter name="Queue">
  947. <para>The name of the queue.</para>
  948. </parameter>
  949. <parameter name="MemberName">
  950. <para>The name of the queue member.</para>
  951. </parameter>
  952. <parameter name="Interface">
  953. <para>The queue member's channel technology or location.</para>
  954. </parameter>
  955. <parameter name="StateInterface">
  956. <para>Channel technology or location from which to read device state changes.</para>
  957. </parameter>
  958. <parameter name="Membership">
  959. <enumlist>
  960. <enum name="dynamic"/>
  961. <enum name="realtime"/>
  962. <enum name="static"/>
  963. </enumlist>
  964. </parameter>
  965. <parameter name="Penalty">
  966. <para>The penalty associated with the queue member.</para>
  967. </parameter>
  968. <parameter name="CallsTaken">
  969. <para>The number of calls this queue member has serviced.</para>
  970. </parameter>
  971. <parameter name="LastCall">
  972. <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
  973. </parameter>
  974. <parameter name="InCall">
  975. <para>Set to 1 if member is in call. Set to 0 after LastCall time is updated.</para>
  976. <enumlist>
  977. <enum name="0"/>
  978. <enum name="1"/>
  979. </enumlist>
  980. </parameter>
  981. <parameter name="Status">
  982. <para>The numeric device state status of the queue member.</para>
  983. <enumlist>
  984. <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
  985. <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
  986. <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
  987. <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
  988. <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
  989. <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
  990. <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
  991. <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
  992. <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
  993. </enumlist>
  994. </parameter>
  995. <parameter name="Paused">
  996. <enumlist>
  997. <enum name="0"/>
  998. <enum name="1"/>
  999. </enumlist>
  1000. </parameter>
  1001. <parameter name="PausedReason">
  1002. <para>If set when paused, the reason the queue member was paused.</para>
  1003. </parameter>
  1004. <parameter name="Ringinuse">
  1005. <enumlist>
  1006. <enum name="0"/>
  1007. <enum name="1"/>
  1008. </enumlist>
  1009. </parameter>
  1010. </syntax>
  1011. </managerEventInstance>
  1012. </managerEvent>
  1013. <managerEvent language="en_US" name="QueueMemberAdded">
  1014. <managerEventInstance class="EVENT_FLAG_AGENT">
  1015. <synopsis>Raised when a member is added to the queue.</synopsis>
  1016. <syntax>
  1017. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
  1018. </syntax>
  1019. <see-also>
  1020. <ref type="managerEvent">QueueMemberRemoved</ref>
  1021. <ref type="application">AddQueueMember</ref>
  1022. </see-also>
  1023. </managerEventInstance>
  1024. </managerEvent>
  1025. <managerEvent language="en_US" name="QueueMemberRemoved">
  1026. <managerEventInstance class="EVENT_FLAG_AGENT">
  1027. <synopsis>Raised when a member is removed from the queue.</synopsis>
  1028. <syntax>
  1029. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
  1030. </syntax>
  1031. <see-also>
  1032. <ref type="managerEvent">QueueMemberAdded</ref>
  1033. <ref type="application">RemoveQueueMember</ref>
  1034. </see-also>
  1035. </managerEventInstance>
  1036. </managerEvent>
  1037. <managerEvent language="en_US" name="QueueMemberPause">
  1038. <managerEventInstance class="EVENT_FLAG_AGENT">
  1039. <synopsis>Raised when a member is paused/unpaused in the queue.</synopsis>
  1040. <syntax>
  1041. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
  1042. <parameter name="Reason">
  1043. <para>The reason a member was paused.</para>
  1044. </parameter>
  1045. </syntax>
  1046. <see-also>
  1047. <ref type="application">PauseQueueMember</ref>
  1048. <ref type="application">UnPauseQueueMember</ref>
  1049. </see-also>
  1050. </managerEventInstance>
  1051. </managerEvent>
  1052. <managerEvent language="en_US" name="QueueMemberPenalty">
  1053. <managerEventInstance class="EVENT_FLAG_AGENT">
  1054. <synopsis>Raised when a member's penalty is changed.</synopsis>
  1055. <syntax>
  1056. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
  1057. </syntax>
  1058. <see-also>
  1059. <ref type="function">QUEUE_MEMBER</ref>
  1060. </see-also>
  1061. </managerEventInstance>
  1062. </managerEvent>
  1063. <managerEvent language="en_US" name="QueueMemberRinginuse">
  1064. <managerEventInstance class="EVENT_FLAG_AGENT">
  1065. <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
  1066. <syntax>
  1067. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
  1068. </syntax>
  1069. <see-also>
  1070. <ref type="function">QUEUE_MEMBER</ref>
  1071. </see-also>
  1072. </managerEventInstance>
  1073. </managerEvent>
  1074. <managerEvent language="en_US" name="QueueCallerJoin">
  1075. <managerEventInstance class="EVENT_FLAG_AGENT">
  1076. <synopsis>Raised when a caller joins a Queue.</synopsis>
  1077. <syntax>
  1078. <channel_snapshot/>
  1079. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1080. <parameter name="Position">
  1081. <para>This channel's current position in the queue.</para>
  1082. </parameter>
  1083. <parameter name="Count">
  1084. <para>The total number of channels in the queue.</para>
  1085. </parameter>
  1086. </syntax>
  1087. <see-also>
  1088. <ref type="managerEvent">QueueCallerLeave</ref>
  1089. <ref type="application">Queue</ref>
  1090. </see-also>
  1091. </managerEventInstance>
  1092. </managerEvent>
  1093. <managerEvent language="en_US" name="QueueCallerLeave">
  1094. <managerEventInstance class="EVENT_FLAG_AGENT">
  1095. <synopsis>Raised when a caller leaves a Queue.</synopsis>
  1096. <syntax>
  1097. <channel_snapshot/>
  1098. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1099. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Count'])" />
  1100. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
  1101. </syntax>
  1102. <see-also>
  1103. <ref type="managerEvent">QueueCallerJoin</ref>
  1104. </see-also>
  1105. </managerEventInstance>
  1106. </managerEvent>
  1107. <managerEvent language="en_US" name="QueueCallerAbandon">
  1108. <managerEventInstance class="EVENT_FLAG_AGENT">
  1109. <synopsis>Raised when a caller abandons the queue.</synopsis>
  1110. <syntax>
  1111. <channel_snapshot/>
  1112. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1113. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
  1114. <parameter name="OriginalPosition">
  1115. <para>The channel's original position in the queue.</para>
  1116. </parameter>
  1117. <parameter name="HoldTime">
  1118. <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
  1119. </parameter>
  1120. </syntax>
  1121. </managerEventInstance>
  1122. </managerEvent>
  1123. <managerEvent language="en_US" name="AgentCalled">
  1124. <managerEventInstance class="EVENT_FLAG_AGENT">
  1125. <synopsis>Raised when an queue member is notified of a caller in the queue.</synopsis>
  1126. <syntax>
  1127. <channel_snapshot/>
  1128. <channel_snapshot prefix="Dest"/>
  1129. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1130. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
  1131. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
  1132. </syntax>
  1133. <see-also>
  1134. <ref type="managerEvent">AgentRingNoAnswer</ref>
  1135. <ref type="managerEvent">AgentComplete</ref>
  1136. <ref type="managerEvent">AgentConnect</ref>
  1137. </see-also>
  1138. </managerEventInstance>
  1139. </managerEvent>
  1140. <managerEvent language="en_US" name="AgentRingNoAnswer">
  1141. <managerEventInstance class="EVENT_FLAG_AGENT">
  1142. <synopsis>Raised when a queue member is notified of a caller in the queue and fails to answer.</synopsis>
  1143. <syntax>
  1144. <channel_snapshot/>
  1145. <channel_snapshot prefix="Dest"/>
  1146. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1147. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
  1148. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
  1149. <parameter name="RingTime">
  1150. <para>The time the queue member was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
  1151. </parameter>
  1152. </syntax>
  1153. <see-also>
  1154. <ref type="managerEvent">AgentCalled</ref>
  1155. </see-also>
  1156. </managerEventInstance>
  1157. </managerEvent>
  1158. <managerEvent language="en_US" name="AgentComplete">
  1159. <managerEventInstance class="EVENT_FLAG_AGENT">
  1160. <synopsis>Raised when a queue member has finished servicing a caller in the queue.</synopsis>
  1161. <syntax>
  1162. <channel_snapshot/>
  1163. <channel_snapshot prefix="Dest"/>
  1164. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1165. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
  1166. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
  1167. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
  1168. <parameter name="TalkTime">
  1169. <para>The time the queue member talked with the caller in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
  1170. </parameter>
  1171. <parameter name="Reason">
  1172. <enumlist>
  1173. <enum name="caller"/>
  1174. <enum name="agent"/>
  1175. <enum name="transfer"/>
  1176. </enumlist>
  1177. </parameter>
  1178. </syntax>
  1179. <see-also>
  1180. <ref type="managerEvent">AgentCalled</ref>
  1181. <ref type="managerEvent">AgentConnect</ref>
  1182. </see-also>
  1183. </managerEventInstance>
  1184. </managerEvent>
  1185. <managerEvent language="en_US" name="AgentDump">
  1186. <managerEventInstance class="EVENT_FLAG_AGENT">
  1187. <synopsis>Raised when a queue member hangs up on a caller in the queue.</synopsis>
  1188. <syntax>
  1189. <channel_snapshot/>
  1190. <channel_snapshot prefix="Dest"/>
  1191. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1192. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
  1193. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
  1194. </syntax>
  1195. <see-also>
  1196. <ref type="managerEvent">AgentCalled</ref>
  1197. <ref type="managerEvent">AgentConnect</ref>
  1198. </see-also>
  1199. </managerEventInstance>
  1200. </managerEvent>
  1201. <managerEvent language="en_US" name="AgentConnect">
  1202. <managerEventInstance class="EVENT_FLAG_AGENT">
  1203. <synopsis>Raised when a queue member answers and is bridged to a caller in the queue.</synopsis>
  1204. <syntax>
  1205. <channel_snapshot/>
  1206. <channel_snapshot prefix="Dest"/>
  1207. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
  1208. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
  1209. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
  1210. <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
  1211. <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
  1212. </syntax>
  1213. <see-also>
  1214. <ref type="managerEvent">AgentCalled</ref>
  1215. <ref type="managerEvent">AgentComplete</ref>
  1216. <ref type="managerEvent">AgentDump</ref>
  1217. </see-also>
  1218. </managerEventInstance>
  1219. </managerEvent>
  1220. ***/
  1221. enum {
  1222. OPT_MARK_AS_ANSWERED = (1 << 0),
  1223. OPT_GO_ON = (1 << 1),
  1224. OPT_DATA_QUALITY = (1 << 2),
  1225. OPT_CALLEE_GO_ON = (1 << 3),
  1226. OPT_CALLEE_HANGUP = (1 << 4),
  1227. OPT_CALLER_HANGUP = (1 << 5),
  1228. OPT_IGNORE_CALL_FW = (1 << 6),
  1229. OPT_IGNORE_CONNECTEDLINE = (1 << 7),
  1230. OPT_CALLEE_PARK = (1 << 8),
  1231. OPT_CALLER_PARK = (1 << 9),
  1232. OPT_NO_RETRY = (1 << 10),
  1233. OPT_RINGING = (1 << 11),
  1234. OPT_RING_WHEN_RINGING = (1 << 12),
  1235. OPT_CALLEE_TRANSFER = (1 << 13),
  1236. OPT_CALLER_TRANSFER = (1 << 14),
  1237. OPT_CALLEE_AUTOMIXMON = (1 << 15),
  1238. OPT_CALLER_AUTOMIXMON = (1 << 16),
  1239. OPT_CALLEE_AUTOMON = (1 << 17),
  1240. OPT_CALLER_AUTOMON = (1 << 18),
  1241. };
  1242. enum {
  1243. OPT_ARG_CALLEE_GO_ON = 0,
  1244. /* note: this entry _MUST_ be the last one in the enum */
  1245. OPT_ARG_ARRAY_SIZE
  1246. };
  1247. AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
  1248. AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),
  1249. AST_APP_OPTION('c', OPT_GO_ON),
  1250. AST_APP_OPTION('d', OPT_DATA_QUALITY),
  1251. AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
  1252. AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
  1253. AST_APP_OPTION('H', OPT_CALLER_HANGUP),
  1254. AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),
  1255. AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
  1256. AST_APP_OPTION('k', OPT_CALLEE_PARK),
  1257. AST_APP_OPTION('K', OPT_CALLER_PARK),
  1258. AST_APP_OPTION('n', OPT_NO_RETRY),
  1259. AST_APP_OPTION('r', OPT_RINGING),
  1260. AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),
  1261. AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
  1262. AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
  1263. AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),
  1264. AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),
  1265. AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),
  1266. AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
  1267. END_OPTIONS);
  1268. enum {
  1269. QUEUE_STRATEGY_RINGALL = 0,
  1270. QUEUE_STRATEGY_LEASTRECENT,
  1271. QUEUE_STRATEGY_FEWESTCALLS,
  1272. QUEUE_STRATEGY_RANDOM,
  1273. QUEUE_STRATEGY_RRMEMORY,
  1274. QUEUE_STRATEGY_LINEAR,
  1275. QUEUE_STRATEGY_WRANDOM,
  1276. QUEUE_STRATEGY_RRORDERED,
  1277. };
  1278. enum {
  1279. QUEUE_AUTOPAUSE_OFF = 0,
  1280. QUEUE_AUTOPAUSE_ON,
  1281. QUEUE_AUTOPAUSE_ALL
  1282. };
  1283. enum queue_reload_mask {
  1284. QUEUE_RELOAD_PARAMETERS = (1 << 0),
  1285. QUEUE_RELOAD_MEMBER = (1 << 1),
  1286. QUEUE_RELOAD_RULES = (1 << 2),
  1287. QUEUE_RESET_STATS = (1 << 3),
  1288. };
  1289. static const struct strategy {
  1290. int strategy;
  1291. const char *name;
  1292. } strategies[] = {
  1293. { QUEUE_STRATEGY_RINGALL, "ringall" },
  1294. { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
  1295. { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
  1296. { QUEUE_STRATEGY_RANDOM, "random" },
  1297. { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
  1298. { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
  1299. { QUEUE_STRATEGY_LINEAR, "linear" },
  1300. { QUEUE_STRATEGY_WRANDOM, "wrandom"},
  1301. { QUEUE_STRATEGY_RRORDERED, "rrordered"},
  1302. };
  1303. static const struct autopause {
  1304. int autopause;
  1305. const char *name;
  1306. } autopausesmodes [] = {
  1307. { QUEUE_AUTOPAUSE_OFF,"no" },
  1308. { QUEUE_AUTOPAUSE_ON, "yes" },
  1309. { QUEUE_AUTOPAUSE_ALL,"all" },
  1310. };
  1311. #define DEFAULT_RETRY 5
  1312. #define DEFAULT_TIMEOUT 15
  1313. #define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
  1314. #define MAX_PERIODIC_ANNOUNCEMENTS 10 /*!< The maximum periodic announcements we can have */
  1315. /*!
  1316. * \brief The minimum number of seconds between position announcements.
  1317. * \note The default value of 15 provides backwards compatibility.
  1318. */
  1319. #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15
  1320. #define MAX_QUEUE_BUCKETS 53
  1321. #define RES_OKAY 0 /*!< Action completed */
  1322. #define RES_EXISTS (-1) /*!< Entry already exists */
  1323. #define RES_OUTOFMEMORY (-2) /*!< Out of memory */
  1324. #define RES_NOSUCHQUEUE (-3) /*!< No such queue */
  1325. #define RES_NOT_DYNAMIC (-4) /*!< Member is not dynamic */
  1326. static char *app = "Queue";
  1327. static char *app_aqm = "AddQueueMember" ;
  1328. static char *app_rqm = "RemoveQueueMember" ;
  1329. static char *app_pqm = "PauseQueueMember" ;
  1330. static char *app_upqm = "UnpauseQueueMember" ;
  1331. static char *app_ql = "QueueLog" ;
  1332. /*! \brief Persistent Members astdb family */
  1333. static const char * const pm_family = "Queue/PersistentMembers";
  1334. /*! \brief queues.conf [general] option */
  1335. static int queue_persistent_members = 0;
  1336. /*! \brief queues.conf per-queue weight option */
  1337. static int use_weight = 0;
  1338. /*! \brief queues.conf [general] option */
  1339. static int autofill_default = 1;
  1340. /*! \brief queues.conf [general] option */
  1341. static int montype_default = 0;
  1342. /*! \brief queues.conf [general] option */
  1343. static int shared_lastcall = 1;
  1344. /*! \brief queuesrules.conf [general] option */
  1345. static int realtime_rules = 0;
  1346. /*! \brief Subscription to device state change messages */
  1347. static struct stasis_subscription *device_state_sub;
  1348. /*! \brief queues.conf [general] option */
  1349. static int update_cdr = 0;
  1350. /*! \brief queues.conf [general] option */
  1351. static int negative_penalty_invalid = 0;
  1352. /*! \brief queues.conf [general] option */
  1353. static int log_membername_as_agent = 0;
  1354. /*! \brief name of the ringinuse field in the realtime database */
  1355. static char *realtime_ringinuse_field;
  1356. enum queue_result {
  1357. QUEUE_UNKNOWN = 0,
  1358. QUEUE_TIMEOUT = 1,
  1359. QUEUE_JOINEMPTY = 2,
  1360. QUEUE_LEAVEEMPTY = 3,
  1361. QUEUE_JOINUNAVAIL = 4,
  1362. QUEUE_LEAVEUNAVAIL = 5,
  1363. QUEUE_FULL = 6,
  1364. QUEUE_CONTINUE = 7,
  1365. };
  1366. static const struct {
  1367. enum queue_result id;
  1368. char *text;
  1369. } queue_results[] = {
  1370. { QUEUE_UNKNOWN, "UNKNOWN" },
  1371. { QUEUE_TIMEOUT, "TIMEOUT" },
  1372. { QUEUE_JOINEMPTY,"JOINEMPTY" },
  1373. { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
  1374. { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
  1375. { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
  1376. { QUEUE_FULL, "FULL" },
  1377. { QUEUE_CONTINUE, "CONTINUE" },
  1378. };
  1379. enum queue_timeout_priority {
  1380. TIMEOUT_PRIORITY_APP,
  1381. TIMEOUT_PRIORITY_CONF,
  1382. };
  1383. /*! \brief We define a custom "local user" structure because we
  1384. * use it not only for keeping track of what is in use but
  1385. * also for keeping track of who we're dialing.
  1386. *
  1387. * There are two "links" defined in this structure, q_next and call_next.
  1388. * q_next links ALL defined callattempt structures into a linked list. call_next is
  1389. * a link which allows for a subset of the callattempts to be traversed. This subset
  1390. * is used in wait_for_answer so that irrelevant callattempts are not traversed. This
  1391. * also is helpful so that queue logs are always accurate in the case where a call to
  1392. * a member times out, especially if using the ringall strategy.
  1393. */
  1394. struct callattempt {
  1395. struct callattempt *q_next;
  1396. struct callattempt *call_next;
  1397. struct ast_channel *chan;
  1398. char interface[256]; /*!< An Asterisk dial string (not a channel name) */
  1399. int metric;
  1400. time_t lastcall;
  1401. struct call_queue *lastqueue;
  1402. struct member *member;
  1403. /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
  1404. struct ast_party_connected_line connected;
  1405. /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
  1406. unsigned int pending_connected_update:1;
  1407. /*! TRUE if the connected line update is blocked. */
  1408. unsigned int block_connected_update:1;
  1409. /*! TRUE if caller id is not available for connected line */
  1410. unsigned int dial_callerid_absent:1;
  1411. /*! TRUE if the call is still active */
  1412. unsigned int stillgoing:1;
  1413. struct ast_aoc_decoded *aoc_s_rate_list;
  1414. /*! Original channel name. Must be freed. Could be NULL if allocation failed. */
  1415. char *orig_chan_name;
  1416. };
  1417. struct queue_ent {
  1418. struct call_queue *parent; /*!< What queue is our parent */
  1419. char moh[MAX_MUSICCLASS]; /*!< Name of musiconhold to be used */
  1420. char announce[PATH_MAX]; /*!< Announcement to play for member when call is answered */
  1421. char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
  1422. char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
  1423. int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
  1424. int pos; /*!< Where we are in the queue */
  1425. int prio; /*!< Our priority */
  1426. int last_pos_said; /*!< Last position we told the user */
  1427. int ring_when_ringing; /*!< Should we only use ring indication when a channel is ringing? */
  1428. time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
  1429. int last_periodic_announce_sound; /*!< The last periodic announcement we made */
  1430. time_t last_pos; /*!< Last time we told the user their position */
  1431. int opos; /*!< Where we started in the queue */
  1432. int handled; /*!< Whether our call was handled */
  1433. int pending; /*!< Non-zero if we are attempting to call a member */
  1434. int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
  1435. int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
  1436. int linpos; /*!< If using linear strategy, what position are we at? */
  1437. int linwrapped; /*!< Is the linpos wrapped? */
  1438. time_t start; /*!< When we started holding */
  1439. time_t expire; /*!< When this entry should expire (time out of queue) */
  1440. int cancel_answered_elsewhere; /*!< Whether we should force the CAE flag on this call (C) option*/
  1441. struct ast_channel *chan; /*!< Our channel */
  1442. AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
  1443. struct penalty_rule *pr; /*!< Pointer to the next penalty rule to implement */
  1444. struct queue_ent *next; /*!< The next queue entry */
  1445. };
  1446. struct member {
  1447. char interface[AST_CHANNEL_NAME]; /*!< Technology/Location to dial to reach this member*/
  1448. char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
  1449. char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
  1450. char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
  1451. int state_id; /*!< Extension state callback id (if using hint) */
  1452. char membername[80]; /*!< Member name to use in queue logs */
  1453. int penalty; /*!< Are we a last resort? */
  1454. int calls; /*!< Number of calls serviced by this member */
  1455. int dynamic; /*!< Are we dynamically added? */
  1456. int realtime; /*!< Is this member realtime? */
  1457. int status; /*!< Status of queue member */
  1458. int paused; /*!< Are we paused (not accepting calls)? */
  1459. char reason_paused[80]; /*!< Reason of paused if member is paused */
  1460. int queuepos; /*!< In what order (pertains to certain strategies) should this member be called? */
  1461. int callcompletedinsl; /*!< Whether the current call was completed within service level */
  1462. time_t starttime; /*!< The time at which the member answered the current caller. */
  1463. time_t lastcall; /*!< When last successful call was hungup */
  1464. struct call_queue *lastqueue; /*!< Last queue we received a call */
  1465. unsigned int dead:1; /*!< Used to detect members deleted in realtime */
  1466. unsigned int delme:1; /*!< Flag to delete entry on reload */
  1467. char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
  1468. unsigned int ringinuse:1; /*!< Flag to ring queue members even if their status is 'inuse' */
  1469. };
  1470. enum empty_conditions {
  1471. QUEUE_EMPTY_PENALTY = (1 << 0),
  1472. QUEUE_EMPTY_PAUSED = (1 << 1),
  1473. QUEUE_EMPTY_INUSE = (1 << 2),
  1474. QUEUE_EMPTY_RINGING = (1 << 3),
  1475. QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
  1476. QUEUE_EMPTY_INVALID = (1 << 5),
  1477. QUEUE_EMPTY_UNKNOWN = (1 << 6),
  1478. QUEUE_EMPTY_WRAPUP = (1 << 7),
  1479. };
  1480. enum member_properties {
  1481. MEMBER_PENALTY = 0,
  1482. MEMBER_RINGINUSE = 1,
  1483. };
  1484. /* values used in multi-bit flags in call_queue */
  1485. #define ANNOUNCEHOLDTIME_ALWAYS 1
  1486. #define ANNOUNCEHOLDTIME_ONCE 2
  1487. #define QUEUE_EVENT_VARIABLES 3
  1488. struct penalty_rule {
  1489. int time; /*!< Number of seconds that need to pass before applying this rule */
  1490. int max_value; /*!< The amount specified in the penalty rule for max penalty */
  1491. int min_value; /*!< The amount specified in the penalty rule for min penalty */
  1492. int max_relative; /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
  1493. int min_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
  1494. AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */
  1495. };
  1496. #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
  1497. #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
  1498. #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
  1499. #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
  1500. struct call_queue {
  1501. AST_DECLARE_STRING_FIELDS(
  1502. /*! Queue name */
  1503. AST_STRING_FIELD(name);
  1504. /*! Music on Hold class */
  1505. AST_STRING_FIELD(moh);
  1506. /*! Announcement to play when call is answered */
  1507. AST_STRING_FIELD(announce);
  1508. /*! Exit context */
  1509. AST_STRING_FIELD(context);
  1510. /*! Macro to run upon member connection */
  1511. AST_STRING_FIELD(membermacro);
  1512. /*! Gosub to run upon member connection */
  1513. AST_STRING_FIELD(membergosub);
  1514. /*! Default rule to use if none specified in call to Queue() */
  1515. AST_STRING_FIELD(defaultrule);
  1516. /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
  1517. AST_STRING_FIELD(sound_next);
  1518. /*! Sound file: "There are currently" (def. queue-thereare) */
  1519. AST_STRING_FIELD(sound_thereare);
  1520. /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
  1521. AST_STRING_FIELD(sound_calls);
  1522. /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
  1523. AST_STRING_FIELD(queue_quantity1);
  1524. /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
  1525. AST_STRING_FIELD(queue_quantity2);
  1526. /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
  1527. AST_STRING_FIELD(sound_holdtime);
  1528. /*! Sound file: "minutes." (def. queue-minutes) */
  1529. AST_STRING_FIELD(sound_minutes);
  1530. /*! Sound file: "minute." (def. queue-minute) */
  1531. AST_STRING_FIELD(sound_minute);
  1532. /*! Sound file: "seconds." (def. queue-seconds) */
  1533. AST_STRING_FIELD(sound_seconds);
  1534. /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
  1535. AST_STRING_FIELD(sound_thanks);
  1536. /*! Sound file: Custom announce for caller, no default */
  1537. AST_STRING_FIELD(sound_callerannounce);
  1538. /*! Sound file: "Hold time" (def. queue-reporthold) */
  1539. AST_STRING_FIELD(sound_reporthold);
  1540. );
  1541. /*! Sound files: Custom announce, no default */
  1542. struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
  1543. unsigned int dead:1;
  1544. unsigned int ringinuse:1;
  1545. unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
  1546. unsigned int setinterfacevar:1;
  1547. unsigned int setqueuevar:1;
  1548. unsigned int setqueueentryvar:1;
  1549. unsigned int reportholdtime:1;
  1550. unsigned int wrapped:1;
  1551. unsigned int timeoutrestart:1;
  1552. unsigned int announceholdtime:2;
  1553. unsigned int announceposition:3;
  1554. int strategy:4;
  1555. unsigned int realtime:1;
  1556. unsigned int found:1;
  1557. unsigned int relativeperiodicannounce:1;
  1558. unsigned int autopausebusy:1;
  1559. unsigned int autopauseunavail:1;
  1560. enum empty_conditions joinempty;
  1561. enum empty_conditions leavewhenempty;
  1562. int announcepositionlimit; /*!< How many positions we announce? */
  1563. int announcefrequency; /*!< How often to announce their position */
  1564. int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
  1565. int periodicannouncefrequency; /*!< How often to play periodic announcement */
  1566. int numperiodicannounce; /*!< The number of periodic announcements configured */
  1567. int randomperiodicannounce; /*!< Are periodic announcments randomly chosen */
  1568. int roundingseconds; /*!< How many seconds do we round to? */
  1569. int holdtime; /*!< Current avg holdtime, based on an exponential average */
  1570. int talktime; /*!< Current avg talktime, based on the same exponential average */
  1571. int callscompleted; /*!< Number of queue calls completed */
  1572. int callsabandoned; /*!< Number of queue calls abandoned */
  1573. int servicelevel; /*!< seconds setting for servicelevel*/
  1574. int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
  1575. char monfmt[8]; /*!< Format to use when recording calls */
  1576. int montype; /*!< Monitor type Monitor vs. MixMonitor */
  1577. int count; /*!< How many entries */
  1578. int maxlen; /*!< Max number of entries */
  1579. int wrapuptime; /*!< Wrapup Time */
  1580. int penaltymemberslimit; /*!< Disregard penalty when queue has fewer than this many members */
  1581. int retry; /*!< Retry calling everyone after this amount of time */
  1582. int timeout; /*!< How long to wait for an answer */
  1583. int weight; /*!< Respective weight */
  1584. int autopause; /*!< Auto pause queue members if they fail to answer */
  1585. int autopausedelay; /*!< Delay auto pause for autopausedelay seconds since last call */
  1586. int timeoutpriority; /*!< Do we allow a fraction of the timeout to occur for a ring? */
  1587. /* Queue strategy things */
  1588. int rrpos; /*!< Round Robin - position */
  1589. int memberdelay; /*!< Seconds to delay connecting member to caller */
  1590. int autofill; /*!< Ignore the head call status and ring an available agent */
  1591. struct ao2_container *members; /*!< Head of the list of members */
  1592. struct queue_ent *head; /*!< Head of the list of callers */
  1593. AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
  1594. AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
  1595. };
  1596. struct rule_list {
  1597. char name[80];
  1598. AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
  1599. AST_LIST_ENTRY(rule_list) list;
  1600. };
  1601. static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
  1602. static struct ao2_container *queues;
  1603. static void update_realtime_members(struct call_queue *q);
  1604. static struct member *interface_exists(struct call_queue *q, const char *interface);
  1605. static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
  1606. static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime);
  1607. static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
  1608. /*! \brief sets the QUEUESTATUS channel variable */
  1609. static void set_queue_result(struct ast_channel *chan, enum queue_result res)
  1610. {
  1611. int i;
  1612. for (i = 0; i < ARRAY_LEN(queue_results); i++) {
  1613. if (queue_results[i].id == res) {
  1614. pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
  1615. return;
  1616. }
  1617. }
  1618. }
  1619. static const char *int2strat(int strategy)
  1620. {
  1621. int x;
  1622. for (x = 0; x < ARRAY_LEN(strategies); x++) {
  1623. if (strategy == strategies[x].strategy) {
  1624. return strategies[x].name;
  1625. }
  1626. }
  1627. return "<unknown>";
  1628. }
  1629. static int strat2int(const char *strategy)
  1630. {
  1631. int x;
  1632. for (x = 0; x < ARRAY_LEN(strategies); x++) {
  1633. if (!strcasecmp(strategy, strategies[x].name)) {
  1634. return strategies[x].strategy;
  1635. }
  1636. }
  1637. return -1;
  1638. }
  1639. static int autopause2int(const char *autopause)
  1640. {
  1641. int x;
  1642. /*This 'double check' that default value is OFF */
  1643. if (ast_strlen_zero(autopause)) {
  1644. return QUEUE_AUTOPAUSE_OFF;
  1645. }
  1646. /*This 'double check' is to ensure old values works */
  1647. if(ast_true(autopause)) {
  1648. return QUEUE_AUTOPAUSE_ON;
  1649. }
  1650. for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
  1651. if (!strcasecmp(autopause, autopausesmodes[x].name)) {
  1652. return autopausesmodes[x].autopause;
  1653. }
  1654. }
  1655. /*This 'double check' that default value is OFF */
  1656. return QUEUE_AUTOPAUSE_OFF;
  1657. }
  1658. static int queue_hash_cb(const void *obj, const int flags)
  1659. {
  1660. const struct call_queue *q = obj;
  1661. return ast_str_case_hash(q->name);
  1662. }
  1663. static int queue_cmp_cb(void *obj, void *arg, int flags)
  1664. {
  1665. struct call_queue *q = obj, *q2 = arg;
  1666. return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
  1667. }
  1668. /*! \internal
  1669. * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg.
  1670. * \param obj the member being acted on
  1671. * \param arg pointer to an integer containing the position value that was removed and requires reduction for anything above
  1672. */
  1673. static int queue_member_decrement_followers(void *obj, void *arg, int flag)
  1674. {
  1675. struct member *mem = obj;
  1676. int *decrement_followers_after = arg;
  1677. if (mem->queuepos > *decrement_followers_after) {
  1678. mem->queuepos--;
  1679. }
  1680. return 0;
  1681. }
  1682. /*! \internal
  1683. * \brief ao2_callback, finds members in a queue marked for deletion and in a cascading fashion runs queue_member_decrement_followers
  1684. * on them. This callback should always be ran before performing mass unlinking of delmarked members from queues.
  1685. * \param obj member being acted on
  1686. * \param arg pointer to the queue members are being removed from
  1687. */
  1688. static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
  1689. {
  1690. struct member *mem = obj;
  1691. struct call_queue *queue = arg;
  1692. int rrpos = mem->queuepos;
  1693. if (mem->delme) {
  1694. ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &rrpos);
  1695. }
  1696. return 0;
  1697. }
  1698. /*! \internal
  1699. * \brief Use this to decrement followers during removal of a member
  1700. * \param queue which queue the member is being removed from
  1701. * \param mem which member is being removed from the queue
  1702. */
  1703. static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
  1704. {
  1705. int pos = mem->queuepos;
  1706. /* If the position being removed is less than the current place in the queue, reduce the queue position by one so that we don't skip the member
  1707. * who would have been next otherwise. */
  1708. if (pos < queue->rrpos) {
  1709. queue->rrpos--;
  1710. }
  1711. ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
  1712. }
  1713. #ifdef REF_DEBUG
  1714. #define queue_ref(q) _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
  1715. #define queue_unref(q) _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
  1716. #define queue_t_ref(q, tag) _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
  1717. #define queue_t_unref(q, tag) _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
  1718. #define queues_t_link(c, q, tag) __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
  1719. #define queues_t_unlink(c, q, tag) __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
  1720. static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
  1721. {
  1722. __ao2_ref_debug(q, 1, tag, file, line, filename);
  1723. return q;
  1724. }
  1725. static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
  1726. {
  1727. if (q) {
  1728. __ao2_ref_debug(q, -1, tag, file, line, filename);
  1729. }
  1730. return NULL;
  1731. }
  1732. #else
  1733. #define queue_t_ref(q, tag) queue_ref(q)
  1734. #define queue_t_unref(q, tag) queue_unref(q)
  1735. #define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
  1736. #define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag)
  1737. static inline struct call_queue *queue_ref(struct call_queue *q)
  1738. {
  1739. ao2_ref(q, 1);
  1740. return q;
  1741. }
  1742. static inline struct call_queue *queue_unref(struct call_queue *q)
  1743. {
  1744. if (q) {
  1745. ao2_ref(q, -1);
  1746. }
  1747. return NULL;
  1748. }
  1749. #endif
  1750. /*! \brief Set variables of queue */
  1751. static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
  1752. {
  1753. char interfacevar[256]="";
  1754. float sl = 0;
  1755. ao2_lock(q);
  1756. if (q->setqueuevar) {
  1757. sl = 0;
  1758. if (q->callscompleted > 0) {
  1759. sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
  1760. }
  1761. snprintf(interfacevar, sizeof(interfacevar),
  1762. "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
  1763. q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
  1764. ao2_unlock(q);
  1765. pbx_builtin_setvar_multiple(chan, interfacevar);
  1766. } else {
  1767. ao2_unlock(q);
  1768. }
  1769. }
  1770. /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
  1771. static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
  1772. {
  1773. struct queue_ent *cur;
  1774. if (!q || !new)
  1775. return;
  1776. if (prev) {
  1777. cur = prev->next;
  1778. prev->next = new;
  1779. } else {
  1780. cur = q->head;
  1781. q->head = new;
  1782. }
  1783. new->next = cur;
  1784. /* every queue_ent must have a reference to it's parent call_queue, this
  1785. * reference does not go away until the end of the queue_ent's life, meaning
  1786. * that even when the queue_ent leaves the call_queue this ref must remain. */
  1787. queue_ref(q);
  1788. new->parent = q;
  1789. new->pos = ++(*pos);
  1790. new->opos = *pos;
  1791. }
  1792. static struct ast_manager_event_blob *queue_channel_to_ami(const char *type, struct stasis_message *message)
  1793. {
  1794. struct ast_channel_blob *obj = stasis_message_data(message);
  1795. RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
  1796. RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
  1797. channel_string = ast_manager_build_channel_state_string(obj->snapshot);
  1798. event_string = ast_manager_str_from_json_object(obj->blob, NULL);
  1799. if (!channel_string || !event_string) {
  1800. return NULL;
  1801. }
  1802. return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
  1803. "%s"
  1804. "%s",
  1805. ast_str_buffer(channel_string),
  1806. ast_str_buffer(event_string));
  1807. }
  1808. static struct ast_manager_event_blob *queue_caller_join_to_ami(struct stasis_message *message)
  1809. {
  1810. return queue_channel_to_ami("QueueCallerJoin", message);
  1811. }
  1812. static struct ast_manager_event_blob *queue_caller_leave_to_ami(struct stasis_message *message)
  1813. {
  1814. return queue_channel_to_ami("QueueCallerLeave", message);
  1815. }
  1816. static struct ast_manager_event_blob *queue_caller_abandon_to_ami(struct stasis_message *message)
  1817. {
  1818. return queue_channel_to_ami("QueueCallerAbandon", message);
  1819. }
  1820. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_join_type,
  1821. .to_ami = queue_caller_join_to_ami,
  1822. );
  1823. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_leave_type,
  1824. .to_ami = queue_caller_leave_to_ami,
  1825. );
  1826. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_abandon_type,
  1827. .to_ami = queue_caller_abandon_to_ami,
  1828. );
  1829. static struct ast_manager_event_blob *queue_member_to_ami(const char *type, struct stasis_message *message)
  1830. {
  1831. struct ast_json_payload *payload = stasis_message_data(message);
  1832. RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
  1833. event_string = ast_manager_str_from_json_object(payload->json, NULL);
  1834. if (!event_string) {
  1835. return NULL;
  1836. }
  1837. return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
  1838. "%s",
  1839. ast_str_buffer(event_string));
  1840. }
  1841. static struct ast_manager_event_blob *queue_member_status_to_ami(struct stasis_message *message)
  1842. {
  1843. return queue_member_to_ami("QueueMemberStatus", message);
  1844. }
  1845. static struct ast_manager_event_blob *queue_member_added_to_ami(struct stasis_message *message)
  1846. {
  1847. return queue_member_to_ami("QueueMemberAdded", message);
  1848. }
  1849. static struct ast_manager_event_blob *queue_member_removed_to_ami(struct stasis_message *message)
  1850. {
  1851. return queue_member_to_ami("QueueMemberRemoved", message);
  1852. }
  1853. static struct ast_manager_event_blob *queue_member_pause_to_ami(struct stasis_message *message)
  1854. {
  1855. return queue_member_to_ami("QueueMemberPause", message);
  1856. }
  1857. static struct ast_manager_event_blob *queue_member_penalty_to_ami(struct stasis_message *message)
  1858. {
  1859. return queue_member_to_ami("QueueMemberPenalty", message);
  1860. }
  1861. static struct ast_manager_event_blob *queue_member_ringinuse_to_ami(struct stasis_message *message)
  1862. {
  1863. return queue_member_to_ami("QueueMemberRinginuse", message);
  1864. }
  1865. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_status_type,
  1866. .to_ami = queue_member_status_to_ami,
  1867. );
  1868. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_added_type,
  1869. .to_ami = queue_member_added_to_ami,
  1870. );
  1871. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_removed_type,
  1872. .to_ami = queue_member_removed_to_ami,
  1873. );
  1874. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_pause_type,
  1875. .to_ami = queue_member_pause_to_ami,
  1876. );
  1877. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_penalty_type,
  1878. .to_ami = queue_member_penalty_to_ami,
  1879. );
  1880. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_ringinuse_type,
  1881. .to_ami = queue_member_ringinuse_to_ami,
  1882. );
  1883. static struct ast_manager_event_blob *queue_multi_channel_to_ami(const char *type, struct stasis_message *message)
  1884. {
  1885. struct ast_multi_channel_blob *obj = stasis_message_data(message);
  1886. struct ast_channel_snapshot *caller;
  1887. struct ast_channel_snapshot *agent;
  1888. RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
  1889. RAII_VAR(struct ast_str *, agent_event_string, NULL, ast_free);
  1890. RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
  1891. caller = ast_multi_channel_blob_get_channel(obj, "caller");
  1892. if (caller) {
  1893. caller_event_string = ast_manager_build_channel_state_string(caller);
  1894. if (!caller_event_string) {
  1895. ast_log(LOG_NOTICE, "No caller event string, bailing\n");
  1896. return NULL;
  1897. }
  1898. }
  1899. agent = ast_multi_channel_blob_get_channel(obj, "agent");
  1900. if (agent) {
  1901. agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
  1902. if (!agent_event_string) {
  1903. ast_log(LOG_NOTICE, "No agent event string, bailing\n");
  1904. return NULL;
  1905. }
  1906. }
  1907. event_string = ast_manager_str_from_json_object(ast_multi_channel_blob_get_json(obj), NULL);
  1908. if (!event_string) {
  1909. return NULL;
  1910. }
  1911. return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
  1912. "%s"
  1913. "%s"
  1914. "%s",
  1915. caller_event_string ? ast_str_buffer(caller_event_string) : "",
  1916. agent_event_string ? ast_str_buffer(agent_event_string) : "",
  1917. ast_str_buffer(event_string));
  1918. }
  1919. static struct ast_manager_event_blob *queue_agent_called_to_ami(struct stasis_message *message)
  1920. {
  1921. return queue_multi_channel_to_ami("AgentCalled", message);
  1922. }
  1923. static struct ast_manager_event_blob *queue_agent_connect_to_ami(struct stasis_message *message)
  1924. {
  1925. return queue_multi_channel_to_ami("AgentConnect", message);
  1926. }
  1927. static struct ast_manager_event_blob *queue_agent_complete_to_ami(struct stasis_message *message)
  1928. {
  1929. return queue_multi_channel_to_ami("AgentComplete", message);
  1930. }
  1931. static struct ast_manager_event_blob *queue_agent_dump_to_ami(struct stasis_message *message)
  1932. {
  1933. return queue_multi_channel_to_ami("AgentDump", message);
  1934. }
  1935. static struct ast_manager_event_blob *queue_agent_ringnoanswer_to_ami(struct stasis_message *message)
  1936. {
  1937. return queue_multi_channel_to_ami("AgentRingNoAnswer", message);
  1938. }
  1939. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_called_type,
  1940. .to_ami = queue_agent_called_to_ami,
  1941. );
  1942. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_connect_type,
  1943. .to_ami = queue_agent_connect_to_ami,
  1944. );
  1945. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_complete_type,
  1946. .to_ami = queue_agent_complete_to_ami,
  1947. );
  1948. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_dump_type,
  1949. .to_ami = queue_agent_dump_to_ami,
  1950. );
  1951. STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_ringnoanswer_type,
  1952. .to_ami = queue_agent_ringnoanswer_to_ami,
  1953. );
  1954. static void queue_publish_multi_channel_snapshot_blob(struct stasis_topic *topic,
  1955. struct ast_channel_snapshot *caller_snapshot,
  1956. struct ast_channel_snapshot *agent_snapshot,
  1957. struct stasis_message_type *type, struct ast_json *blob)
  1958. {
  1959. RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
  1960. RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
  1961. if (!type) {
  1962. return;
  1963. }
  1964. payload = ast_multi_channel_blob_create(blob);
  1965. if (!payload) {
  1966. return;
  1967. }
  1968. if (caller_snapshot) {
  1969. ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
  1970. } else {
  1971. ast_debug(1, "Empty caller_snapshot; sending incomplete event\n");
  1972. }
  1973. if (agent_snapshot) {
  1974. ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
  1975. }
  1976. msg = stasis_message_create(type, payload);
  1977. if (!msg) {
  1978. return;
  1979. }
  1980. stasis_publish(topic, msg);
  1981. }
  1982. static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent,
  1983. struct stasis_message_type *type, struct ast_json *blob)
  1984. {
  1985. RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
  1986. RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
  1987. ast_channel_lock(caller);
  1988. caller_snapshot = ast_channel_snapshot_create(caller);
  1989. ast_channel_unlock(caller);
  1990. ast_channel_lock(agent);
  1991. agent_snapshot = ast_channel_snapshot_create(agent);
  1992. ast_channel_unlock(agent);
  1993. if (!caller_snapshot || !agent_snapshot) {
  1994. return;
  1995. }
  1996. queue_publish_multi_channel_snapshot_blob(ast_channel_topic(caller), caller_snapshot,
  1997. agent_snapshot, type, blob);
  1998. }
  1999. /*!
  2000. * \internal
  2001. * \brief Publish the member blob.
  2002. * \since 12.0.0
  2003. *
  2004. * \param type Stasis message type to publish.
  2005. * \param blob The information being published.
  2006. *
  2007. * \note The json blob reference is passed to this function.
  2008. *
  2009. * \return Nothing
  2010. */
  2011. static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
  2012. {
  2013. RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
  2014. RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
  2015. if (!blob || !type) {
  2016. ast_json_unref(blob);
  2017. return;
  2018. }
  2019. payload = ast_json_payload_create(blob);
  2020. ast_json_unref(blob);
  2021. if (!payload) {
  2022. return;
  2023. }
  2024. msg = stasis_message_create(type, payload);
  2025. if (!msg) {
  2026. return;
  2027. }
  2028. stasis_publish(ast_manager_get_topic(), msg);
  2029. }
  2030. static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
  2031. {
  2032. return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i, s: s, s: i}",
  2033. "Queue", q->name,
  2034. "MemberName", mem->membername,
  2035. "Interface", mem->interface,
  2036. "StateInterface", mem->state_interface,
  2037. "Membership", (mem->dynamic ? "dynamic" : (mem->realtime ? "realtime" : "static")),
  2038. "Penalty", mem->penalty,
  2039. "CallsTaken", mem->calls,
  2040. "LastCall", (int)mem->lastcall,
  2041. "InCall", mem->starttime ? 1 : 0,
  2042. "Status", mem->status,
  2043. "Paused", mem->paused,
  2044. "PausedReason", mem->reason_paused,
  2045. "Ringinuse", mem->ringinuse);
  2046. }
  2047. /*! \brief Check if members are available
  2048. *
  2049. * This function checks to see if members are available to be called. If any member
  2050. * is available, the function immediately returns 0. If no members are available,
  2051. * then -1 is returned.
  2052. */
  2053. static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
  2054. {
  2055. struct member *member;
  2056. struct ao2_iterator mem_iter;
  2057. ao2_lock(q);
  2058. mem_iter = ao2_iterator_init(q->members, 0);
  2059. for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
  2060. if ((max_penalty != INT_MAX && member->penalty > max_penalty) || (min_penalty != INT_MAX && member->penalty < min_penalty)) {
  2061. if (conditions & QUEUE_EMPTY_PENALTY) {
  2062. ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
  2063. continue;
  2064. }
  2065. }
  2066. switch (devstate ? ast_device_state(member->state_interface) : member->status) {
  2067. case AST_DEVICE_INVALID:
  2068. if (conditions & QUEUE_EMPTY_INVALID) {
  2069. ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
  2070. break;
  2071. }
  2072. goto default_case;
  2073. case AST_DEVICE_UNAVAILABLE:
  2074. if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
  2075. ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
  2076. break;
  2077. }
  2078. goto default_case;
  2079. case AST_DEVICE_INUSE:
  2080. if (conditions & QUEUE_EMPTY_INUSE) {
  2081. ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
  2082. break;
  2083. }
  2084. goto default_case;
  2085. case AST_DEVICE_RINGING:
  2086. if (conditions & QUEUE_EMPTY_RINGING) {
  2087. ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
  2088. break;
  2089. }
  2090. goto default_case;
  2091. case AST_DEVICE_UNKNOWN:
  2092. if (conditions & QUEUE_EMPTY_UNKNOWN) {
  2093. ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
  2094. break;
  2095. }
  2096. /* Fall-through */
  2097. default:
  2098. default_case:
  2099. if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
  2100. ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
  2101. break;
  2102. } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
  2103. ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
  2104. break;
  2105. } else {
  2106. ao2_ref(member, -1);
  2107. ao2_iterator_destroy(&mem_iter);
  2108. ao2_unlock(q);
  2109. ast_debug(4, "%s is available.\n", member->membername);
  2110. return 0;
  2111. }
  2112. break;
  2113. }
  2114. }
  2115. ao2_iterator_destroy(&mem_iter);
  2116. ao2_unlock(q);
  2117. if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
  2118. /* member state still may be RINGING due to lag in event message - check again with device state */
  2119. return get_member_status(q, max_penalty, min_penalty, conditions, 1);
  2120. }
  2121. return -1;
  2122. }
  2123. /*
  2124. * A "pool" of member objects that calls are currently pending on. If an
  2125. * agent is a member of multiple queues it's possible for that agent to be
  2126. * called by each of the queues at the same time. This happens because device
  2127. * state is slow to notify the queue app of one of it's member's being rung.
  2128. * This "pool" allows us to track which members are currently being rung while
  2129. * we wait on the device state change.
  2130. */
  2131. static struct ao2_container *pending_members;
  2132. #define MAX_CALL_ATTEMPT_BUCKETS 353
  2133. static int pending_members_hash(const void *obj, const int flags)
  2134. {
  2135. const struct member *object;
  2136. const char *key;
  2137. switch (flags & OBJ_SEARCH_MASK) {
  2138. case OBJ_SEARCH_KEY:
  2139. key = obj;
  2140. break;
  2141. case OBJ_SEARCH_OBJECT:
  2142. object = obj;
  2143. key = object->interface;
  2144. break;
  2145. default:
  2146. ast_assert(0);
  2147. return 0;
  2148. }
  2149. return ast_str_case_hash(key);
  2150. }
  2151. static int pending_members_cmp(void *obj, void *arg, int flags)
  2152. {
  2153. const struct member *object_left = obj;
  2154. const struct member *object_right = arg;
  2155. const char *right_key = arg;
  2156. int cmp;
  2157. switch (flags & OBJ_SEARCH_MASK) {
  2158. case OBJ_SEARCH_OBJECT:
  2159. right_key = object_right->interface;
  2160. /* Fall through */
  2161. case OBJ_SEARCH_KEY:
  2162. cmp = strcasecmp(object_left->interface, right_key);
  2163. break;
  2164. case OBJ_SEARCH_PARTIAL_KEY:
  2165. /* Not supported by container. */
  2166. ast_assert(0);
  2167. return 0;
  2168. default:
  2169. cmp = 0;
  2170. break;
  2171. }
  2172. if (cmp) {
  2173. return 0;
  2174. }
  2175. return CMP_MATCH;
  2176. }
  2177. static void pending_members_remove(struct member *mem)
  2178. {
  2179. ast_debug(3, "Removed %s from pending_members\n", mem->membername);
  2180. ao2_find(pending_members, mem, OBJ_POINTER | OBJ_NODATA | OBJ_UNLINK);
  2181. }
  2182. /*! \brief set a member's status based on device state of that member's state_interface.
  2183. *
  2184. * Lock interface list find sc, iterate through each queues queue_member list for member to
  2185. * update state inside queues
  2186. */
  2187. static void update_status(struct call_queue *q, struct member *m, const int status)
  2188. {
  2189. if (m->status != status) {
  2190. /* If this member has transitioned to being available then update their queue
  2191. * information. If they are currently in a call then the leg to the agent will be
  2192. * considered done and the call finished.
  2193. */
  2194. if (status == AST_DEVICE_NOT_INUSE) {
  2195. update_queue(q, m, m->callcompletedinsl, m->starttime);
  2196. }
  2197. m->status = status;
  2198. /* Remove the member from the pending members pool only when the status changes.
  2199. * This is not done unconditionally because we can occasionally see multiple
  2200. * device state notifications of not in use after a previous call has ended,
  2201. * including after we have initiated a new call. This is more likely to
  2202. * happen when there is latency in the connection to the member.
  2203. */
  2204. pending_members_remove(m);
  2205. }
  2206. queue_publish_member_blob(queue_member_status_type(), queue_member_blob_create(q, m));
  2207. }
  2208. /*!
  2209. * \internal
  2210. * \brief Determine if a queue member is available
  2211. * \retval 1 if the member is available
  2212. * \retval 0 if the member is not available
  2213. */
  2214. static int is_member_available(struct call_queue *q, struct member *mem)
  2215. {
  2216. int available = 0;
  2217. switch (mem->status) {
  2218. case AST_DEVICE_INVALID:
  2219. case AST_DEVICE_UNAVAILABLE:
  2220. break;
  2221. case AST_DEVICE_INUSE:
  2222. case AST_DEVICE_BUSY:
  2223. case AST_DEVICE_RINGING:
  2224. case AST_DEVICE_RINGINUSE:
  2225. case AST_DEVICE_ONHOLD:
  2226. if (!mem->ringinuse) {
  2227. break;
  2228. }
  2229. /* else fall through */
  2230. case AST_DEVICE_NOT_INUSE:
  2231. case AST_DEVICE_UNKNOWN:
  2232. if (!mem->paused) {
  2233. available = 1;
  2234. }
  2235. break;
  2236. }
  2237. /* Let wrapuptimes override device state availability */
  2238. if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) {
  2239. available = 0;
  2240. }
  2241. return available;
  2242. }
  2243. /*! \brief set a member's status based on device state of that member's interface*/
  2244. static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
  2245. {
  2246. struct ao2_iterator miter, qiter;
  2247. struct ast_device_state_message *dev_state;
  2248. struct member *m;
  2249. struct call_queue *q;
  2250. char interface[80], *slash_pos;
  2251. int found = 0; /* Found this member in any queue */
  2252. int found_member; /* Found this member in this queue */
  2253. int avail = 0; /* Found an available member in this queue */
  2254. if (ast_device_state_message_type() != stasis_message_type(msg)) {
  2255. return;
  2256. }
  2257. dev_state = stasis_message_data(msg);
  2258. if (dev_state->eid) {
  2259. /* ignore non-aggregate states */
  2260. return;
  2261. }
  2262. qiter = ao2_iterator_init(queues, 0);
  2263. while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
  2264. ao2_lock(q);
  2265. avail = 0;
  2266. found_member = 0;
  2267. miter = ao2_iterator_init(q->members, 0);
  2268. for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
  2269. if (!found_member) {
  2270. ast_copy_string(interface, m->state_interface, sizeof(interface));
  2271. if ((slash_pos = strchr(interface, '/'))) {
  2272. if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
  2273. *slash_pos = '\0';
  2274. }
  2275. }
  2276. if (!strcasecmp(interface, dev_state->device)) {
  2277. found_member = 1;
  2278. update_status(q, m, dev_state->state);
  2279. }
  2280. }
  2281. /* check every member until we find one NOT_INUSE */
  2282. if (!avail) {
  2283. avail = is_member_available(q, m);
  2284. }
  2285. if (avail && found_member) {
  2286. /* early exit as we've found an available member and the member of interest */
  2287. ao2_ref(m, -1);
  2288. break;
  2289. }
  2290. }
  2291. if (found_member) {
  2292. found = 1;
  2293. if (avail) {
  2294. ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
  2295. } else {
  2296. ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
  2297. }
  2298. }
  2299. ao2_iterator_destroy(&miter);
  2300. ao2_unlock(q);
  2301. queue_t_unref(q, "Done with iterator");
  2302. }
  2303. ao2_iterator_destroy(&qiter);
  2304. if (found) {
  2305. ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
  2306. dev_state->device,
  2307. dev_state->state,
  2308. ast_devstate2str(dev_state->state));
  2309. } else {
  2310. ast_debug(3, "Device '%s' changed to state '%u' (%s) but we don't care because they're not a member of any queue.\n",
  2311. dev_state->device,
  2312. dev_state->state,
  2313. ast_devstate2str(dev_state->state));
  2314. }
  2315. return;
  2316. }
  2317. /*! \brief Helper function which converts from extension state to device state values */
  2318. static int extensionstate2devicestate(int state)
  2319. {
  2320. switch (state) {
  2321. case AST_EXTENSION_NOT_INUSE:
  2322. state = AST_DEVICE_NOT_INUSE;
  2323. break;
  2324. case AST_EXTENSION_INUSE:
  2325. state = AST_DEVICE_INUSE;
  2326. break;
  2327. case AST_EXTENSION_BUSY:
  2328. state = AST_DEVICE_BUSY;
  2329. break;
  2330. case AST_EXTENSION_RINGING:
  2331. state = AST_DEVICE_RINGING;
  2332. break;
  2333. case AST_EXTENSION_ONHOLD:
  2334. state = AST_DEVICE_ONHOLD;
  2335. break;
  2336. case AST_EXTENSION_UNAVAILABLE:
  2337. state = AST_DEVICE_UNAVAILABLE;
  2338. break;
  2339. case AST_EXTENSION_REMOVED:
  2340. case AST_EXTENSION_DEACTIVATED:
  2341. default:
  2342. state = AST_DEVICE_INVALID;
  2343. break;
  2344. }
  2345. return state;
  2346. }
  2347. static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
  2348. {
  2349. struct ao2_iterator miter, qiter;
  2350. struct member *m;
  2351. struct call_queue *q;
  2352. int state = info->exten_state;
  2353. int found = 0, device_state = extensionstate2devicestate(state);
  2354. /* only interested in extension state updates involving device states */
  2355. if (info->reason != AST_HINT_UPDATE_DEVICE) {
  2356. return 0;
  2357. }
  2358. qiter = ao2_iterator_init(queues, 0);
  2359. while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
  2360. ao2_lock(q);
  2361. miter = ao2_iterator_init(q->members, 0);
  2362. for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
  2363. if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
  2364. update_status(q, m, device_state);
  2365. ao2_ref(m, -1);
  2366. found = 1;
  2367. break;
  2368. }
  2369. }
  2370. ao2_iterator_destroy(&miter);
  2371. ao2_unlock(q);
  2372. queue_t_unref(q, "Done with iterator");
  2373. }
  2374. ao2_iterator_destroy(&qiter);
  2375. if (found) {
  2376. ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
  2377. } else {
  2378. ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
  2379. exten, context, device_state, ast_devstate2str(device_state));
  2380. }
  2381. return 0;
  2382. }
  2383. /*! \brief Return the current state of a member */
  2384. static int get_queue_member_status(struct member *cur)
  2385. {
  2386. return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
  2387. }
  2388. static void destroy_queue_member_cb(void *obj)
  2389. {
  2390. struct member *mem = obj;
  2391. if (mem->state_id != -1) {
  2392. ast_extension_state_del(mem->state_id, extension_state_cb);
  2393. }
  2394. }
  2395. /*! \brief allocate space for new queue member and set fields based on parameters passed */
  2396. static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
  2397. {
  2398. struct member *cur;
  2399. if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {
  2400. cur->ringinuse = ringinuse;
  2401. cur->penalty = penalty;
  2402. cur->paused = paused;
  2403. ast_copy_string(cur->interface, interface, sizeof(cur->interface));
  2404. if (!ast_strlen_zero(state_interface)) {
  2405. ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
  2406. } else {
  2407. ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
  2408. }
  2409. if (!ast_strlen_zero(membername)) {
  2410. ast_copy_string(cur->membername, membername, sizeof(cur->membername));
  2411. } else {
  2412. ast_copy_string(cur->membername, interface, sizeof(cur->membername));
  2413. }
  2414. if (!strchr(cur->interface, '/')) {
  2415. ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
  2416. }
  2417. if (!strncmp(cur->state_interface, "hint:", 5)) {
  2418. char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
  2419. char *exten = strsep(&context, "@") + 5;
  2420. ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
  2421. ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
  2422. cur->state_id = ast_extension_state_add(cur->state_context, cur->state_exten, extension_state_cb, NULL);
  2423. } else {
  2424. cur->state_id = -1;
  2425. }
  2426. cur->status = get_queue_member_status(cur);
  2427. }
  2428. return cur;
  2429. }
  2430. static int compress_char(const char c)
  2431. {
  2432. if (c < 32) {
  2433. return 0;
  2434. } else if (c > 96) {
  2435. return c - 64;
  2436. }
  2437. return c - 32;
  2438. }
  2439. static int member_hash_fn(const void *obj, const int flags)
  2440. {
  2441. const struct member *mem = obj;
  2442. const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
  2443. const char *chname = strchr(interface, '/');
  2444. int ret = 0, i;
  2445. if (!chname) {
  2446. chname = interface;
  2447. }
  2448. for (i = 0; i < 5 && chname[i]; i++) {
  2449. ret += compress_char(chname[i]) << (i * 6);
  2450. }
  2451. return ret;
  2452. }
  2453. static int member_cmp_fn(void *obj1, void *obj2, int flags)
  2454. {
  2455. struct member *mem1 = obj1;
  2456. struct member *mem2 = obj2;
  2457. const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
  2458. return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
  2459. }
  2460. /*!
  2461. * \brief Initialize Queue default values.
  2462. * \note the queue's lock must be held before executing this function
  2463. */
  2464. static void init_queue(struct call_queue *q)
  2465. {
  2466. int i;
  2467. struct penalty_rule *pr_iter;
  2468. q->dead = 0;
  2469. q->retry = DEFAULT_RETRY;
  2470. q->timeout = DEFAULT_TIMEOUT;
  2471. q->maxlen = 0;
  2472. ast_string_field_set(q, context, "");
  2473. q->announcefrequency = 0;
  2474. q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
  2475. q->announceholdtime = 1;
  2476. q->announcepositionlimit = 10; /* Default 10 positions */
  2477. q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
  2478. q->roundingseconds = 0; /* Default - don't announce seconds */
  2479. q->servicelevel = 0;
  2480. q->ringinuse = 1;
  2481. q->announce_to_first_user = 0;
  2482. q->setinterfacevar = 0;
  2483. q->setqueuevar = 0;
  2484. q->setqueueentryvar = 0;
  2485. q->autofill = autofill_default;
  2486. q->montype = montype_default;
  2487. q->monfmt[0] = '\0';
  2488. q->reportholdtime = 0;
  2489. q->wrapuptime = 0;
  2490. q->penaltymemberslimit = 0;
  2491. q->joinempty = 0;
  2492. q->leavewhenempty = 0;
  2493. q->memberdelay = 0;
  2494. q->weight = 0;
  2495. q->timeoutrestart = 0;
  2496. q->periodicannouncefrequency = 0;
  2497. q->randomperiodicannounce = 0;
  2498. q->numperiodicannounce = 0;
  2499. q->autopause = QUEUE_AUTOPAUSE_OFF;
  2500. q->timeoutpriority = TIMEOUT_PRIORITY_APP;
  2501. q->autopausedelay = 0;
  2502. if (!q->members) {
  2503. if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
  2504. /* linear strategy depends on order, so we have to place all members in a list */
  2505. q->members = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, member_cmp_fn);
  2506. } else {
  2507. q->members = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, 37,
  2508. member_hash_fn, NULL, member_cmp_fn);
  2509. }
  2510. }
  2511. q->found = 1;
  2512. ast_string_field_set(q, moh, "");
  2513. ast_string_field_set(q, sound_next, "queue-youarenext");
  2514. ast_string_field_set(q, sound_thereare, "queue-thereare");
  2515. ast_string_field_set(q, sound_calls, "queue-callswaiting");
  2516. ast_string_field_set(q, queue_quantity1, "queue-quantity1");
  2517. ast_string_field_set(q, queue_quantity2, "queue-quantity2");
  2518. ast_string_field_set(q, sound_holdtime, "queue-holdtime");
  2519. ast_string_field_set(q, sound_minutes, "queue-minutes");
  2520. ast_string_field_set(q, sound_minute, "queue-minute");
  2521. ast_string_field_set(q, sound_seconds, "queue-seconds");
  2522. ast_string_field_set(q, sound_thanks, "queue-thankyou");
  2523. ast_string_field_set(q, sound_reporthold, "queue-reporthold");
  2524. if (!q->sound_periodicannounce[0]) {
  2525. q->sound_periodicannounce[0] = ast_str_create(32);
  2526. }
  2527. if (q->sound_periodicannounce[0]) {
  2528. ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
  2529. }
  2530. for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
  2531. if (q->sound_periodicannounce[i]) {
  2532. ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
  2533. }
  2534. }
  2535. while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
  2536. ast_free(pr_iter);
  2537. }
  2538. /* On restart assume no members are available.
  2539. * The queue_avail hint is a boolean state to indicate whether a member is available or not.
  2540. *
  2541. * This seems counter intuitive, but is required to light a BLF
  2542. * AST_DEVICE_INUSE indicates no members are available.
  2543. * AST_DEVICE_NOT_INUSE indicates a member is available.
  2544. */
  2545. ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
  2546. }
  2547. static void clear_queue(struct call_queue *q)
  2548. {
  2549. q->holdtime = 0;
  2550. q->callscompleted = 0;
  2551. q->callsabandoned = 0;
  2552. q->callscompletedinsl = 0;
  2553. q->talktime = 0;
  2554. if (q->members) {
  2555. struct member *mem;
  2556. struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
  2557. while ((mem = ao2_iterator_next(&mem_iter))) {
  2558. mem->calls = 0;
  2559. mem->callcompletedinsl = 0;
  2560. mem->lastcall = 0;
  2561. mem->starttime = 0;
  2562. ao2_ref(mem, -1);
  2563. }
  2564. ao2_iterator_destroy(&mem_iter);
  2565. }
  2566. }
  2567. /*!
  2568. * \brief Change queue penalty by adding rule.
  2569. *
  2570. * Check rule for errors with time or fomatting, see if rule is relative to rest
  2571. * of queue, iterate list of rules to find correct insertion point, insert and return.
  2572. * \retval -1 on failure
  2573. * \retval 0 on success
  2574. * \note Call this with the rule_lists locked
  2575. */
  2576. static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
  2577. {
  2578. char *timestr, *maxstr, *minstr, *contentdup;
  2579. struct penalty_rule *rule = NULL, *rule_iter;
  2580. struct rule_list *rl_iter;
  2581. int penaltychangetime, inserted = 0;
  2582. if (!(rule = ast_calloc(1, sizeof(*rule)))) {
  2583. return -1;
  2584. }
  2585. contentdup = ast_strdupa(content);
  2586. if (!(maxstr = strchr(contentdup, ','))) {
  2587. ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
  2588. ast_free(rule);
  2589. return -1;
  2590. }
  2591. *maxstr++ = '\0';
  2592. timestr = contentdup;
  2593. if ((penaltychangetime = atoi(timestr)) < 0) {
  2594. ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
  2595. ast_free(rule);
  2596. return -1;
  2597. }
  2598. rule->time = penaltychangetime;
  2599. if ((minstr = strchr(maxstr,','))) {
  2600. *minstr++ = '\0';
  2601. }
  2602. /* The last check will evaluate true if either no penalty change is indicated for a given rule
  2603. * OR if a min penalty change is indicated but no max penalty change is */
  2604. if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
  2605. rule->max_relative = 1;
  2606. }
  2607. rule->max_value = atoi(maxstr);
  2608. if (!ast_strlen_zero(minstr)) {
  2609. if (*minstr == '+' || *minstr == '-') {
  2610. rule->min_relative = 1;
  2611. }
  2612. rule->min_value = atoi(minstr);
  2613. } else { /*there was no minimum specified, so assume this means no change*/
  2614. rule->min_relative = 1;
  2615. }
  2616. /*We have the rule made, now we need to insert it where it belongs*/
  2617. AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
  2618. if (strcasecmp(rl_iter->name, list_name)) {
  2619. continue;
  2620. }
  2621. AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
  2622. if (rule->time < rule_iter->time) {
  2623. AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
  2624. inserted = 1;
  2625. break;
  2626. }
  2627. }
  2628. AST_LIST_TRAVERSE_SAFE_END;
  2629. if (!inserted) {
  2630. AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
  2631. inserted = 1;
  2632. }
  2633. break;
  2634. }
  2635. if (!inserted) {
  2636. ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
  2637. ast_free(rule);
  2638. return -1;
  2639. }
  2640. return 0;
  2641. }
  2642. /*!
  2643. * \brief Load queue rules from realtime.
  2644. *
  2645. * Check rule for errors with time or fomatting, see if rule is relative to rest
  2646. * of queue, iterate list of rules to find correct insertion point, insert and return.
  2647. * \retval -1 on failure
  2648. * \retval 0 on success
  2649. * \note Call this with the rule_lists locked
  2650. */
  2651. static int load_realtime_rules(void)
  2652. {
  2653. struct ast_config *cfg;
  2654. struct rule_list *rl_iter, *new_rl;
  2655. struct penalty_rule *pr_iter;
  2656. char *rulecat = NULL;
  2657. if (!ast_check_realtime("queue_rules")) {
  2658. ast_log(LOG_WARNING, "Missing \"queue_rules\" in extconfig.conf\n");
  2659. return 0;
  2660. }
  2661. if (!(cfg = ast_load_realtime_multientry("queue_rules", "rule_name LIKE", "%", SENTINEL))) {
  2662. ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n");
  2663. return 0;
  2664. }
  2665. while ((rulecat = ast_category_browse(cfg, rulecat))) {
  2666. const char *timestr, *maxstr, *minstr, *rule_name;
  2667. int penaltychangetime, rule_exists = 0, inserted = 0;
  2668. int max_penalty = 0, min_penalty = 0, min_relative = 0, max_relative = 0;
  2669. struct penalty_rule *new_penalty_rule = NULL;
  2670. rule_name = ast_variable_retrieve(cfg, rulecat, "rule_name");
  2671. if (ast_strlen_zero(rule_name)) {
  2672. continue;
  2673. }
  2674. AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
  2675. if (!(strcasecmp(rl_iter->name, rule_name))) {
  2676. rule_exists = 1;
  2677. new_rl = rl_iter;
  2678. break;
  2679. }
  2680. }
  2681. if (!rule_exists) {
  2682. if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
  2683. ast_config_destroy(cfg);
  2684. return -1;
  2685. }
  2686. ast_copy_string(new_rl->name, rule_name, sizeof(new_rl->name));
  2687. AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
  2688. }
  2689. timestr = ast_variable_retrieve(cfg, rulecat, "time");
  2690. if (!(timestr) || sscanf(timestr, "%30d", &penaltychangetime) != 1) {
  2691. ast_log(LOG_NOTICE, "Failed to parse time (%s) for one of the %s rules, skipping it\n",
  2692. (ast_strlen_zero(timestr) ? "invalid value" : timestr), rule_name);
  2693. continue;
  2694. }
  2695. if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) {
  2696. ast_config_destroy(cfg);
  2697. return -1;
  2698. }
  2699. if (!(maxstr = ast_variable_retrieve(cfg, rulecat, "max_penalty")) ||
  2700. ast_strlen_zero(maxstr) || sscanf(maxstr, "%30d", &max_penalty) != 1) {
  2701. max_penalty = 0;
  2702. max_relative = 1;
  2703. } else {
  2704. if (*maxstr == '+' || *maxstr == '-') {
  2705. max_relative = 1;
  2706. }
  2707. }
  2708. if (!(minstr = ast_variable_retrieve(cfg, rulecat, "min_penalty")) ||
  2709. ast_strlen_zero(minstr) || sscanf(minstr, "%30d", &min_penalty) != 1) {
  2710. min_penalty = 0;
  2711. min_relative = 1;
  2712. } else {
  2713. if (*minstr == '+' || *minstr == '-') {
  2714. min_relative = 1;
  2715. }
  2716. }
  2717. new_penalty_rule->time = penaltychangetime;
  2718. new_penalty_rule->max_relative = max_relative;
  2719. new_penalty_rule->max_value = max_penalty;
  2720. new_penalty_rule->min_relative = min_relative;
  2721. new_penalty_rule->min_value = min_penalty;
  2722. AST_LIST_TRAVERSE_SAFE_BEGIN(&new_rl->rules, pr_iter, list) {
  2723. if (new_penalty_rule->time < pr_iter->time) {
  2724. AST_LIST_INSERT_BEFORE_CURRENT(new_penalty_rule, list);
  2725. inserted = 1;
  2726. }
  2727. }
  2728. AST_LIST_TRAVERSE_SAFE_END;
  2729. if (!inserted) {
  2730. AST_LIST_INSERT_TAIL(&new_rl->rules, new_penalty_rule, list);
  2731. }
  2732. }
  2733. ast_config_destroy(cfg);
  2734. return 0;
  2735. }
  2736. static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
  2737. {
  2738. char *value_copy = ast_strdupa(value);
  2739. char *option = NULL;
  2740. while ((option = strsep(&value_copy, ","))) {
  2741. if (!strcasecmp(option, "paused")) {
  2742. *empty |= QUEUE_EMPTY_PAUSED;
  2743. } else if (!strcasecmp(option, "penalty")) {
  2744. *empty |= QUEUE_EMPTY_PENALTY;
  2745. } else if (!strcasecmp(option, "inuse")) {
  2746. *empty |= QUEUE_EMPTY_INUSE;
  2747. } else if (!strcasecmp(option, "ringing")) {
  2748. *empty |= QUEUE_EMPTY_RINGING;
  2749. } else if (!strcasecmp(option, "invalid")) {
  2750. *empty |= QUEUE_EMPTY_INVALID;
  2751. } else if (!strcasecmp(option, "wrapup")) {
  2752. *empty |= QUEUE_EMPTY_WRAPUP;
  2753. } else if (!strcasecmp(option, "unavailable")) {
  2754. *empty |= QUEUE_EMPTY_UNAVAILABLE;
  2755. } else if (!strcasecmp(option, "unknown")) {
  2756. *empty |= QUEUE_EMPTY_UNKNOWN;
  2757. } else if (!strcasecmp(option, "loose")) {
  2758. *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
  2759. } else if (!strcasecmp(option, "strict")) {
  2760. *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
  2761. } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
  2762. *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
  2763. } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
  2764. *empty = 0;
  2765. } else {
  2766. ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
  2767. }
  2768. }
  2769. }
  2770. /*! \brief Configure a queue parameter.
  2771. *
  2772. * The failunknown flag is set for config files (and static realtime) to show
  2773. * errors for unknown parameters. It is cleared for dynamic realtime to allow
  2774. * extra fields in the tables.
  2775. * \note For error reporting, line number is passed for .conf static configuration,
  2776. * for Realtime queues, linenum is -1.
  2777. */
  2778. static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
  2779. {
  2780. if (!strcasecmp(param, "musicclass") ||
  2781. !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
  2782. ast_string_field_set(q, moh, val);
  2783. } else if (!strcasecmp(param, "announce")) {
  2784. ast_string_field_set(q, announce, val);
  2785. } else if (!strcasecmp(param, "context")) {
  2786. ast_string_field_set(q, context, val);
  2787. } else if (!strcasecmp(param, "timeout")) {
  2788. q->timeout = atoi(val);
  2789. if (q->timeout < 0) {
  2790. q->timeout = DEFAULT_TIMEOUT;
  2791. }
  2792. } else if (!strcasecmp(param, "ringinuse")) {
  2793. q->ringinuse = ast_true(val);
  2794. } else if (!strcasecmp(param, "setinterfacevar")) {
  2795. q->setinterfacevar = ast_true(val);
  2796. } else if (!strcasecmp(param, "setqueuevar")) {
  2797. q->setqueuevar = ast_true(val);
  2798. } else if (!strcasecmp(param, "setqueueentryvar")) {
  2799. q->setqueueentryvar = ast_true(val);
  2800. } else if (!strcasecmp(param, "monitor-format")) {
  2801. ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
  2802. } else if (!strcasecmp(param, "membermacro")) {
  2803. ast_string_field_set(q, membermacro, val);
  2804. } else if (!strcasecmp(param, "membergosub")) {
  2805. ast_string_field_set(q, membergosub, val);
  2806. } else if (!strcasecmp(param, "queue-youarenext")) {
  2807. ast_string_field_set(q, sound_next, val);
  2808. } else if (!strcasecmp(param, "queue-thereare")) {
  2809. ast_string_field_set(q, sound_thereare, val);
  2810. } else if (!strcasecmp(param, "queue-callswaiting")) {
  2811. ast_string_field_set(q, sound_calls, val);
  2812. } else if (!strcasecmp(param, "queue-quantity1")) {
  2813. ast_string_field_set(q, queue_quantity1, val);
  2814. } else if (!strcasecmp(param, "queue-quantity2")) {
  2815. ast_string_field_set(q, queue_quantity2, val);
  2816. } else if (!strcasecmp(param, "queue-holdtime")) {
  2817. ast_string_field_set(q, sound_holdtime, val);
  2818. } else if (!strcasecmp(param, "queue-minutes")) {
  2819. ast_string_field_set(q, sound_minutes, val);
  2820. } else if (!strcasecmp(param, "queue-minute")) {
  2821. ast_string_field_set(q, sound_minute, val);
  2822. } else if (!strcasecmp(param, "queue-seconds")) {
  2823. ast_string_field_set(q, sound_seconds, val);
  2824. } else if (!strcasecmp(param, "queue-thankyou")) {
  2825. ast_string_field_set(q, sound_thanks, val);
  2826. } else if (!strcasecmp(param, "queue-callerannounce")) {
  2827. ast_string_field_set(q, sound_callerannounce, val);
  2828. } else if (!strcasecmp(param, "queue-reporthold")) {
  2829. ast_string_field_set(q, sound_reporthold, val);
  2830. } else if (!strcasecmp(param, "announce-frequency")) {
  2831. q->announcefrequency = atoi(val);
  2832. } else if (!strcasecmp(param, "announce-to-first-user")) {
  2833. q->announce_to_first_user = ast_true(val);
  2834. } else if (!strcasecmp(param, "min-announce-frequency")) {
  2835. q->minannouncefrequency = atoi(val);
  2836. ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
  2837. } else if (!strcasecmp(param, "announce-round-seconds")) {
  2838. q->roundingseconds = atoi(val);
  2839. /* Rounding to any other values just doesn't make sense... */
  2840. if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
  2841. || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
  2842. if (linenum >= 0) {
  2843. ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
  2844. "using 0 instead for queue '%s' at line %d of queues.conf\n",
  2845. val, param, q->name, linenum);
  2846. } else {
  2847. ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
  2848. "using 0 instead for queue '%s'\n", val, param, q->name);
  2849. }
  2850. q->roundingseconds=0;
  2851. }
  2852. } else if (!strcasecmp(param, "announce-holdtime")) {
  2853. if (!strcasecmp(val, "once")) {
  2854. q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
  2855. } else if (ast_true(val)) {
  2856. q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
  2857. } else {
  2858. q->announceholdtime = 0;
  2859. }
  2860. } else if (!strcasecmp(param, "announce-position")) {
  2861. if (!strcasecmp(val, "limit")) {
  2862. q->announceposition = ANNOUNCEPOSITION_LIMIT;
  2863. } else if (!strcasecmp(val, "more")) {
  2864. q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
  2865. } else if (ast_true(val)) {
  2866. q->announceposition = ANNOUNCEPOSITION_YES;
  2867. } else {
  2868. q->announceposition = ANNOUNCEPOSITION_NO;
  2869. }
  2870. } else if (!strcasecmp(param, "announce-position-limit")) {
  2871. q->announcepositionlimit = atoi(val);
  2872. } else if (!strcasecmp(param, "periodic-announce")) {
  2873. if (strchr(val, ',')) {
  2874. char *s, *buf = ast_strdupa(val);
  2875. unsigned int i = 0;
  2876. while ((s = strsep(&buf, ",|"))) {
  2877. if (!q->sound_periodicannounce[i]) {
  2878. q->sound_periodicannounce[i] = ast_str_create(16);
  2879. }
  2880. ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
  2881. i++;
  2882. if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
  2883. break;
  2884. }
  2885. }
  2886. q->numperiodicannounce = i;
  2887. } else {
  2888. ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
  2889. q->numperiodicannounce = 1;
  2890. }
  2891. } else if (!strcasecmp(param, "periodic-announce-frequency")) {
  2892. q->periodicannouncefrequency = atoi(val);
  2893. } else if (!strcasecmp(param, "relative-periodic-announce")) {
  2894. q->relativeperiodicannounce = ast_true(val);
  2895. } else if (!strcasecmp(param, "random-periodic-announce")) {
  2896. q->randomperiodicannounce = ast_true(val);
  2897. } else if (!strcasecmp(param, "retry")) {
  2898. q->retry = atoi(val);
  2899. if (q->retry <= 0) {
  2900. q->retry = DEFAULT_RETRY;
  2901. }
  2902. } else if (!strcasecmp(param, "wrapuptime")) {
  2903. q->wrapuptime = atoi(val);
  2904. } else if (!strcasecmp(param, "penaltymemberslimit")) {
  2905. if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
  2906. q->penaltymemberslimit = 0;
  2907. }
  2908. } else if (!strcasecmp(param, "autofill")) {
  2909. q->autofill = ast_true(val);
  2910. } else if (!strcasecmp(param, "monitor-type")) {
  2911. if (!strcasecmp(val, "mixmonitor")) {
  2912. q->montype = 1;
  2913. }
  2914. } else if (!strcasecmp(param, "autopause")) {
  2915. q->autopause = autopause2int(val);
  2916. } else if (!strcasecmp(param, "autopausedelay")) {
  2917. q->autopausedelay = atoi(val);
  2918. } else if (!strcasecmp(param, "autopausebusy")) {
  2919. q->autopausebusy = ast_true(val);
  2920. } else if (!strcasecmp(param, "autopauseunavail")) {
  2921. q->autopauseunavail = ast_true(val);
  2922. } else if (!strcasecmp(param, "maxlen")) {
  2923. q->maxlen = atoi(val);
  2924. if (q->maxlen < 0) {
  2925. q->maxlen = 0;
  2926. }
  2927. } else if (!strcasecmp(param, "servicelevel")) {
  2928. q->servicelevel= atoi(val);
  2929. } else if (!strcasecmp(param, "strategy")) {
  2930. int strategy;
  2931. /* We are a static queue and already have set this, no need to do it again */
  2932. if (failunknown) {
  2933. return;
  2934. }
  2935. strategy = strat2int(val);
  2936. if (strategy < 0) {
  2937. ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
  2938. val, q->name);
  2939. q->strategy = QUEUE_STRATEGY_RINGALL;
  2940. }
  2941. if (strategy == q->strategy) {
  2942. return;
  2943. }
  2944. if (strategy == QUEUE_STRATEGY_LINEAR) {
  2945. ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
  2946. return;
  2947. }
  2948. q->strategy = strategy;
  2949. } else if (!strcasecmp(param, "joinempty")) {
  2950. parse_empty_options(val, &q->joinempty, 1);
  2951. } else if (!strcasecmp(param, "leavewhenempty")) {
  2952. parse_empty_options(val, &q->leavewhenempty, 0);
  2953. } else if (!strcasecmp(param, "reportholdtime")) {
  2954. q->reportholdtime = ast_true(val);
  2955. } else if (!strcasecmp(param, "memberdelay")) {
  2956. q->memberdelay = atoi(val);
  2957. } else if (!strcasecmp(param, "weight")) {
  2958. q->weight = atoi(val);
  2959. } else if (!strcasecmp(param, "timeoutrestart")) {
  2960. q->timeoutrestart = ast_true(val);
  2961. } else if (!strcasecmp(param, "defaultrule")) {
  2962. ast_string_field_set(q, defaultrule, val);
  2963. } else if (!strcasecmp(param, "timeoutpriority")) {
  2964. if (!strcasecmp(val, "conf")) {
  2965. q->timeoutpriority = TIMEOUT_PRIORITY_CONF;
  2966. } else {
  2967. q->timeoutpriority = TIMEOUT_PRIORITY_APP;
  2968. }
  2969. } else if (failunknown) {
  2970. if (linenum >= 0) {
  2971. ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
  2972. q->name, param, linenum);
  2973. } else {
  2974. ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
  2975. }
  2976. }
  2977. }
  2978. #define QUEUE_PAUSED_DEVSTATE AST_DEVICE_INUSE
  2979. #define QUEUE_UNPAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
  2980. #define QUEUE_UNKNOWN_PAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
  2981. /*! \internal
  2982. * \brief If adding a single new member to a queue, use this function instead of ao2_linking.
  2983. * This adds round robin queue position data for a fresh member as well as links it.
  2984. * \param queue Which queue the member is being added to
  2985. * \param mem Which member is being added to the queue
  2986. */
  2987. static void member_add_to_queue(struct call_queue *queue, struct member *mem)
  2988. {
  2989. ao2_lock(queue->members);
  2990. mem->queuepos = ao2_container_count(queue->members);
  2991. ao2_link(queue->members, mem);
  2992. ast_devstate_changed(mem->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
  2993. AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", queue->name, mem->interface);
  2994. ao2_unlock(queue->members);
  2995. }
  2996. /*! \internal
  2997. * \brief If removing a single member from a queue, use this function instead of ao2_unlinking.
  2998. * This will perform round robin queue position reordering for the remaining members.
  2999. * \param queue Which queue the member is being removed from
  3000. * \param member Which member is being removed from the queue
  3001. */
  3002. static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
  3003. {
  3004. pending_members_remove(mem);
  3005. ao2_lock(queue->members);
  3006. ast_devstate_changed(QUEUE_UNKNOWN_PAUSED_DEVSTATE, AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", queue->name, mem->interface);
  3007. queue_member_follower_removal(queue, mem);
  3008. ao2_unlink(queue->members, mem);
  3009. ao2_unlock(queue->members);
  3010. }
  3011. /*!
  3012. * \brief Find rt member record to update otherwise create one.
  3013. *
  3014. * Search for member in queue, if found update penalty/paused state,
  3015. * if no member exists create one flag it as a RT member and add to queue member list.
  3016. */
  3017. static void rt_handle_member_record(struct call_queue *q, char *category, struct ast_config *member_config)
  3018. {
  3019. struct member *m;
  3020. struct ao2_iterator mem_iter;
  3021. int penalty = 0;
  3022. int paused = 0;
  3023. int found = 0;
  3024. int ringinuse = q->ringinuse;
  3025. const char *config_val;
  3026. const char *interface = ast_variable_retrieve(member_config, category, "interface");
  3027. const char *rt_uniqueid = ast_variable_retrieve(member_config, category, "uniqueid");
  3028. const char *membername = S_OR(ast_variable_retrieve(member_config, category, "membername"), interface);
  3029. const char *state_interface = S_OR(ast_variable_retrieve(member_config, category, "state_interface"), interface);
  3030. const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty");
  3031. const char *paused_str = ast_variable_retrieve(member_config, category, "paused");
  3032. if (ast_strlen_zero(rt_uniqueid)) {
  3033. ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
  3034. return;
  3035. }
  3036. if (penalty_str) {
  3037. penalty = atoi(penalty_str);
  3038. if ((penalty < 0) && negative_penalty_invalid) {
  3039. return;
  3040. } else if (penalty < 0) {
  3041. penalty = 0;
  3042. }
  3043. }
  3044. if (paused_str) {
  3045. paused = atoi(paused_str);
  3046. if (paused < 0) {
  3047. paused = 0;
  3048. }
  3049. }
  3050. if ((config_val = ast_variable_retrieve(member_config, category, realtime_ringinuse_field))) {
  3051. if (ast_true(config_val)) {
  3052. ringinuse = 1;
  3053. } else if (ast_false(config_val)) {
  3054. ringinuse = 0;
  3055. } else {
  3056. ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);
  3057. }
  3058. }
  3059. /* Find member by realtime uniqueid and update */
  3060. mem_iter = ao2_iterator_init(q->members, 0);
  3061. while ((m = ao2_iterator_next(&mem_iter))) {
  3062. if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
  3063. m->dead = 0; /* Do not delete this one. */
  3064. ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
  3065. if (paused_str) {
  3066. m->paused = paused;
  3067. ast_devstate_changed(m->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
  3068. AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", q->name, m->interface);
  3069. }
  3070. if (strcasecmp(state_interface, m->state_interface)) {
  3071. ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
  3072. }
  3073. m->penalty = penalty;
  3074. m->ringinuse = ringinuse;
  3075. found = 1;
  3076. ao2_ref(m, -1);
  3077. break;
  3078. }
  3079. ao2_ref(m, -1);
  3080. }
  3081. ao2_iterator_destroy(&mem_iter);
  3082. /* Create a new member */
  3083. if (!found) {
  3084. if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse))) {
  3085. m->dead = 0;
  3086. m->realtime = 1;
  3087. ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
  3088. if (!log_membername_as_agent) {
  3089. ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
  3090. } else {
  3091. ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
  3092. }
  3093. member_add_to_queue(q, m);
  3094. ao2_ref(m, -1);
  3095. m = NULL;
  3096. }
  3097. }
  3098. }
  3099. /*! \brief Iterate through queue's member list and delete them */
  3100. static void free_members(struct call_queue *q, int all)
  3101. {
  3102. /* Free non-dynamic members */
  3103. struct member *cur;
  3104. struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
  3105. while ((cur = ao2_iterator_next(&mem_iter))) {
  3106. if (all || !cur->dynamic) {
  3107. member_remove_from_queue(q, cur);
  3108. }
  3109. ao2_ref(cur, -1);
  3110. }
  3111. ao2_iterator_destroy(&mem_iter);
  3112. }
  3113. /*! \brief Free queue's member list then its string fields */
  3114. static void destroy_queue(void *obj)
  3115. {
  3116. struct call_queue *q = obj;
  3117. int i;
  3118. free_members(q, 1);
  3119. ast_string_field_free_memory(q);
  3120. for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
  3121. if (q->sound_periodicannounce[i]) {
  3122. free(q->sound_periodicannounce[i]);
  3123. }
  3124. }
  3125. ao2_ref(q->members, -1);
  3126. }
  3127. static struct call_queue *alloc_queue(const char *queuename)
  3128. {
  3129. struct call_queue *q;
  3130. if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
  3131. if (ast_string_field_init(q, 64)) {
  3132. queue_t_unref(q, "String field allocation failed");
  3133. return NULL;
  3134. }
  3135. ast_string_field_set(q, name, queuename);
  3136. }
  3137. return q;
  3138. }
  3139. /*!
  3140. * \brief Reload a single queue via realtime.
  3141. *
  3142. * Check for statically defined queue first, check if deleted RT queue,
  3143. * check for new RT queue, if queue vars are not defined init them with defaults.
  3144. * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
  3145. * \retval the queue,
  3146. * \retval NULL if it doesn't exist.
  3147. * \note Should be called with the "queues" container locked.
  3148. */
  3149. static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
  3150. {
  3151. struct ast_variable *v;
  3152. struct call_queue *q, tmpq = {
  3153. .name = queuename,
  3154. };
  3155. struct member *m;
  3156. struct ao2_iterator mem_iter;
  3157. char *category = NULL;
  3158. const char *tmp_name;
  3159. char *tmp;
  3160. char tmpbuf[64]; /* Must be longer than the longest queue param name. */
  3161. /* Static queues override realtime. */
  3162. if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
  3163. ao2_lock(q);
  3164. if (!q->realtime) {
  3165. if (q->dead) {
  3166. ao2_unlock(q);
  3167. queue_t_unref(q, "Queue is dead; can't return it");
  3168. return NULL;
  3169. }
  3170. ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
  3171. ao2_unlock(q);
  3172. return q;
  3173. }
  3174. } else if (!member_config) {
  3175. /* Not found in the list, and it's not realtime ... */
  3176. return NULL;
  3177. }
  3178. /* Check if queue is defined in realtime. */
  3179. if (!queue_vars) {
  3180. /* Delete queue from in-core list if it has been deleted in realtime. */
  3181. if (q) {
  3182. /*! \note Hmm, can't seem to distinguish a DB failure from a not
  3183. found condition... So we might delete an in-core queue
  3184. in case of DB failure. */
  3185. ast_debug(1, "Queue %s not found in realtime.\n", queuename);
  3186. q->dead = 1;
  3187. /* Delete if unused (else will be deleted when last caller leaves). */
  3188. queues_t_unlink(queues, q, "Unused; removing from container");
  3189. ao2_unlock(q);
  3190. queue_t_unref(q, "Queue is dead; can't return it");
  3191. }
  3192. return NULL;
  3193. }
  3194. /* Create a new queue if an in-core entry does not exist yet. */
  3195. if (!q) {
  3196. struct ast_variable *tmpvar = NULL;
  3197. if (!(q = alloc_queue(queuename))) {
  3198. return NULL;
  3199. }
  3200. ao2_lock(q);
  3201. clear_queue(q);
  3202. q->realtime = 1;
  3203. /*Before we initialize the queue, we need to set the strategy, so that linear strategy
  3204. * will allocate the members properly
  3205. */
  3206. for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
  3207. if (!strcasecmp(tmpvar->name, "strategy")) {
  3208. q->strategy = strat2int(tmpvar->value);
  3209. if (q->strategy < 0) {
  3210. ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
  3211. tmpvar->value, q->name);
  3212. q->strategy = QUEUE_STRATEGY_RINGALL;
  3213. }
  3214. break;
  3215. }
  3216. }
  3217. /* We traversed all variables and didn't find a strategy */
  3218. if (!tmpvar) {
  3219. q->strategy = QUEUE_STRATEGY_RINGALL;
  3220. }
  3221. queues_t_link(queues, q, "Add queue to container");
  3222. }
  3223. init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
  3224. memset(tmpbuf, 0, sizeof(tmpbuf));
  3225. for (v = queue_vars; v; v = v->next) {
  3226. /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
  3227. if (strchr(v->name, '_')) {
  3228. ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
  3229. tmp_name = tmpbuf;
  3230. tmp = tmpbuf;
  3231. while ((tmp = strchr(tmp, '_'))) {
  3232. *tmp++ = '-';
  3233. }
  3234. } else {
  3235. tmp_name = v->name;
  3236. }
  3237. /* NULL values don't get returned from realtime; blank values should
  3238. * still get set. If someone doesn't want a value to be set, they
  3239. * should set the realtime column to NULL, not blank. */
  3240. queue_set_param(q, tmp_name, v->value, -1, 0);
  3241. }
  3242. /* Temporarily set realtime members dead so we can detect deleted ones. */
  3243. mem_iter = ao2_iterator_init(q->members, 0);
  3244. while ((m = ao2_iterator_next(&mem_iter))) {
  3245. if (m->realtime) {
  3246. m->dead = 1;
  3247. }
  3248. ao2_ref(m, -1);
  3249. }
  3250. ao2_iterator_destroy(&mem_iter);
  3251. while ((category = ast_category_browse(member_config, category))) {
  3252. rt_handle_member_record(q, category, member_config);
  3253. }
  3254. /* Delete all realtime members that have been deleted in DB. */
  3255. mem_iter = ao2_iterator_init(q->members, 0);
  3256. while ((m = ao2_iterator_next(&mem_iter))) {
  3257. if (m->dead) {
  3258. if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
  3259. ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
  3260. } else {
  3261. ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
  3262. }
  3263. member_remove_from_queue(q, m);
  3264. }
  3265. ao2_ref(m, -1);
  3266. }
  3267. ao2_iterator_destroy(&mem_iter);
  3268. ao2_unlock(q);
  3269. return q;
  3270. }
  3271. /*!
  3272. * note */
  3273. /*!
  3274. * \internal
  3275. * \brief Returns reference to the named queue. If the queue is realtime, it will load the queue as well.
  3276. * \param queuename - name of the desired queue
  3277. *
  3278. * \retval the queue
  3279. * \retval NULL if it doesn't exist
  3280. */
  3281. static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
  3282. {
  3283. struct ast_variable *queue_vars;
  3284. struct ast_config *member_config = NULL;
  3285. struct call_queue *q = NULL, tmpq = {
  3286. .name = queuename,
  3287. };
  3288. int prev_weight = 0;
  3289. /* Find the queue in the in-core list first. */
  3290. q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
  3291. if (!q || q->realtime) {
  3292. /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
  3293. queue operations while waiting for the DB.
  3294. This will be two separate database transactions, so we might
  3295. see queue parameters as they were before another process
  3296. changed the queue and member list as it was after the change.
  3297. Thus we might see an empty member list when a queue is
  3298. deleted. In practise, this is unlikely to cause a problem. */
  3299. queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
  3300. if (queue_vars) {
  3301. member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
  3302. if (!member_config) {
  3303. ast_debug(1, "No queue_members defined in config extconfig.conf\n");
  3304. member_config = ast_config_new();
  3305. }
  3306. }
  3307. if (q) {
  3308. prev_weight = q->weight ? 1 : 0;
  3309. queue_t_unref(q, "Need to find realtime queue");
  3310. }
  3311. q = find_queue_by_name_rt(queuename, queue_vars, member_config);
  3312. ast_config_destroy(member_config);
  3313. ast_variables_destroy(queue_vars);
  3314. /* update the use_weight value if the queue's has gained or lost a weight */
  3315. if (q) {
  3316. if (!q->weight && prev_weight) {
  3317. ast_atomic_fetchadd_int(&use_weight, -1);
  3318. }
  3319. if (q->weight && !prev_weight) {
  3320. ast_atomic_fetchadd_int(&use_weight, +1);
  3321. }
  3322. }
  3323. /* Other cases will end up with the proper value for use_weight */
  3324. } else {
  3325. update_realtime_members(q);
  3326. }
  3327. return q;
  3328. }
  3329. static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
  3330. {
  3331. int ret = -1;
  3332. if (ast_strlen_zero(mem->rt_uniqueid)) {
  3333. return ret;
  3334. }
  3335. if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0) {
  3336. ret = 0;
  3337. }
  3338. return ret;
  3339. }
  3340. static void update_realtime_members(struct call_queue *q)
  3341. {
  3342. struct ast_config *member_config = NULL;
  3343. struct member *m;
  3344. char *category = NULL;
  3345. struct ao2_iterator mem_iter;
  3346. if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
  3347. /* This queue doesn't have realtime members. If the queue still has any realtime
  3348. * members in memory, they need to be removed.
  3349. */
  3350. ao2_lock(q);
  3351. mem_iter = ao2_iterator_init(q->members, 0);
  3352. while ((m = ao2_iterator_next(&mem_iter))) {
  3353. if (m->realtime) {
  3354. member_remove_from_queue(q, m);
  3355. }
  3356. ao2_ref(m, -1);
  3357. }
  3358. ao2_iterator_destroy(&mem_iter);
  3359. ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
  3360. ao2_unlock(q);
  3361. return;
  3362. }
  3363. ao2_lock(q);
  3364. /* Temporarily set realtime members dead so we can detect deleted ones.*/
  3365. mem_iter = ao2_iterator_init(q->members, 0);
  3366. while ((m = ao2_iterator_next(&mem_iter))) {
  3367. if (m->realtime) {
  3368. m->dead = 1;
  3369. }
  3370. ao2_ref(m, -1);
  3371. }
  3372. ao2_iterator_destroy(&mem_iter);
  3373. while ((category = ast_category_browse(member_config, category))) {
  3374. rt_handle_member_record(q, category, member_config);
  3375. }
  3376. /* Delete all realtime members that have been deleted in DB. */
  3377. mem_iter = ao2_iterator_init(q->members, 0);
  3378. while ((m = ao2_iterator_next(&mem_iter))) {
  3379. if (m->dead) {
  3380. if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
  3381. ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
  3382. } else {
  3383. ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
  3384. }
  3385. member_remove_from_queue(q, m);
  3386. }
  3387. ao2_ref(m, -1);
  3388. }
  3389. ao2_iterator_destroy(&mem_iter);
  3390. ao2_unlock(q);
  3391. ast_config_destroy(member_config);
  3392. }
  3393. static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
  3394. {
  3395. struct call_queue *q;
  3396. struct queue_ent *cur, *prev = NULL;
  3397. int res = -1;
  3398. int pos = 0;
  3399. int inserted = 0;
  3400. if (!(q = find_load_queue_rt_friendly(queuename))) {
  3401. return res;
  3402. }
  3403. ao2_lock(q);
  3404. /* This is our one */
  3405. if (q->joinempty) {
  3406. int status = 0;
  3407. if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty, 0))) {
  3408. *reason = QUEUE_JOINEMPTY;
  3409. ao2_unlock(q);
  3410. queue_t_unref(q, "Done with realtime queue");
  3411. return res;
  3412. }
  3413. }
  3414. if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
  3415. *reason = QUEUE_FULL;
  3416. } else if (*reason == QUEUE_UNKNOWN) {
  3417. RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
  3418. /* There's space for us, put us at the right position inside
  3419. * the queue.
  3420. * Take into account the priority of the calling user */
  3421. inserted = 0;
  3422. prev = NULL;
  3423. cur = q->head;
  3424. while (cur) {
  3425. /* We have higher priority than the current user, enter
  3426. * before him, after all the other users with priority
  3427. * higher or equal to our priority. */
  3428. if ((!inserted) && (qe->prio > cur->prio)) {
  3429. insert_entry(q, prev, qe, &pos);
  3430. inserted = 1;
  3431. }
  3432. /* <= is necessary for the position comparison because it may not be possible to enter
  3433. * at our desired position since higher-priority callers may have taken the position we want
  3434. */
  3435. if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
  3436. insert_entry(q, prev, qe, &pos);
  3437. inserted = 1;
  3438. /*pos is incremented inside insert_entry, so don't need to add 1 here*/
  3439. if (position < pos) {
  3440. ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
  3441. }
  3442. }
  3443. cur->pos = ++pos;
  3444. prev = cur;
  3445. cur = cur->next;
  3446. }
  3447. /* No luck, join at the end of the queue */
  3448. if (!inserted) {
  3449. insert_entry(q, prev, qe, &pos);
  3450. }
  3451. ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
  3452. ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
  3453. ast_copy_string(qe->context, q->context, sizeof(qe->context));
  3454. q->count++;
  3455. if (q->count == 1) {
  3456. ast_devstate_changed(AST_DEVICE_RINGING, AST_DEVSTATE_CACHABLE, "Queue:%s", q->name);
  3457. }
  3458. res = 0;
  3459. blob = ast_json_pack("{s: s, s: i, s: i}",
  3460. "Queue", q->name,
  3461. "Position", qe->pos,
  3462. "Count", q->count);
  3463. ast_channel_publish_cached_blob(qe->chan, queue_caller_join_type(), blob);
  3464. ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
  3465. }
  3466. ao2_unlock(q);
  3467. queue_t_unref(q, "Done with realtime queue");
  3468. return res;
  3469. }
  3470. static int play_file(struct ast_channel *chan, const char *filename)
  3471. {
  3472. int res;
  3473. if (ast_strlen_zero(filename)) {
  3474. return 0;
  3475. }
  3476. if (!ast_fileexists(filename, NULL, ast_channel_language(chan))) {
  3477. return 0;
  3478. }
  3479. ast_stopstream(chan);
  3480. res = ast_streamfile(chan, filename, ast_channel_language(chan));
  3481. if (!res) {
  3482. res = ast_waitstream(chan, AST_DIGIT_ANY);
  3483. }
  3484. ast_stopstream(chan);
  3485. return res;
  3486. }
  3487. /*!
  3488. * \brief Check for valid exit from queue via goto
  3489. * \retval 0 if failure
  3490. * \retval 1 if successful
  3491. */
  3492. static int valid_exit(struct queue_ent *qe, char digit)
  3493. {
  3494. int digitlen = strlen(qe->digits);
  3495. /* Prevent possible buffer overflow */
  3496. if (digitlen < sizeof(qe->digits) - 2) {
  3497. qe->digits[digitlen] = digit;
  3498. qe->digits[digitlen + 1] = '\0';
  3499. } else {
  3500. qe->digits[0] = '\0';
  3501. return 0;
  3502. }
  3503. /* If there's no context to goto, short-circuit */
  3504. if (ast_strlen_zero(qe->context)) {
  3505. return 0;
  3506. }
  3507. /* If the extension is bad, then reset the digits to blank */
  3508. if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
  3509. S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, NULL))) {
  3510. qe->digits[0] = '\0';
  3511. return 0;
  3512. }
  3513. /* We have an exact match */
  3514. if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
  3515. qe->valid_digits = 1;
  3516. /* Return 1 on a successful goto */
  3517. return 1;
  3518. }
  3519. return 0;
  3520. }
  3521. static int say_position(struct queue_ent *qe, int ringing)
  3522. {
  3523. int res = 0, announceposition = 0;
  3524. long avgholdmins, avgholdsecs;
  3525. int say_thanks = 1;
  3526. time_t now;
  3527. /* Let minannouncefrequency seconds pass between the start of each position announcement */
  3528. time(&now);
  3529. if ((now - qe->last_pos) < qe->parent->minannouncefrequency) {
  3530. return 0;
  3531. }
  3532. /* If either our position has changed, or we are over the freq timer, say position */
  3533. if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency)) {
  3534. return 0;
  3535. }
  3536. if (ringing) {
  3537. ast_indicate(qe->chan,-1);
  3538. } else {
  3539. ast_moh_stop(qe->chan);
  3540. }
  3541. if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
  3542. qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
  3543. (qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
  3544. qe->pos <= qe->parent->announcepositionlimit)) {
  3545. announceposition = 1;
  3546. }
  3547. if (announceposition == 1) {
  3548. /* Say we're next, if we are */
  3549. if (qe->pos == 1) {
  3550. res = play_file(qe->chan, qe->parent->sound_next);
  3551. if (res) {
  3552. goto playout;
  3553. }
  3554. goto posout;
  3555. } else {
  3556. if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
  3557. /* More than Case*/
  3558. res = play_file(qe->chan, qe->parent->queue_quantity1);
  3559. if (res) {
  3560. goto playout;
  3561. }
  3562. res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
  3563. if (res) {
  3564. goto playout;
  3565. }
  3566. } else {
  3567. /* Normal Case */
  3568. res = play_file(qe->chan, qe->parent->sound_thereare);
  3569. if (res) {
  3570. goto playout;
  3571. }
  3572. res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
  3573. if (res) {
  3574. goto playout;
  3575. }
  3576. }
  3577. if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
  3578. /* More than Case*/
  3579. res = play_file(qe->chan, qe->parent->queue_quantity2);
  3580. if (res) {
  3581. goto playout;
  3582. }
  3583. } else {
  3584. res = play_file(qe->chan, qe->parent->sound_calls);
  3585. if (res) {
  3586. goto playout;
  3587. }
  3588. }
  3589. }
  3590. }
  3591. /* Round hold time to nearest minute */
  3592. avgholdmins = labs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
  3593. /* If they have specified a rounding then round the seconds as well */
  3594. if (qe->parent->roundingseconds) {
  3595. avgholdsecs = (labs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
  3596. avgholdsecs *= qe->parent->roundingseconds;
  3597. } else {
  3598. avgholdsecs = 0;
  3599. }
  3600. ast_verb(3, "Hold time for %s is %ld minute(s) %ld seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
  3601. /* If the hold time is >1 min, if it's enabled, and if it's not
  3602. supposed to be only once and we have already said it, say it */
  3603. if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
  3604. ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
  3605. !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
  3606. res = play_file(qe->chan, qe->parent->sound_holdtime);
  3607. if (res) {
  3608. goto playout;
  3609. }
  3610. if (avgholdmins >= 1) {
  3611. res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
  3612. if (res) {
  3613. goto playout;
  3614. }
  3615. if (avgholdmins == 1) {
  3616. res = play_file(qe->chan, qe->parent->sound_minute);
  3617. if (res) {
  3618. goto playout;
  3619. }
  3620. } else {
  3621. res = play_file(qe->chan, qe->parent->sound_minutes);
  3622. if (res) {
  3623. goto playout;
  3624. }
  3625. }
  3626. }
  3627. if (avgholdsecs >= 1) {
  3628. res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
  3629. if (res) {
  3630. goto playout;
  3631. }
  3632. res = play_file(qe->chan, qe->parent->sound_seconds);
  3633. if (res) {
  3634. goto playout;
  3635. }
  3636. }
  3637. } else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
  3638. say_thanks = 0;
  3639. }
  3640. posout:
  3641. if (qe->parent->announceposition) {
  3642. ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
  3643. ast_channel_name(qe->chan), qe->parent->name, qe->pos);
  3644. }
  3645. if (say_thanks) {
  3646. res = play_file(qe->chan, qe->parent->sound_thanks);
  3647. }
  3648. playout:
  3649. if ((res > 0 && !valid_exit(qe, res))) {
  3650. res = 0;
  3651. }
  3652. /* Set our last_pos indicators */
  3653. qe->last_pos = now;
  3654. qe->last_pos_said = qe->pos;
  3655. /* Don't restart music on hold if we're about to exit the caller from the queue */
  3656. if (!res) {
  3657. if (ringing) {
  3658. ast_indicate(qe->chan, AST_CONTROL_RINGING);
  3659. } else {
  3660. ast_moh_start(qe->chan, qe->moh, NULL);
  3661. }
  3662. }
  3663. return res;
  3664. }
  3665. static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
  3666. {
  3667. int oldvalue;
  3668. /* Calculate holdtime using an exponential average */
  3669. /* Thanks to SRT for this contribution */
  3670. /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
  3671. ao2_lock(qe->parent);
  3672. if ((qe->parent->callscompleted + qe->parent->callsabandoned) == 0) {
  3673. qe->parent->holdtime = newholdtime;
  3674. } else {
  3675. oldvalue = qe->parent->holdtime;
  3676. qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
  3677. }
  3678. ao2_unlock(qe->parent);
  3679. }
  3680. /*! \brief Caller leaving queue.
  3681. *
  3682. * Search the queue to find the leaving client, if found remove from queue
  3683. * create manager event, move others up the queue.
  3684. */
  3685. static void leave_queue(struct queue_ent *qe)
  3686. {
  3687. struct call_queue *q;
  3688. struct queue_ent *current, *prev = NULL;
  3689. struct penalty_rule *pr_iter;
  3690. int pos = 0;
  3691. if (!(q = qe->parent)) {
  3692. return;
  3693. }
  3694. queue_t_ref(q, "Copy queue pointer from queue entry");
  3695. ao2_lock(q);
  3696. prev = NULL;
  3697. for (current = q->head; current; current = current->next) {
  3698. if (current == qe) {
  3699. RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
  3700. char posstr[20];
  3701. q->count--;
  3702. if (!q->count) {
  3703. ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s", q->name);
  3704. }
  3705. blob = ast_json_pack("{s: s, s: i, s: i}",
  3706. "Queue", q->name,
  3707. "Position", qe->pos,
  3708. "Count", q->count);
  3709. ast_channel_publish_cached_blob(qe->chan, queue_caller_leave_type(), blob);
  3710. ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
  3711. /* Take us out of the queue */
  3712. if (prev) {
  3713. prev->next = current->next;
  3714. } else {
  3715. q->head = current->next;
  3716. }
  3717. /* Free penalty rules */
  3718. while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list))) {
  3719. ast_free(pr_iter);
  3720. }
  3721. qe->pr = NULL;
  3722. snprintf(posstr, sizeof(posstr), "%d", qe->pos);
  3723. pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
  3724. } else {
  3725. /* Renumber the people after us in the queue based on a new count */
  3726. current->pos = ++pos;
  3727. prev = current;
  3728. }
  3729. }
  3730. ao2_unlock(q);
  3731. /*If the queue is a realtime queue, check to see if it's still defined in real time*/
  3732. if (q->realtime) {
  3733. struct ast_variable *var;
  3734. if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
  3735. q->dead = 1;
  3736. } else {
  3737. ast_variables_destroy(var);
  3738. }
  3739. }
  3740. if (q->dead) {
  3741. /* It's dead and nobody is in it, so kill it */
  3742. queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
  3743. }
  3744. /* unref the explicit ref earlier in the function */
  3745. queue_t_unref(q, "Expire copied reference");
  3746. }
  3747. /*!
  3748. * \internal
  3749. * \brief Destroy the given callattempt structure and free it.
  3750. * \since 1.8
  3751. *
  3752. * \param doomed callattempt structure to destroy.
  3753. *
  3754. * \return Nothing
  3755. */
  3756. static void callattempt_free(struct callattempt *doomed)
  3757. {
  3758. if (doomed->member) {
  3759. ao2_ref(doomed->member, -1);
  3760. }
  3761. ast_party_connected_line_free(&doomed->connected);
  3762. ast_free(doomed->orig_chan_name);
  3763. ast_free(doomed);
  3764. }
  3765. static void publish_dial_end_event(struct ast_channel *in, struct callattempt *outgoing, struct ast_channel *exception, const char *status)
  3766. {
  3767. struct callattempt *cur;
  3768. for (cur = outgoing; cur; cur = cur->q_next) {
  3769. if (cur->chan && cur->chan != exception) {
  3770. ast_channel_publish_dial(in, cur->chan, NULL, status);
  3771. }
  3772. }
  3773. }
  3774. /*! \brief Hang up a list of outgoing calls */
  3775. static void hangupcalls(struct queue_ent *qe, struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
  3776. {
  3777. struct callattempt *oo;
  3778. while (outgoing) {
  3779. /* If someone else answered the call we should indicate this in the CANCEL */
  3780. /* Hangup any existing lines we have open */
  3781. if (outgoing->chan && (outgoing->chan != exception)) {
  3782. if (exception || cancel_answered_elsewhere) {
  3783. ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
  3784. }
  3785. ast_channel_publish_dial(qe->chan, outgoing->chan, outgoing->interface, "CANCEL");
  3786. /* When dialing channels it is possible that they may not ever
  3787. * leave the not in use state (Local channels in particular) by
  3788. * the time we cancel them. If this occurs but we know they were
  3789. * dialed we explicitly remove them from the pending members
  3790. * container so that subsequent call attempts occur.
  3791. */
  3792. if (outgoing->member->status == AST_DEVICE_NOT_INUSE) {
  3793. pending_members_remove(outgoing->member);
  3794. }
  3795. ast_hangup(outgoing->chan);
  3796. }
  3797. oo = outgoing;
  3798. outgoing = outgoing->q_next;
  3799. ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
  3800. callattempt_free(oo);
  3801. }
  3802. }
  3803. /*!
  3804. * \brief Get the number of members available to accept a call.
  3805. *
  3806. * \note The queue passed in should be locked prior to this function call
  3807. *
  3808. * \param[in] q The queue for which we are couting the number of available members
  3809. * \return Return the number of available members in queue q
  3810. */
  3811. static int num_available_members(struct call_queue *q)
  3812. {
  3813. struct member *mem;
  3814. int avl = 0;
  3815. struct ao2_iterator mem_iter;
  3816. mem_iter = ao2_iterator_init(q->members, 0);
  3817. while ((mem = ao2_iterator_next(&mem_iter))) {
  3818. avl += is_member_available(q, mem);
  3819. ao2_ref(mem, -1);
  3820. /* If autofill is not enabled or if the queue's strategy is ringall, then
  3821. * we really don't care about the number of available members so much as we
  3822. * do that there is at least one available.
  3823. *
  3824. * In fact, we purposely will return from this function stating that only
  3825. * one member is available if either of those conditions hold. That way,
  3826. * functions which determine what action to take based on the number of available
  3827. * members will operate properly. The reasoning is that even if multiple
  3828. * members are available, only the head caller can actually be serviced.
  3829. */
  3830. if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
  3831. break;
  3832. }
  3833. }
  3834. ao2_iterator_destroy(&mem_iter);
  3835. return avl;
  3836. }
  3837. /* traverse all defined queues which have calls waiting and contain this member
  3838. return 0 if no other queue has precedence (higher weight) or 1 if found */
  3839. static int compare_weight(struct call_queue *rq, struct member *member)
  3840. {
  3841. struct call_queue *q;
  3842. struct member *mem;
  3843. int found = 0;
  3844. struct ao2_iterator queue_iter;
  3845. queue_iter = ao2_iterator_init(queues, 0);
  3846. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  3847. if (q == rq) { /* don't check myself, could deadlock */
  3848. queue_t_unref(q, "Done with iterator");
  3849. continue;
  3850. }
  3851. ao2_lock(q);
  3852. if (q->count && q->members) {
  3853. if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
  3854. ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
  3855. if (q->weight > rq->weight && q->count >= num_available_members(q)) {
  3856. ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
  3857. found = 1;
  3858. }
  3859. ao2_ref(mem, -1);
  3860. }
  3861. }
  3862. ao2_unlock(q);
  3863. queue_t_unref(q, "Done with iterator");
  3864. if (found) {
  3865. break;
  3866. }
  3867. }
  3868. ao2_iterator_destroy(&queue_iter);
  3869. return found;
  3870. }
  3871. /*! \brief common hangup actions */
  3872. static void do_hang(struct callattempt *o)
  3873. {
  3874. o->stillgoing = 0;
  3875. ast_hangup(o->chan);
  3876. pending_members_remove(o->member);
  3877. o->chan = NULL;
  3878. }
  3879. /*!
  3880. * \internal
  3881. * \brief Check if the member status is available.
  3882. *
  3883. * \param status Member status to check if available.
  3884. *
  3885. * \retval non-zero if the member status is available.
  3886. */
  3887. static int member_status_available(int status)
  3888. {
  3889. return status == AST_DEVICE_NOT_INUSE || status == AST_DEVICE_UNKNOWN;
  3890. }
  3891. /*!
  3892. * \internal
  3893. * \brief Determine if can ring a queue entry.
  3894. *
  3895. * \param qe Queue entry to check.
  3896. * \param call Member call attempt.
  3897. *
  3898. * \retval non-zero if an entry can be called.
  3899. */
  3900. static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
  3901. {
  3902. if (call->member->paused) {
  3903. ast_debug(1, "%s paused, can't receive call\n", call->interface);
  3904. return 0;
  3905. }
  3906. if (!call->member->ringinuse && !member_status_available(call->member->status)) {
  3907. ast_debug(1, "%s not available, can't receive call\n", call->interface);
  3908. return 0;
  3909. }
  3910. if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))
  3911. || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {
  3912. ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
  3913. (call->lastqueue ? call->lastqueue->name : qe->parent->name),
  3914. call->interface);
  3915. return 0;
  3916. }
  3917. if (use_weight && compare_weight(qe->parent, call->member)) {
  3918. ast_debug(1, "Priority queue delaying call to %s:%s\n",
  3919. qe->parent->name, call->interface);
  3920. return 0;
  3921. }
  3922. if (!call->member->ringinuse) {
  3923. struct member *mem;
  3924. ao2_lock(pending_members);
  3925. mem = ao2_find(pending_members, call->member,
  3926. OBJ_SEARCH_OBJECT | OBJ_NOLOCK);
  3927. if (mem) {
  3928. /*
  3929. * If found that means this member is currently being attempted
  3930. * from another calling thread, so stop trying from this thread
  3931. */
  3932. ast_debug(1, "%s has another call trying, can't receive call\n",
  3933. call->interface);
  3934. ao2_ref(mem, -1);
  3935. ao2_unlock(pending_members);
  3936. return 0;
  3937. }
  3938. /*
  3939. * If not found add it to the container so another queue
  3940. * won't attempt to call this member at the same time.
  3941. */
  3942. ast_debug(3, "Add %s to pending_members\n", call->member->membername);
  3943. ao2_link(pending_members, call->member);
  3944. ao2_unlock(pending_members);
  3945. /*
  3946. * The queue member is available. Get current status to be sure
  3947. * because the device state and extension state callbacks may
  3948. * not have updated the status yet.
  3949. */
  3950. if (!member_status_available(get_queue_member_status(call->member))) {
  3951. ast_debug(1, "%s actually not available, can't receive call\n",
  3952. call->interface);
  3953. pending_members_remove(call->member);
  3954. return 0;
  3955. }
  3956. }
  3957. return 1;
  3958. }
  3959. /*!
  3960. * \brief Part 2 of ring_one
  3961. *
  3962. * Does error checking before attempting to request a channel and call a member.
  3963. * This function is only called from ring_one().
  3964. * Failure can occur if:
  3965. * - Agent on call
  3966. * - Agent is paused
  3967. * - Wrapup time not expired
  3968. * - Priority by another queue
  3969. *
  3970. * \retval 1 on success to reach a free agent
  3971. * \retval 0 on failure to get agent.
  3972. */
  3973. static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
  3974. {
  3975. int res;
  3976. int status;
  3977. char tech[256];
  3978. char *location;
  3979. const char *macrocontext, *macroexten;
  3980. RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
  3981. /* on entry here, we know that tmp->chan == NULL */
  3982. if (!can_ring_entry(qe, tmp)) {
  3983. tmp->stillgoing = 0;
  3984. ++*busies;
  3985. return 0;
  3986. }
  3987. ast_copy_string(tech, tmp->interface, sizeof(tech));
  3988. if ((location = strchr(tech, '/'))) {
  3989. *location++ = '\0';
  3990. } else {
  3991. location = "";
  3992. }
  3993. /* Request the peer */
  3994. tmp->chan = ast_request(tech, ast_channel_nativeformats(qe->chan), NULL, qe->chan, location, &status);
  3995. if (!tmp->chan) { /* If we can't, just go on to the next call */
  3996. ao2_lock(qe->parent);
  3997. qe->parent->rrpos++;
  3998. qe->linpos++;
  3999. ao2_unlock(qe->parent);
  4000. pending_members_remove(tmp->member);
  4001. publish_dial_end_event(qe->chan, tmp, NULL, "BUSY");
  4002. tmp->stillgoing = 0;
  4003. ++*busies;
  4004. return 0;
  4005. }
  4006. ast_channel_lock_both(tmp->chan, qe->chan);
  4007. ast_channel_req_accountcodes_precious(tmp->chan, qe->chan,
  4008. AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
  4009. if (qe->cancel_answered_elsewhere) {
  4010. ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
  4011. }
  4012. ast_channel_appl_set(tmp->chan, "AppQueue");
  4013. ast_channel_data_set(tmp->chan, "(Outgoing Line)");
  4014. memset(ast_channel_whentohangup(tmp->chan), 0, sizeof(*ast_channel_whentohangup(tmp->chan)));
  4015. /* If the new channel has no callerid, try to guess what it should be */
  4016. if (!ast_channel_caller(tmp->chan)->id.number.valid) {
  4017. if (ast_channel_connected(qe->chan)->id.number.valid) {
  4018. struct ast_party_caller caller;
  4019. ast_party_caller_set_init(&caller, ast_channel_caller(tmp->chan));
  4020. caller.id = ast_channel_connected(qe->chan)->id;
  4021. caller.ani = ast_channel_connected(qe->chan)->ani;
  4022. ast_channel_set_caller_event(tmp->chan, &caller, NULL);
  4023. } else if (!ast_strlen_zero(ast_channel_dialed(qe->chan)->number.str)) {
  4024. ast_set_callerid(tmp->chan, ast_channel_dialed(qe->chan)->number.str, NULL, NULL);
  4025. } else if (!ast_strlen_zero(S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)))) {
  4026. ast_set_callerid(tmp->chan, S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)), NULL, NULL);
  4027. }
  4028. tmp->dial_callerid_absent = 1;
  4029. }
  4030. ast_party_redirecting_copy(ast_channel_redirecting(tmp->chan), ast_channel_redirecting(qe->chan));
  4031. ast_channel_dialed(tmp->chan)->transit_network_select = ast_channel_dialed(qe->chan)->transit_network_select;
  4032. ast_connected_line_copy_from_caller(ast_channel_connected(tmp->chan), ast_channel_caller(qe->chan));
  4033. /* Inherit specially named variables from parent channel */
  4034. ast_channel_inherit_variables(qe->chan, tmp->chan);
  4035. ast_channel_datastore_inherit(qe->chan, tmp->chan);
  4036. ast_max_forwards_decrement(tmp->chan);
  4037. /* Presense of ADSI CPE on outgoing channel follows ours */
  4038. ast_channel_adsicpe_set(tmp->chan, ast_channel_adsicpe(qe->chan));
  4039. /* Inherit context and extension */
  4040. macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
  4041. ast_channel_dialcontext_set(tmp->chan, ast_strlen_zero(macrocontext) ? ast_channel_context(qe->chan) : macrocontext);
  4042. macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
  4043. if (!ast_strlen_zero(macroexten)) {
  4044. ast_channel_exten_set(tmp->chan, macroexten);
  4045. } else {
  4046. ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan));
  4047. }
  4048. /* Save the original channel name to detect call pickup masquerading in. */
  4049. tmp->orig_chan_name = ast_strdup(ast_channel_name(tmp->chan));
  4050. ast_channel_unlock(tmp->chan);
  4051. ast_channel_unlock(qe->chan);
  4052. /* Place the call, but don't wait on the answer */
  4053. if ((res = ast_call(tmp->chan, location, 0))) {
  4054. /* Again, keep going even if there's an error */
  4055. ast_verb(3, "Couldn't call %s\n", tmp->interface);
  4056. do_hang(tmp);
  4057. ++*busies;
  4058. return 0;
  4059. }
  4060. ast_channel_lock_both(tmp->chan, qe->chan);
  4061. blob = ast_json_pack("{s: s, s: s, s: s}",
  4062. "Queue", qe->parent->name,
  4063. "Interface", tmp->interface,
  4064. "MemberName", tmp->member->membername);
  4065. queue_publish_multi_channel_blob(qe->chan, tmp->chan, queue_agent_called_type(), blob);
  4066. ast_channel_publish_dial(qe->chan, tmp->chan, tmp->interface, NULL);
  4067. ast_channel_unlock(tmp->chan);
  4068. ast_channel_unlock(qe->chan);
  4069. ast_verb(3, "Called %s\n", tmp->interface);
  4070. return 1;
  4071. }
  4072. /*! \brief find the entry with the best metric, or NULL */
  4073. static struct callattempt *find_best(struct callattempt *outgoing)
  4074. {
  4075. struct callattempt *best = NULL, *cur;
  4076. for (cur = outgoing; cur; cur = cur->q_next) {
  4077. if (cur->stillgoing && /* Not already done */
  4078. !cur->chan && /* Isn't already going */
  4079. (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
  4080. best = cur;
  4081. }
  4082. }
  4083. return best;
  4084. }
  4085. /*!
  4086. * \brief Place a call to a queue member.
  4087. *
  4088. * Once metrics have been calculated for each member, this function is used
  4089. * to place a call to the appropriate member (or members). The low-level
  4090. * channel-handling and error detection is handled in ring_entry
  4091. *
  4092. * \retval 1 if a member was called successfully
  4093. * \retval 0 otherwise
  4094. */
  4095. static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
  4096. {
  4097. int ret = 0;
  4098. while (ret == 0) {
  4099. struct callattempt *best = find_best(outgoing);
  4100. if (!best) {
  4101. ast_debug(1, "Nobody left to try ringing in queue\n");
  4102. break;
  4103. }
  4104. if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
  4105. struct callattempt *cur;
  4106. /* Ring everyone who shares this best metric (for ringall) */
  4107. for (cur = outgoing; cur; cur = cur->q_next) {
  4108. if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
  4109. ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
  4110. ret |= ring_entry(qe, cur, busies);
  4111. }
  4112. }
  4113. } else {
  4114. /* Ring just the best channel */
  4115. ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
  4116. ret = ring_entry(qe, best, busies);
  4117. }
  4118. /* If we have timed out, break out */
  4119. if (qe->expire && (time(NULL) >= qe->expire)) {
  4120. ast_debug(1, "Queue timed out while ringing members.\n");
  4121. ret = 0;
  4122. break;
  4123. }
  4124. }
  4125. return ret;
  4126. }
  4127. /*! \brief Search for best metric and add to Round Robbin queue */
  4128. static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
  4129. {
  4130. struct callattempt *best = find_best(outgoing);
  4131. if (best) {
  4132. /* Ring just the best channel */
  4133. ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
  4134. qe->parent->rrpos = best->metric % 1000;
  4135. } else {
  4136. /* Just increment rrpos */
  4137. if (qe->parent->wrapped) {
  4138. /* No more channels, start over */
  4139. qe->parent->rrpos = 0;
  4140. } else {
  4141. /* Prioritize next entry */
  4142. qe->parent->rrpos++;
  4143. }
  4144. }
  4145. qe->parent->wrapped = 0;
  4146. return 0;
  4147. }
  4148. /*! \brief Search for best metric and add to Linear queue */
  4149. static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
  4150. {
  4151. struct callattempt *best = find_best(outgoing);
  4152. if (best) {
  4153. /* Ring just the best channel */
  4154. ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
  4155. qe->linpos = best->metric % 1000;
  4156. } else {
  4157. /* Just increment rrpos */
  4158. if (qe->linwrapped) {
  4159. /* No more channels, start over */
  4160. qe->linpos = 0;
  4161. } else {
  4162. /* Prioritize next entry */
  4163. qe->linpos++;
  4164. }
  4165. }
  4166. qe->linwrapped = 0;
  4167. return 0;
  4168. }
  4169. /*! \brief Playback announcement to queued members if period has elapsed */
  4170. static int say_periodic_announcement(struct queue_ent *qe, int ringing)
  4171. {
  4172. int res = 0;
  4173. time_t now;
  4174. /* Get the current time */
  4175. time(&now);
  4176. /* Check to see if it is time to announce */
  4177. if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency) {
  4178. return 0;
  4179. }
  4180. /* Stop the music on hold so we can play our own file */
  4181. if (ringing) {
  4182. ast_indicate(qe->chan,-1);
  4183. } else {
  4184. ast_moh_stop(qe->chan);
  4185. }
  4186. ast_verb(3, "Playing periodic announcement\n");
  4187. if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
  4188. qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
  4189. } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
  4190. ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
  4191. qe->last_periodic_announce_sound = 0;
  4192. }
  4193. /* play the announcement */
  4194. res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
  4195. if (res > 0 && !valid_exit(qe, res)) {
  4196. res = 0;
  4197. }
  4198. /* Resume Music on Hold if the caller is going to stay in the queue */
  4199. if (!res) {
  4200. if (ringing) {
  4201. ast_indicate(qe->chan, AST_CONTROL_RINGING);
  4202. } else {
  4203. ast_moh_start(qe->chan, qe->moh, NULL);
  4204. }
  4205. }
  4206. /* update last_periodic_announce_time */
  4207. if (qe->parent->relativeperiodicannounce) {
  4208. time(&qe->last_periodic_announce_time);
  4209. } else {
  4210. qe->last_periodic_announce_time = now;
  4211. }
  4212. /* Update the current periodic announcement to the next announcement */
  4213. if (!qe->parent->randomperiodicannounce) {
  4214. qe->last_periodic_announce_sound++;
  4215. }
  4216. return res;
  4217. }
  4218. /*! \brief Record that a caller gave up on waiting in queue */
  4219. static void record_abandoned(struct queue_ent *qe)
  4220. {
  4221. RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
  4222. pbx_builtin_setvar_helper(qe->chan, "ABANDONED", "TRUE");
  4223. set_queue_variables(qe->parent, qe->chan);
  4224. ao2_lock(qe->parent);
  4225. blob = ast_json_pack("{s: s, s: i, s: i, s: i}",
  4226. "Queue", qe->parent->name,
  4227. "Position", qe->pos,
  4228. "OriginalPosition", qe->opos,
  4229. "HoldTime", (int)(time(NULL) - qe->start));
  4230. qe->parent->callsabandoned++;
  4231. ao2_unlock(qe->parent);
  4232. ast_channel_publish_cached_blob(qe->chan, queue_caller_abandon_type(), blob);
  4233. }
  4234. /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
  4235. static void rna(int rnatime, struct queue_ent *qe, struct ast_channel *peer, char *interface, char *membername, int autopause)
  4236. {
  4237. RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
  4238. ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
  4239. /* Stop ringing, and resume MOH if specified */
  4240. if (qe->ring_when_ringing) {
  4241. ast_indicate(qe->chan, -1);
  4242. ast_moh_start(qe->chan, qe->moh, NULL);
  4243. }
  4244. blob = ast_json_pack("{s: s, s: s, s: s, s: i}",
  4245. "Queue", qe->parent->name,
  4246. "Interface", interface,
  4247. "MemberName", membername,
  4248. "RingTime", rnatime);
  4249. queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_ringnoanswer_type(), blob);
  4250. ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), membername, "RINGNOANSWER", "%d", rnatime);
  4251. if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && autopause) {
  4252. if (qe->parent->autopausedelay > 0) {
  4253. struct member *mem;
  4254. ao2_lock(qe->parent);
  4255. if ((mem = interface_exists(qe->parent, interface))) {
  4256. time_t idletime = time(&idletime)-mem->lastcall;
  4257. if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
  4258. ao2_unlock(qe->parent);
  4259. ao2_ref(mem, -1);
  4260. return;
  4261. }
  4262. ao2_ref(mem, -1);
  4263. }
  4264. ao2_unlock(qe->parent);
  4265. }
  4266. if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
  4267. if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
  4268. ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
  4269. interface, qe->parent->name);
  4270. } else {
  4271. ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
  4272. }
  4273. } else {
  4274. /* If queue autopause is mode all, just don't send any queue to stop.
  4275. * the function will stop in all queues */
  4276. if (!set_member_paused("", interface, "Auto-Pause", 1)) {
  4277. ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
  4278. interface, qe->parent->name);
  4279. } else {
  4280. ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
  4281. }
  4282. }
  4283. }
  4284. return;
  4285. }
  4286. /*!
  4287. * \internal
  4288. * \brief Update connected line on chan from peer.
  4289. * \since 13.6.0
  4290. *
  4291. * \param chan Channel to get connected line updated.
  4292. * \param peer Channel providing connected line information.
  4293. * \param is_caller Non-zero if chan is the calling channel.
  4294. *
  4295. * \return Nothing
  4296. */
  4297. static void update_connected_line_from_peer(struct ast_channel *chan, struct ast_channel *peer, int is_caller)
  4298. {
  4299. struct ast_party_connected_line connected_caller;
  4300. ast_party_connected_line_init(&connected_caller);
  4301. ast_channel_lock(peer);
  4302. ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(peer));
  4303. ast_channel_unlock(peer);
  4304. connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
  4305. if (ast_channel_connected_line_sub(peer, chan, &connected_caller, 0)
  4306. && ast_channel_connected_line_macro(peer, chan, &connected_caller, is_caller, 0)) {
  4307. ast_channel_update_connected_line(chan, &connected_caller, NULL);
  4308. }
  4309. ast_party_connected_line_free(&connected_caller);
  4310. }
  4311. #define AST_MAX_WATCHERS 256
  4312. /*!
  4313. * \brief Wait for a member to answer the call
  4314. *
  4315. * \param[in] qe the queue_ent corresponding to the caller in the queue
  4316. * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
  4317. * \param[in] to the amount of time (in milliseconds) to wait for a response
  4318. * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
  4319. * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
  4320. * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
  4321. * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
  4322. *
  4323. * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
  4324. */
  4325. static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
  4326. {
  4327. const char *queue = qe->parent->name;
  4328. struct callattempt *o, *start = NULL, *prev = NULL;
  4329. int status;
  4330. int numbusies = prebusies;
  4331. int numnochan = 0;
  4332. int stillgoing = 0;
  4333. int orig = *to;
  4334. struct ast_frame *f;
  4335. struct callattempt *peer = NULL;
  4336. struct ast_channel *winner;
  4337. struct ast_channel *in = qe->chan;
  4338. char on[80] = "";
  4339. char membername[80] = "";
  4340. long starttime = 0;
  4341. long endtime = 0;
  4342. #ifdef HAVE_EPOLL
  4343. struct callattempt *epollo;
  4344. #endif
  4345. char *inchan_name;
  4346. struct timeval start_time_tv = ast_tvnow();
  4347. ast_channel_lock(qe->chan);
  4348. inchan_name = ast_strdupa(ast_channel_name(qe->chan));
  4349. ast_channel_unlock(qe->chan);
  4350. starttime = (long) time(NULL);
  4351. #ifdef HAVE_EPOLL
  4352. for (epollo = outgoing; epollo; epollo = epollo->q_next) {
  4353. if (epollo->chan) {
  4354. ast_poll_channel_add(in, epollo->chan);
  4355. }
  4356. }
  4357. #endif
  4358. while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
  4359. int numlines, retry, pos = 1;
  4360. struct ast_channel *watchers[AST_MAX_WATCHERS];
  4361. watchers[0] = in;
  4362. start = NULL;
  4363. for (retry = 0; retry < 2; retry++) {
  4364. numlines = 0;
  4365. for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
  4366. if (o->stillgoing) { /* Keep track of important channels */
  4367. stillgoing = 1;
  4368. if (o->chan) {
  4369. if (pos < AST_MAX_WATCHERS) {
  4370. watchers[pos++] = o->chan;
  4371. }
  4372. if (!start) {
  4373. start = o;
  4374. } else {
  4375. prev->call_next = o;
  4376. }
  4377. prev = o;
  4378. }
  4379. } else if (prev) {
  4380. prev->call_next = NULL;
  4381. }
  4382. numlines++;
  4383. }
  4384. if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
  4385. (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */) {
  4386. break;
  4387. }
  4388. /* On "ringall" strategy we only move to the next penalty level
  4389. when *all* ringing phones are done in the current penalty level */
  4390. ring_one(qe, outgoing, &numbusies);
  4391. /* and retry... */
  4392. }
  4393. if (pos == 1 /* not found */) {
  4394. if (numlines == (numbusies + numnochan)) {
  4395. ast_debug(1, "Everyone is busy at this time\n");
  4396. } else {
  4397. ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
  4398. }
  4399. *to = 0;
  4400. return NULL;
  4401. }
  4402. /* Poll for events from both the incoming channel as well as any outgoing channels */
  4403. winner = ast_waitfor_n(watchers, pos, to);
  4404. /* Service all of the outgoing channels */
  4405. for (o = start; o; o = o->call_next) {
  4406. /* We go with a fixed buffer here instead of using ast_strdupa. Using
  4407. * ast_strdupa in a loop like this one can cause a stack overflow
  4408. */
  4409. char ochan_name[AST_CHANNEL_NAME];
  4410. if (o->chan) {
  4411. ast_channel_lock(o->chan);
  4412. ast_copy_string(ochan_name, ast_channel_name(o->chan), sizeof(ochan_name));
  4413. ast_channel_unlock(o->chan);
  4414. }
  4415. if (o->stillgoing && (o->chan) && (ast_channel_state(o->chan) == AST_STATE_UP)) {
  4416. if (!peer) {
  4417. ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
  4418. if (o->orig_chan_name
  4419. && strcmp(o->orig_chan_name, ochan_name)) {
  4420. /*
  4421. * The channel name changed so we must generate COLP update.
  4422. * Likely because a call pickup channel masqueraded in.
  4423. */
  4424. update_connected_line_from_peer(in, o->chan, 1);
  4425. } else if (!o->block_connected_update) {
  4426. if (o->pending_connected_update) {
  4427. if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
  4428. ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
  4429. ast_channel_update_connected_line(in, &o->connected, NULL);
  4430. }
  4431. } else if (!o->dial_callerid_absent) {
  4432. update_connected_line_from_peer(in, o->chan, 1);
  4433. }
  4434. }
  4435. if (o->aoc_s_rate_list) {
  4436. size_t encoded_size;
  4437. struct ast_aoc_encoded *encoded;
  4438. if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
  4439. ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
  4440. ast_aoc_destroy_encoded(encoded);
  4441. }
  4442. }
  4443. peer = o;
  4444. }
  4445. } else if (o->chan && (o->chan == winner)) {
  4446. ast_copy_string(on, o->member->interface, sizeof(on));
  4447. ast_copy_string(membername, o->member->membername, sizeof(membername));
  4448. /* Before processing channel, go ahead and check for forwarding */
  4449. if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {
  4450. ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
  4451. numnochan++;
  4452. do_hang(o);
  4453. winner = NULL;
  4454. continue;
  4455. } else if (!ast_strlen_zero(ast_channel_call_forward(o->chan))) {
  4456. struct ast_channel *original = o->chan;
  4457. char forwarder[AST_CHANNEL_NAME];
  4458. char tmpchan[256];
  4459. char *stuff;
  4460. char *tech;
  4461. int failed = 0;
  4462. ast_copy_string(tmpchan, ast_channel_call_forward(o->chan), sizeof(tmpchan));
  4463. ast_copy_string(forwarder, ast_channel_name(o->chan), sizeof(forwarder));
  4464. if ((stuff = strchr(tmpchan, '/'))) {
  4465. *stuff++ = '\0';
  4466. tech = tmpchan;
  4467. } else {
  4468. const char *forward_context;
  4469. ast_channel_lock(o->chan);
  4470. forward_context = pbx_builtin_getvar_helper(o->chan, "FORWARD_CONTEXT");
  4471. snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), forward_context ? forward_context : ast_channel_context(o->chan));
  4472. ast_channel_unlock(o->chan);
  4473. stuff = tmpchan;
  4474. tech = "Local";
  4475. }
  4476. if (!strcasecmp(tech, "Local")) {
  4477. /*
  4478. * Drop the connected line update block for local channels since
  4479. * this is going to run dialplan and the user can change his
  4480. * mind about what connected line information he wants to send.
  4481. */
  4482. o->block_connected_update = 0;
  4483. }
  4484. ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
  4485. /* Setup parameters */
  4486. o->chan = ast_request(tech, ast_channel_nativeformats(in), NULL, in, stuff, &status);
  4487. if (!o->chan) {
  4488. ast_log(LOG_NOTICE,
  4489. "Forwarding failed to create channel to dial '%s/%s'\n",
  4490. tech, stuff);
  4491. o->stillgoing = 0;
  4492. numnochan++;
  4493. } else {
  4494. ast_channel_lock_both(o->chan, original);
  4495. ast_party_redirecting_copy(ast_channel_redirecting(o->chan),
  4496. ast_channel_redirecting(original));
  4497. ast_channel_unlock(o->chan);
  4498. ast_channel_unlock(original);
  4499. ast_channel_lock_both(o->chan, in);
  4500. ast_channel_inherit_variables(in, o->chan);
  4501. ast_channel_datastore_inherit(in, o->chan);
  4502. pbx_builtin_setvar_helper(o->chan, "FORWARDERNAME", forwarder);
  4503. ast_max_forwards_decrement(o->chan);
  4504. if (o->pending_connected_update) {
  4505. /*
  4506. * Re-seed the callattempt's connected line information with
  4507. * previously acquired connected line info from the queued
  4508. * channel. The previously acquired connected line info could
  4509. * have been set through the CONNECTED_LINE dialplan function.
  4510. */
  4511. o->pending_connected_update = 0;
  4512. ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));
  4513. }
  4514. ast_free(o->orig_chan_name);
  4515. o->orig_chan_name = ast_strdup(ast_channel_name(o->chan));
  4516. ast_channel_req_accountcodes(o->chan, in, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
  4517. if (!ast_channel_redirecting(o->chan)->from.number.valid
  4518. || ast_strlen_zero(ast_channel_redirecting(o->chan)->from.number.str)) {
  4519. /*
  4520. * The call was not previously redirected so it is
  4521. * now redirected from this number.
  4522. */
  4523. ast_party_number_free(&ast_channel_redirecting(o->chan)->from.number);
  4524. ast_party_number_init(&ast_channel_redirecting(o->chan)->from.number);
  4525. ast_channel_redirecting(o->chan)->from.number.valid = 1;
  4526. ast_channel_redirecting(o->chan)->from.number.str =
  4527. ast_strdup(S_OR(ast_channel_macroexten(in), ast_channel_exten(in)));
  4528. }
  4529. ast_channel_dialed(o->chan)->transit_network_select = ast_channel_dialed(in)->transit_network_select;
  4530. o->dial_callerid_absent = !ast_channel_caller(o->chan)->id.number.valid
  4531. || ast_strlen_zero(ast_channel_caller(o->chan)->id.number.str);
  4532. ast_connected_line_copy_from_caller(ast_channel_connected(o->chan),
  4533. ast_channel_caller(in));
  4534. ast_channel_unlock(in);
  4535. if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL
  4536. && !o->block_connected_update) {
  4537. struct ast_party_redirecting redirecting;
  4538. /*
  4539. * Redirecting updates to the caller make sense only on single
  4540. * call at a time strategies.
  4541. *
  4542. * We must unlock o->chan before calling
  4543. * ast_channel_redirecting_macro, because we put o->chan into
  4544. * autoservice there. That is pretty much a guaranteed
  4545. * deadlock. This is why the handling of o->chan's lock may
  4546. * seem a bit unusual here.
  4547. */
  4548. ast_party_redirecting_init(&redirecting);
  4549. ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(o->chan));
  4550. ast_channel_unlock(o->chan);
  4551. if (ast_channel_redirecting_sub(o->chan, in, &redirecting, 0) &&
  4552. ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0)) {
  4553. ast_channel_update_redirecting(in, &redirecting, NULL);
  4554. }
  4555. ast_party_redirecting_free(&redirecting);
  4556. } else {
  4557. ast_channel_unlock(o->chan);
  4558. }
  4559. if (ast_call(o->chan, stuff, 0)) {
  4560. ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
  4561. tech, stuff);
  4562. failed = 1;
  4563. }
  4564. }
  4565. ast_channel_publish_dial_forward(qe->chan, original, o->chan, NULL,
  4566. "CANCEL", ast_channel_call_forward(original));
  4567. if (o->chan) {
  4568. ast_channel_publish_dial(qe->chan, o->chan, stuff, NULL);
  4569. }
  4570. if (failed) {
  4571. do_hang(o);
  4572. numnochan++;
  4573. }
  4574. /* Hangup the original channel now, in case we needed it */
  4575. ast_hangup(winner);
  4576. continue;
  4577. }
  4578. f = ast_read(winner);
  4579. if (f) {
  4580. if (f->frametype == AST_FRAME_CONTROL) {
  4581. switch (f->subclass.integer) {
  4582. case AST_CONTROL_ANSWER:
  4583. /* This is our guy if someone answered. */
  4584. if (!peer) {
  4585. ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
  4586. ast_channel_publish_dial(qe->chan, o->chan, on, "ANSWER");
  4587. publish_dial_end_event(qe->chan, outgoing, o->chan, "CANCEL");
  4588. if (o->orig_chan_name
  4589. && strcmp(o->orig_chan_name, ochan_name)) {
  4590. /*
  4591. * The channel name changed so we must generate COLP update.
  4592. * Likely because a call pickup channel masqueraded in.
  4593. */
  4594. update_connected_line_from_peer(in, o->chan, 1);
  4595. } else if (!o->block_connected_update) {
  4596. if (o->pending_connected_update) {
  4597. if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
  4598. ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
  4599. ast_channel_update_connected_line(in, &o->connected, NULL);
  4600. }
  4601. } else if (!o->dial_callerid_absent) {
  4602. update_connected_line_from_peer(in, o->chan, 1);
  4603. }
  4604. }
  4605. if (o->aoc_s_rate_list) {
  4606. size_t encoded_size;
  4607. struct ast_aoc_encoded *encoded;
  4608. if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
  4609. ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
  4610. ast_aoc_destroy_encoded(encoded);
  4611. }
  4612. }
  4613. peer = o;
  4614. }
  4615. break;
  4616. case AST_CONTROL_BUSY:
  4617. ast_verb(3, "%s is busy\n", ochan_name);
  4618. ast_channel_publish_dial(qe->chan, o->chan, on, "BUSY");
  4619. endtime = (long) time(NULL);
  4620. endtime -= starttime;
  4621. rna(endtime * 1000, qe, o->chan, on, membername, qe->parent->autopausebusy);
  4622. do_hang(o);
  4623. if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
  4624. if (qe->parent->timeoutrestart) {
  4625. start_time_tv = ast_tvnow();
  4626. }
  4627. /* Have enough time for a queue member to answer? */
  4628. if (ast_remaining_ms(start_time_tv, orig) > 500) {
  4629. ring_one(qe, outgoing, &numbusies);
  4630. starttime = (long) time(NULL);
  4631. }
  4632. }
  4633. numbusies++;
  4634. break;
  4635. case AST_CONTROL_CONGESTION:
  4636. ast_verb(3, "%s is circuit-busy\n", ochan_name);
  4637. ast_channel_publish_dial(qe->chan, o->chan, on, "CONGESTION");
  4638. endtime = (long) time(NULL);
  4639. endtime -= starttime;
  4640. rna(endtime * 1000, qe, o->chan, on, membername, qe->parent->autopauseunavail);
  4641. do_hang(o);
  4642. if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
  4643. if (qe->parent->timeoutrestart) {
  4644. start_time_tv = ast_tvnow();
  4645. }
  4646. if (ast_remaining_ms(start_time_tv, orig) > 500) {
  4647. ring_one(qe, outgoing, &numbusies);
  4648. starttime = (long) time(NULL);
  4649. }
  4650. }
  4651. numbusies++;
  4652. break;
  4653. case AST_CONTROL_RINGING:
  4654. ast_verb(3, "%s is ringing\n", ochan_name);
  4655. /* Start ring indication when the channel is ringing, if specified */
  4656. if (qe->ring_when_ringing) {
  4657. ast_moh_stop(qe->chan);
  4658. ast_indicate(qe->chan, AST_CONTROL_RINGING);
  4659. }
  4660. break;
  4661. case AST_CONTROL_OFFHOOK:
  4662. /* Ignore going off hook */
  4663. break;
  4664. case AST_CONTROL_CONNECTED_LINE:
  4665. if (o->block_connected_update) {
  4666. ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
  4667. break;
  4668. }
  4669. if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
  4670. struct ast_party_connected_line connected;
  4671. ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
  4672. ast_party_connected_line_set_init(&connected, &o->connected);
  4673. ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
  4674. ast_party_connected_line_set(&o->connected, &connected, NULL);
  4675. ast_party_connected_line_free(&connected);
  4676. o->pending_connected_update = 1;
  4677. break;
  4678. }
  4679. /*
  4680. * Prevent using the CallerID from the outgoing channel since we
  4681. * got a connected line update from it.
  4682. */
  4683. o->dial_callerid_absent = 1;
  4684. if (ast_channel_connected_line_sub(o->chan, in, f, 1) &&
  4685. ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
  4686. ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
  4687. }
  4688. break;
  4689. case AST_CONTROL_AOC:
  4690. {
  4691. struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
  4692. if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
  4693. ast_aoc_destroy_decoded(o->aoc_s_rate_list);
  4694. o->aoc_s_rate_list = decoded;
  4695. } else {
  4696. ast_aoc_destroy_decoded(decoded);
  4697. }
  4698. }
  4699. break;
  4700. case AST_CONTROL_REDIRECTING:
  4701. if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
  4702. /*
  4703. * Redirecting updates to the caller make sense only on single
  4704. * call at a time strategies.
  4705. */
  4706. break;
  4707. }
  4708. if (o->block_connected_update) {
  4709. ast_verb(3, "Redirecting update to %s prevented\n",
  4710. inchan_name);
  4711. break;
  4712. }
  4713. ast_verb(3, "%s redirecting info has changed, passing it to %s\n",
  4714. ochan_name, inchan_name);
  4715. if (ast_channel_redirecting_sub(o->chan, in, f, 1) &&
  4716. ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
  4717. ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
  4718. }
  4719. break;
  4720. case AST_CONTROL_PVT_CAUSE_CODE:
  4721. ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
  4722. break;
  4723. default:
  4724. ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
  4725. break;
  4726. }
  4727. }
  4728. ast_frfree(f);
  4729. } else { /* ast_read() returned NULL */
  4730. endtime = (long) time(NULL) - starttime;
  4731. ast_channel_publish_dial(qe->chan, o->chan, on, "NOANSWER");
  4732. rna(endtime * 1000, qe, o->chan, on, membername, 1);
  4733. do_hang(o);
  4734. if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
  4735. if (qe->parent->timeoutrestart) {
  4736. start_time_tv = ast_tvnow();
  4737. }
  4738. if (ast_remaining_ms(start_time_tv, orig) > 500) {
  4739. ring_one(qe, outgoing, &numbusies);
  4740. starttime = (long) time(NULL);
  4741. }
  4742. }
  4743. }
  4744. }
  4745. }
  4746. /* If we received an event from the caller, deal with it. */
  4747. if (winner == in) {
  4748. f = ast_read(in);
  4749. if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
  4750. /* Got hung up */
  4751. *to = -1;
  4752. publish_dial_end_event(in, outgoing, NULL, "CANCEL");
  4753. if (f) {
  4754. if (f->data.uint32) {
  4755. ast_channel_hangupcause_set(in, f->data.uint32);
  4756. }
  4757. ast_frfree(f);
  4758. }
  4759. return NULL;
  4760. }
  4761. if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
  4762. ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
  4763. *to = 0;
  4764. publish_dial_end_event(in, outgoing, NULL, "CANCEL");
  4765. ast_frfree(f);
  4766. return NULL;
  4767. }
  4768. if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
  4769. ast_verb(3, "User pressed digit: %c\n", f->subclass.integer);
  4770. *to = 0;
  4771. publish_dial_end_event(in, outgoing, NULL, "CANCEL");
  4772. *digit = f->subclass.integer;
  4773. ast_frfree(f);
  4774. return NULL;
  4775. }
  4776. /* Send the frame from the in channel to all outgoing channels. */
  4777. for (o = start; o; o = o->call_next) {
  4778. if (!o->stillgoing || !o->chan) {
  4779. /* This outgoing channel has died so don't send the frame to it. */
  4780. continue;
  4781. }
  4782. switch (f->frametype) {
  4783. case AST_FRAME_CONTROL:
  4784. switch (f->subclass.integer) {
  4785. case AST_CONTROL_CONNECTED_LINE:
  4786. if (o->block_connected_update) {
  4787. ast_verb(3, "Connected line update to %s prevented.\n", ast_channel_name(o->chan));
  4788. break;
  4789. }
  4790. if (ast_channel_connected_line_sub(in, o->chan, f, 1) &&
  4791. ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
  4792. ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
  4793. }
  4794. break;
  4795. case AST_CONTROL_REDIRECTING:
  4796. if (o->block_connected_update) {
  4797. ast_verb(3, "Redirecting update to %s prevented.\n", ast_channel_name(o->chan));
  4798. break;
  4799. }
  4800. if (ast_channel_redirecting_sub(in, o->chan, f, 1) &&
  4801. ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
  4802. ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
  4803. }
  4804. break;
  4805. default:
  4806. /* We are not going to do anything with this frame. */
  4807. goto skip_frame;
  4808. }
  4809. break;
  4810. default:
  4811. /* We are not going to do anything with this frame. */
  4812. goto skip_frame;
  4813. }
  4814. }
  4815. skip_frame:;
  4816. ast_frfree(f);
  4817. }
  4818. }
  4819. if (!*to) {
  4820. for (o = start; o; o = o->call_next) {
  4821. if (o->chan) {
  4822. rna(orig, qe, o->chan, o->interface, o->member->membername, 1);
  4823. }
  4824. }
  4825. publish_dial_end_event(qe->chan, outgoing, NULL, "NOANSWER");
  4826. }
  4827. #ifdef HAVE_EPOLL
  4828. for (epollo = outgoing; epollo; epollo = epollo->q_next) {
  4829. if (epollo->chan) {
  4830. ast_poll_channel_del(in, epollo->chan);
  4831. }
  4832. }
  4833. #endif
  4834. return peer;
  4835. }
  4836. /*!
  4837. * \brief Check if we should start attempting to call queue members.
  4838. *
  4839. * A simple process, really. Count the number of members who are available
  4840. * to take our call and then see if we are in a position in the queue at
  4841. * which a member could accept our call.
  4842. *
  4843. * \param[in] qe The caller who wants to know if it is his turn
  4844. * \retval 0 It is not our turn
  4845. * \retval 1 It is our turn
  4846. */
  4847. static int is_our_turn(struct queue_ent *qe)
  4848. {
  4849. struct queue_ent *ch;
  4850. int res;
  4851. int avl;
  4852. int idx = 0;
  4853. /* This needs a lock. How many members are available to be served? */
  4854. ao2_lock(qe->parent);
  4855. avl = num_available_members(qe->parent);
  4856. ch = qe->parent->head;
  4857. ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
  4858. while ((idx < avl) && (ch) && (ch != qe)) {
  4859. if (!ch->pending) {
  4860. idx++;
  4861. }
  4862. ch = ch->next;
  4863. }
  4864. ao2_unlock(qe->parent);
  4865. /* If the queue entry is within avl [the number of available members] calls from the top ...
  4866. * Autofill and position check added to support autofill=no (as only calls
  4867. * from the front of the queue are valid when autofill is disabled)
  4868. */
  4869. if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
  4870. ast_debug(1, "It's our turn (%s).\n", ast_channel_name(qe->chan));
  4871. res = 1;
  4872. } else {
  4873. ast_debug(1, "It's not our turn (%s).\n", ast_channel_name(qe->chan));
  4874. res = 0;
  4875. }
  4876. /* Update realtime members if this is the first call and number of avalable members is 0 */
  4877. if (avl == 0 && qe->pos == 1) {
  4878. update_realtime_members(qe->parent);
  4879. }
  4880. return res;
  4881. }
  4882. /*!
  4883. * \brief update rules for queues
  4884. *
  4885. * Calculate min/max penalties making sure if relative they stay within bounds.
  4886. * Update queues penalty and set dialplan vars, goto next list entry.
  4887. */
  4888. static void update_qe_rule(struct queue_ent *qe)
  4889. {
  4890. int max_penalty = INT_MAX;
  4891. if (qe->max_penalty != INT_MAX) {
  4892. char max_penalty_str[20];
  4893. if (qe->pr->max_relative) {
  4894. max_penalty = qe->max_penalty + qe->pr->max_value;
  4895. } else {
  4896. max_penalty = qe->pr->max_value;
  4897. }
  4898. /* a relative change to the penalty could put it below 0 */
  4899. if (max_penalty < 0) {
  4900. max_penalty = 0;
  4901. }
  4902. snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
  4903. pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
  4904. qe->max_penalty = max_penalty;
  4905. ast_debug(3, "Setting max penalty to %d for caller %s since %d seconds have elapsed\n",
  4906. qe->max_penalty, ast_channel_name(qe->chan), qe->pr->time);
  4907. }
  4908. if (qe->min_penalty != INT_MAX) {
  4909. char min_penalty_str[20];
  4910. int min_penalty;
  4911. if (qe->pr->min_relative) {
  4912. min_penalty = qe->min_penalty + qe->pr->min_value;
  4913. } else {
  4914. min_penalty = qe->pr->min_value;
  4915. }
  4916. /* a relative change to the penalty could put it below 0 */
  4917. if (min_penalty < 0) {
  4918. min_penalty = 0;
  4919. }
  4920. if (max_penalty != INT_MAX && min_penalty > max_penalty) {
  4921. min_penalty = max_penalty;
  4922. }
  4923. snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
  4924. pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
  4925. qe->min_penalty = min_penalty;
  4926. ast_debug(3, "Setting min penalty to %d for caller %s since %d seconds have elapsed\n",
  4927. qe->min_penalty, ast_channel_name(qe->chan), qe->pr->time);
  4928. }
  4929. qe->pr = AST_LIST_NEXT(qe->pr, list);
  4930. }
  4931. /*! \brief The waiting areas for callers who are not actively calling members
  4932. *
  4933. * This function is one large loop. This function will return if a caller
  4934. * either exits the queue or it becomes that caller's turn to attempt calling
  4935. * queue members. Inside the loop, we service the caller with periodic announcements,
  4936. * holdtime announcements, etc. as configured in queues.conf
  4937. *
  4938. * \retval 0 if the caller's turn has arrived
  4939. * \retval -1 if the caller should exit the queue.
  4940. */
  4941. static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
  4942. {
  4943. int res = 0;
  4944. /* This is the holding pen for callers 2 through maxlen */
  4945. for (;;) {
  4946. if (is_our_turn(qe)) {
  4947. break;
  4948. }
  4949. /* If we have timed out, break out */
  4950. if (qe->expire && (time(NULL) >= qe->expire)) {
  4951. *reason = QUEUE_TIMEOUT;
  4952. break;
  4953. }
  4954. if (qe->parent->leavewhenempty) {
  4955. int status = 0;
  4956. if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty, 0))) {
  4957. *reason = QUEUE_LEAVEEMPTY;
  4958. ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) (time(NULL) - qe->start));
  4959. res = -1;
  4960. qe->handled = -1;
  4961. break;
  4962. }
  4963. }
  4964. /* Make a position announcement, if enabled */
  4965. if (qe->parent->announcefrequency &&
  4966. (res = say_position(qe,ringing))) {
  4967. break;
  4968. }
  4969. /* If we have timed out, break out */
  4970. if (qe->expire && (time(NULL) >= qe->expire)) {
  4971. *reason = QUEUE_TIMEOUT;
  4972. break;
  4973. }
  4974. /* Make a periodic announcement, if enabled */
  4975. if (qe->parent->periodicannouncefrequency &&
  4976. (res = say_periodic_announcement(qe,ringing)))
  4977. break;
  4978. /* see if we need to move to the next penalty level for this queue */
  4979. while (qe->pr && ((time(NULL) - qe->start) >= qe->pr->time)) {
  4980. update_qe_rule(qe);
  4981. }
  4982. /* If we have timed out, break out */
  4983. if (qe->expire && (time(NULL) >= qe->expire)) {
  4984. *reason = QUEUE_TIMEOUT;
  4985. break;
  4986. }
  4987. /* Wait a second before checking again */
  4988. if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
  4989. if (res > 0 && !valid_exit(qe, res)) {
  4990. res = 0;
  4991. } else {
  4992. break;
  4993. }
  4994. }
  4995. /* If we have timed out, break out */
  4996. if (qe->expire && (time(NULL) >= qe->expire)) {
  4997. *reason = QUEUE_TIMEOUT;
  4998. break;
  4999. }
  5000. }
  5001. return res;
  5002. }
  5003. /*!
  5004. * \brief update the queue status
  5005. * \retval Always 0
  5006. */
  5007. static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime)
  5008. {
  5009. int oldtalktime;
  5010. int newtalktime = time(NULL) - starttime;
  5011. struct member *mem;
  5012. struct call_queue *qtmp;
  5013. struct ao2_iterator queue_iter;
  5014. /* It is possible for us to be called when a call has already been considered terminated
  5015. * and data updated, so to ensure we only act on the call that the agent is currently in
  5016. * we check when the call was bridged.
  5017. */
  5018. if (!starttime || (member->starttime != starttime)) {
  5019. return 0;
  5020. }
  5021. if (shared_lastcall) {
  5022. queue_iter = ao2_iterator_init(queues, 0);
  5023. while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  5024. ao2_lock(qtmp);
  5025. if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
  5026. time(&mem->lastcall);
  5027. mem->calls++;
  5028. mem->callcompletedinsl = 0;
  5029. mem->starttime = 0;
  5030. mem->lastqueue = q;
  5031. ao2_ref(mem, -1);
  5032. }
  5033. ao2_unlock(qtmp);
  5034. queue_t_unref(qtmp, "Done with iterator");
  5035. }
  5036. ao2_iterator_destroy(&queue_iter);
  5037. } else {
  5038. ao2_lock(q);
  5039. time(&member->lastcall);
  5040. member->callcompletedinsl = 0;
  5041. member->calls++;
  5042. member->starttime = 0;
  5043. member->lastqueue = q;
  5044. ao2_unlock(q);
  5045. }
  5046. /* Member might never experience any direct status change (local
  5047. * channel with forwarding in particular). If that's the case,
  5048. * this is the last chance to remove it from pending or subsequent
  5049. * calls will not occur.
  5050. */
  5051. pending_members_remove(member);
  5052. ao2_lock(q);
  5053. q->callscompleted++;
  5054. if (callcompletedinsl) {
  5055. q->callscompletedinsl++;
  5056. }
  5057. if (q->callscompleted == 1) {
  5058. q->talktime = newtalktime;
  5059. } else {
  5060. /* Calculate talktime using the same exponential average as holdtime code */
  5061. oldtalktime = q->talktime;
  5062. q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
  5063. }
  5064. ao2_unlock(q);
  5065. return 0;
  5066. }
  5067. /*! \brief Calculate the metric of each member in the outgoing callattempts
  5068. *
  5069. * A numeric metric is given to each member depending on the ring strategy used
  5070. * by the queue. Members with lower metrics will be called before members with
  5071. * higher metrics
  5072. * \retval -1 if penalties are exceeded
  5073. * \retval 0 otherwise
  5074. */
  5075. static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
  5076. {
  5077. /* disregarding penalty on too few members? */
  5078. int membercount = ao2_container_count(q->members);
  5079. unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
  5080. if (usepenalty) {
  5081. if ((qe->max_penalty != INT_MAX && mem->penalty > qe->max_penalty) ||
  5082. (qe->min_penalty != INT_MAX && mem->penalty < qe->min_penalty)) {
  5083. return -1;
  5084. }
  5085. } else {
  5086. ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
  5087. membercount, q->penaltymemberslimit);
  5088. }
  5089. switch (q->strategy) {
  5090. case QUEUE_STRATEGY_RINGALL:
  5091. /* Everyone equal, except for penalty */
  5092. tmp->metric = mem->penalty * 1000000 * usepenalty;
  5093. break;
  5094. case QUEUE_STRATEGY_LINEAR:
  5095. if (pos < qe->linpos) {
  5096. tmp->metric = 1000 + pos;
  5097. } else {
  5098. if (pos > qe->linpos) {
  5099. /* Indicate there is another priority */
  5100. qe->linwrapped = 1;
  5101. }
  5102. tmp->metric = pos;
  5103. }
  5104. tmp->metric += mem->penalty * 1000000 * usepenalty;
  5105. break;
  5106. case QUEUE_STRATEGY_RRORDERED:
  5107. case QUEUE_STRATEGY_RRMEMORY:
  5108. pos = mem->queuepos;
  5109. if (pos < q->rrpos) {
  5110. tmp->metric = 1000 + pos;
  5111. } else {
  5112. if (pos > q->rrpos) {
  5113. /* Indicate there is another priority */
  5114. q->wrapped = 1;
  5115. }
  5116. tmp->metric = pos;
  5117. }
  5118. tmp->metric += mem->penalty * 1000000 * usepenalty;
  5119. break;
  5120. case QUEUE_STRATEGY_RANDOM:
  5121. tmp->metric = ast_random() % 1000;
  5122. tmp->metric += mem->penalty * 1000000 * usepenalty;
  5123. break;
  5124. case QUEUE_STRATEGY_WRANDOM:
  5125. tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
  5126. break;
  5127. case QUEUE_STRATEGY_FEWESTCALLS:
  5128. tmp->metric = mem->calls;
  5129. tmp->metric += mem->penalty * 1000000 * usepenalty;
  5130. break;
  5131. case QUEUE_STRATEGY_LEASTRECENT:
  5132. if (!mem->lastcall) {
  5133. tmp->metric = 0;
  5134. } else {
  5135. tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
  5136. }
  5137. tmp->metric += mem->penalty * 1000000 * usepenalty;
  5138. break;
  5139. default:
  5140. ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
  5141. break;
  5142. }
  5143. return 0;
  5144. }
  5145. enum agent_complete_reason {
  5146. CALLER,
  5147. AGENT,
  5148. TRANSFER
  5149. };
  5150. /*! \brief Send out AMI message with member call completion status information */
  5151. static void send_agent_complete(const char *queuename, struct ast_channel_snapshot *caller,
  5152. struct ast_channel_snapshot *peer, const struct member *member, time_t holdstart,
  5153. time_t callstart, enum agent_complete_reason rsn)
  5154. {
  5155. const char *reason = NULL; /* silence dumb compilers */
  5156. RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
  5157. switch (rsn) {
  5158. case CALLER:
  5159. reason = "caller";
  5160. break;
  5161. case AGENT:
  5162. reason = "agent";
  5163. break;
  5164. case TRANSFER:
  5165. reason = "transfer";
  5166. break;
  5167. }
  5168. blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: s}",
  5169. "Queue", queuename,
  5170. "Interface", member->interface,
  5171. "MemberName", member->membername,
  5172. "HoldTime", (long)(callstart - holdstart),
  5173. "TalkTime", (long)(time(NULL) - callstart),
  5174. "Reason", reason ?: "");
  5175. queue_publish_multi_channel_snapshot_blob(ast_queue_topic(queuename), caller, peer,
  5176. queue_agent_complete_type(), blob);
  5177. }
  5178. static void queue_agent_cb(void *userdata, struct stasis_subscription *sub,
  5179. struct stasis_message *msg)
  5180. {
  5181. struct ast_channel_blob *agent_blob;
  5182. agent_blob = stasis_message_data(msg);
  5183. if (ast_channel_agent_login_type() == stasis_message_type(msg)) {
  5184. ast_queue_log("NONE", agent_blob->snapshot->uniqueid,
  5185. ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
  5186. "AGENTLOGIN", "%s", agent_blob->snapshot->name);
  5187. } else if (ast_channel_agent_logoff_type() == stasis_message_type(msg)) {
  5188. ast_queue_log("NONE", agent_blob->snapshot->uniqueid,
  5189. ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
  5190. "AGENTLOGOFF", "%s|%ld", agent_blob->snapshot->name,
  5191. (long) ast_json_integer_get(ast_json_object_get(agent_blob->blob, "logintime")));
  5192. }
  5193. }
  5194. /*!
  5195. * \brief Structure representing relevant data during a local channel optimization
  5196. *
  5197. * The reason we care about local channel optimizations is that we want to be able
  5198. * to accurately report when the caller and queue member have stopped talking to
  5199. * each other. A local channel optimization can cause it to appear that the conversation
  5200. * has stopped immediately after it has begun. By tracking that the relevant channels
  5201. * to monitor have changed due to a local channel optimization, we can give accurate
  5202. * reports.
  5203. *
  5204. * Local channel optimizations for queues are restricted from their normal operation.
  5205. * Bridges created by queues can only be the destination of local channel optimizations,
  5206. * not the source. In addition, move-swap local channel optimizations are the only
  5207. * permitted types of local channel optimization.
  5208. *
  5209. * This data is populated when we are told that a local channel optimization begin
  5210. * is occurring. When we get told the optimization has ended successfully, we then
  5211. * apply the data here into the queue_stasis_data.
  5212. */
  5213. struct local_optimization {
  5214. /*! The uniqueid of the channel that will be taking the place of the caller or member */
  5215. const char *source_chan_uniqueid;
  5216. /*! Indication of whether we think there is a local channel optimization in progress */
  5217. int in_progress;
  5218. /*! The identifier for this local channel optimization */
  5219. unsigned int id;
  5220. };
  5221. /*!
  5222. * \brief User data for stasis subscriptions used for queue calls.
  5223. *
  5224. * app_queue subscribes to channel and bridge events for all bridged calls.
  5225. * app_queue cares about the following events:
  5226. *
  5227. * \li bridge enter: To determine the unique ID of the bridge created for the call.
  5228. * \li blind transfer: To send an appropriate agent complete event.
  5229. * \li attended transfer: To send an appropriate agent complete event.
  5230. * \li local optimization: To update caller and member unique IDs for the call.
  5231. * \li hangup: To send an appropriate agent complete event.
  5232. *
  5233. * The stasis subscriptions last until we determine that the caller and the member
  5234. * are no longer bridged with each other.
  5235. */
  5236. struct queue_stasis_data {
  5237. AST_DECLARE_STRING_FIELDS(
  5238. /*! The unique ID of the caller's channel. */
  5239. AST_STRING_FIELD(caller_uniqueid);
  5240. /*! The unique ID of the queue member's channel */
  5241. AST_STRING_FIELD(member_uniqueid);
  5242. /*! The unique ID of the bridge created by the queue */
  5243. AST_STRING_FIELD(bridge_uniqueid);
  5244. );
  5245. /*! The relevant queue */
  5246. struct call_queue *queue;
  5247. /*! The queue member that has answered the call */
  5248. struct member *member;
  5249. /*! The time at which the caller entered the queue. Start of the caller's hold time */
  5250. time_t holdstart;
  5251. /*! The time at which the member answered the call. */
  5252. time_t starttime;
  5253. /*! The original position of the caller when he entered the queue */
  5254. int caller_pos;
  5255. /*! Indication if the call was answered within the configured service level of the queue */
  5256. int callcompletedinsl;
  5257. /*! Indicates if the stasis subscriptions are shutting down */
  5258. int dying;
  5259. /*! The stasis message router for bridge events */
  5260. struct stasis_message_router *bridge_router;
  5261. /*! The stasis message router for channel events */
  5262. struct stasis_message_router *channel_router;
  5263. /*! Local channel optimization details for the caller */
  5264. struct local_optimization caller_optimize;
  5265. /*! Local channel optimization details for the member */
  5266. struct local_optimization member_optimize;
  5267. };
  5268. /*!
  5269. * \internal
  5270. * \brief Free memory for a queue_stasis_data
  5271. */
  5272. static void queue_stasis_data_destructor(void *obj)
  5273. {
  5274. struct queue_stasis_data *queue_data = obj;
  5275. /* This can only happen if refcounts for this object have got severely messed up */
  5276. ast_assert(queue_data->bridge_router == NULL);
  5277. ast_assert(queue_data->channel_router == NULL);
  5278. ao2_cleanup(queue_data->member);
  5279. queue_unref(queue_data->queue);
  5280. ast_string_field_free_memory(queue_data);
  5281. }
  5282. /*!
  5283. * \internal
  5284. * \brief End all stasis subscriptions on a queue_stasis_data
  5285. */
  5286. static void remove_stasis_subscriptions(struct queue_stasis_data *queue_data)
  5287. {
  5288. SCOPED_AO2LOCK(lock, queue_data);
  5289. queue_data->dying = 1;
  5290. stasis_message_router_unsubscribe(queue_data->bridge_router);
  5291. queue_data->bridge_router = NULL;
  5292. stasis_message_router_unsubscribe(queue_data->channel_router);
  5293. queue_data->channel_router = NULL;
  5294. }
  5295. /*!
  5296. * \internal
  5297. * \brief Allocate a queue_stasis_data and initialize its data.
  5298. */
  5299. static struct queue_stasis_data *queue_stasis_data_alloc(struct queue_ent *qe,
  5300. struct ast_channel *peer, struct member *mem, time_t holdstart,
  5301. time_t starttime, int callcompletedinsl)
  5302. {
  5303. struct queue_stasis_data *queue_data;
  5304. queue_data = ao2_alloc(sizeof(*queue_data), queue_stasis_data_destructor);
  5305. if (!queue_data) {
  5306. return NULL;
  5307. }
  5308. if (ast_string_field_init(queue_data, 64)) {
  5309. ao2_cleanup(queue_data);
  5310. return NULL;
  5311. }
  5312. ast_string_field_set(queue_data, caller_uniqueid, ast_channel_uniqueid(qe->chan));
  5313. ast_string_field_set(queue_data, member_uniqueid, ast_channel_uniqueid(peer));
  5314. queue_data->queue = queue_ref(qe->parent);
  5315. queue_data->starttime = starttime;
  5316. queue_data->holdstart = holdstart;
  5317. queue_data->callcompletedinsl = callcompletedinsl;
  5318. queue_data->caller_pos = qe->opos;
  5319. ao2_ref(mem, +1);
  5320. queue_data->member = mem;
  5321. return queue_data;
  5322. }
  5323. /*!
  5324. * \internal
  5325. * \brief Log an attended transfer in the queue log.
  5326. *
  5327. * Attended transfer queue log messages vary based on the method by which the
  5328. * attended transfer was completed.
  5329. *
  5330. * \param queue_data Data pertaining to the particular call in the queue.
  5331. * \param atxfer_msg The stasis attended transfer message data.
  5332. */
  5333. static void log_attended_transfer(struct queue_stasis_data *queue_data,
  5334. struct ast_attended_transfer_message *atxfer_msg)
  5335. {
  5336. RAII_VAR(struct ast_str *, transfer_str, ast_str_create(32), ast_free);
  5337. if (!transfer_str) {
  5338. ast_log(LOG_WARNING, "Unable to log attended transfer to queue log\n");
  5339. return;
  5340. }
  5341. switch (atxfer_msg->dest_type) {
  5342. case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
  5343. ast_str_set(&transfer_str, 0, "BRIDGE|%s", atxfer_msg->dest.bridge);
  5344. break;
  5345. case AST_ATTENDED_TRANSFER_DEST_APP:
  5346. case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
  5347. ast_str_set(&transfer_str, 0, "APP|%s", atxfer_msg->dest.app);
  5348. break;
  5349. case AST_ATTENDED_TRANSFER_DEST_LINK:
  5350. ast_str_set(&transfer_str, 0, "LINK|%s|%s", atxfer_msg->dest.links[0]->name,
  5351. atxfer_msg->dest.links[1]->name);
  5352. break;
  5353. case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
  5354. case AST_ATTENDED_TRANSFER_DEST_FAIL:
  5355. /* Threeways are headed off and should not be logged here */
  5356. ast_assert(0);
  5357. return;
  5358. }
  5359. ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername, "ATTENDEDTRANSFER", "%s|%ld|%ld|%d",
  5360. ast_str_buffer(transfer_str),
  5361. (long) (queue_data->starttime - queue_data->holdstart),
  5362. (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
  5363. }
  5364. /*!
  5365. * \internal
  5366. * \brief Handle a stasis bridge enter event.
  5367. *
  5368. * We track this particular event in order to learn what bridge
  5369. * was created for the queue call.
  5370. *
  5371. * \param userdata Data pertaining to the particular call in the queue.
  5372. * \param sub The stasis subscription on which the message occurred.
  5373. * \param topic The topic for this event.
  5374. * \param msg The stasis message for the bridge enter event
  5375. */
  5376. static void handle_bridge_enter(void *userdata, struct stasis_subscription *sub,
  5377. struct stasis_message *msg)
  5378. {
  5379. struct queue_stasis_data *queue_data = userdata;
  5380. struct ast_bridge_blob *enter_blob = stasis_message_data(msg);
  5381. SCOPED_AO2LOCK(lock, queue_data);
  5382. if (queue_data->dying) {
  5383. return;
  5384. }
  5385. if (!ast_strlen_zero(queue_data->bridge_uniqueid)) {
  5386. return;
  5387. }
  5388. if (!strcmp(enter_blob->channel->uniqueid, queue_data->caller_uniqueid)) {
  5389. ast_string_field_set(queue_data, bridge_uniqueid,
  5390. enter_blob->bridge->uniqueid);
  5391. ast_debug(3, "Detected entry of caller channel %s into bridge %s\n",
  5392. enter_blob->channel->name, queue_data->bridge_uniqueid);
  5393. }
  5394. }
  5395. /*!
  5396. * \brief Handle a blind transfer event
  5397. *
  5398. * This event is important in order to be able to log the end of the
  5399. * call to the queue log and to stasis.
  5400. *
  5401. * \param userdata Data pertaining to the particular call in the queue.
  5402. * \param sub The stasis subscription on which the message occurred.
  5403. * \param topic The topic for this event.
  5404. * \param msg The stasis message for the blind transfer event
  5405. */
  5406. static void handle_blind_transfer(void *userdata, struct stasis_subscription *sub,
  5407. struct stasis_message *msg)
  5408. {
  5409. struct queue_stasis_data *queue_data = userdata;
  5410. struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
  5411. const char *exten;
  5412. const char *context;
  5413. RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
  5414. RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
  5415. if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
  5416. return;
  5417. }
  5418. ao2_lock(queue_data);
  5419. if (queue_data->dying) {
  5420. ao2_unlock(queue_data);
  5421. return;
  5422. }
  5423. if (ast_strlen_zero(queue_data->bridge_uniqueid) ||
  5424. strcmp(queue_data->bridge_uniqueid, transfer_msg->bridge->uniqueid)) {
  5425. ao2_unlock(queue_data);
  5426. return;
  5427. }
  5428. caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
  5429. member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
  5430. ao2_unlock(queue_data);
  5431. exten = transfer_msg->exten;
  5432. context = transfer_msg->context;
  5433. ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);
  5434. ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
  5435. "BLINDTRANSFER", "%s|%s|%ld|%ld|%d",
  5436. exten, context,
  5437. (long) (queue_data->starttime - queue_data->holdstart),
  5438. (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
  5439. send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
  5440. queue_data->holdstart, queue_data->starttime, TRANSFER);
  5441. update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
  5442. queue_data->starttime);
  5443. remove_stasis_subscriptions(queue_data);
  5444. }
  5445. /*!
  5446. * \brief Handle an attended transfer event
  5447. *
  5448. * This event is important in order to be able to log the end of the
  5449. * call to the queue log and to stasis.
  5450. *
  5451. * \param userdata Data pertaining to the particular call in the queue.
  5452. * \param sub The stasis subscription on which the message occurred.
  5453. * \param topic The topic for this event.
  5454. * \param msg The stasis message for the attended transfer event.
  5455. */
  5456. static void handle_attended_transfer(void *userdata, struct stasis_subscription *sub,
  5457. struct stasis_message *msg)
  5458. {
  5459. struct queue_stasis_data *queue_data = userdata;
  5460. struct ast_attended_transfer_message *atxfer_msg = stasis_message_data(msg);
  5461. RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
  5462. RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
  5463. if (atxfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS ||
  5464. atxfer_msg->dest_type == AST_ATTENDED_TRANSFER_DEST_THREEWAY) {
  5465. return;
  5466. }
  5467. ao2_lock(queue_data);
  5468. if (queue_data->dying) {
  5469. ao2_unlock(queue_data);
  5470. return;
  5471. }
  5472. if (ast_strlen_zero(queue_data->bridge_uniqueid)) {
  5473. ao2_unlock(queue_data);
  5474. return;
  5475. }
  5476. if ((!atxfer_msg->to_transferee.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
  5477. atxfer_msg->to_transferee.bridge_snapshot->uniqueid)) &&
  5478. (!atxfer_msg->to_transfer_target.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
  5479. atxfer_msg->to_transfer_target.bridge_snapshot->uniqueid))) {
  5480. ao2_unlock(queue_data);
  5481. return;
  5482. }
  5483. caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
  5484. member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
  5485. ao2_unlock(queue_data);
  5486. ast_debug(3, "Detected attended transfer in queue %s\n", queue_data->queue->name);
  5487. log_attended_transfer(queue_data, atxfer_msg);
  5488. send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
  5489. queue_data->holdstart, queue_data->starttime, TRANSFER);
  5490. update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
  5491. queue_data->starttime);
  5492. remove_stasis_subscriptions(queue_data);
  5493. }
  5494. /*!
  5495. * \internal
  5496. * \brief Callback for all stasis bridge events
  5497. *
  5498. * Based on the event and what bridge it is on, the task is farmed out to relevant
  5499. * subroutines for further processing.
  5500. */
  5501. static void queue_bridge_cb(void *userdata, struct stasis_subscription *sub,
  5502. struct stasis_message *msg)
  5503. {
  5504. if (stasis_subscription_final_message(sub, msg)) {
  5505. ao2_cleanup(userdata);
  5506. }
  5507. }
  5508. /*!
  5509. * \internal
  5510. * \brief Handler for the beginning of a local channel optimization
  5511. *
  5512. * This method gathers data relevant to the local channel optimization and stores
  5513. * it to be used once the local optimization completes.
  5514. *
  5515. * \param userdata Data pertaining to the particular call in the queue.
  5516. * \param sub The stasis subscription on which the message occurred.
  5517. * \param topic The topic for this event.
  5518. * \param msg The stasis message for the local optimization begin event
  5519. */
  5520. static void handle_local_optimization_begin(void *userdata, struct stasis_subscription *sub,
  5521. struct stasis_message *msg)
  5522. {
  5523. struct queue_stasis_data *queue_data = userdata;
  5524. struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
  5525. struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
  5526. struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
  5527. struct ast_channel_snapshot *source = ast_multi_channel_blob_get_channel(optimization_blob, "source");
  5528. struct local_optimization *optimization;
  5529. unsigned int id;
  5530. SCOPED_AO2LOCK(lock, queue_data);
  5531. if (queue_data->dying) {
  5532. return;
  5533. }
  5534. if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {
  5535. optimization = &queue_data->member_optimize;
  5536. } else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
  5537. optimization = &queue_data->caller_optimize;
  5538. } else {
  5539. return;
  5540. }
  5541. /* We only allow move-swap optimizations, so there had BETTER be a source */
  5542. ast_assert(source != NULL);
  5543. optimization->source_chan_uniqueid = ast_strdup(source->uniqueid);
  5544. if (!optimization->source_chan_uniqueid) {
  5545. ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->name);
  5546. return;
  5547. }
  5548. id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));
  5549. optimization->id = id;
  5550. optimization->in_progress = 1;
  5551. }
  5552. /*!
  5553. * \internal
  5554. * \brief Handler for the end of a local channel optimization
  5555. *
  5556. * This method takes the data gathered during the local channel optimization begin
  5557. * event and applies it to the queue stasis data appropriately. This generally involves
  5558. * updating the caller or member unique ID with the channel that is taking the place of
  5559. * the previous caller or member.
  5560. *
  5561. * \param userdata Data pertaining to the particular call in the queue.
  5562. * \param sub The stasis subscription on which the message occurred.
  5563. * \param topic The topic for this event.
  5564. * \param msg The stasis message for the local optimization end event
  5565. */
  5566. static void handle_local_optimization_end(void *userdata, struct stasis_subscription *sub,
  5567. struct stasis_message *msg)
  5568. {
  5569. struct queue_stasis_data *queue_data = userdata;
  5570. struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
  5571. struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
  5572. struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
  5573. struct local_optimization *optimization;
  5574. int is_caller;
  5575. unsigned int id;
  5576. SCOPED_AO2LOCK(lock, queue_data);
  5577. if (queue_data->dying) {
  5578. return;
  5579. }
  5580. if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {
  5581. optimization = &queue_data->member_optimize;
  5582. is_caller = 0;
  5583. } else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
  5584. optimization = &queue_data->caller_optimize;
  5585. is_caller = 1;
  5586. } else {
  5587. return;
  5588. }
  5589. id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));
  5590. if (!optimization->in_progress) {
  5591. ast_log(LOG_WARNING, "Told of a local optimization end when we had no previous begin\n");
  5592. return;
  5593. }
  5594. if (id != optimization->id) {
  5595. ast_log(LOG_WARNING, "Local optimization end event ID does not match begin (%u != %u)\n",
  5596. id, optimization->id);
  5597. return;
  5598. }
  5599. if (is_caller) {
  5600. ast_debug(3, "Local optimization: Changing queue caller uniqueid from %s to %s\n",
  5601. queue_data->caller_uniqueid, optimization->source_chan_uniqueid);
  5602. ast_string_field_set(queue_data, caller_uniqueid, optimization->source_chan_uniqueid);
  5603. } else {
  5604. ast_debug(3, "Local optimization: Changing queue member uniqueid from %s to %s\n",
  5605. queue_data->member_uniqueid, optimization->source_chan_uniqueid);
  5606. ast_string_field_set(queue_data, member_uniqueid, optimization->source_chan_uniqueid);
  5607. }
  5608. optimization->in_progress = 0;
  5609. }
  5610. /*!
  5611. * \internal
  5612. * \brief Handler for hangup stasis event
  5613. *
  5614. * This is how we determine that the caller or member has hung up and the call
  5615. * has ended. An appropriate queue log and stasis message are raised in this
  5616. * callback.
  5617. *
  5618. * \param userdata Data pertaining to the particular call in the queue.
  5619. * \param sub The stasis subscription on which the message occurred.
  5620. * \param topic The topic for this event.
  5621. * \param msg The stasis message for the hangup event.
  5622. */
  5623. static void handle_hangup(void *userdata, struct stasis_subscription *sub,
  5624. struct stasis_message *msg)
  5625. {
  5626. struct queue_stasis_data *queue_data = userdata;
  5627. struct ast_channel_blob *channel_blob = stasis_message_data(msg);
  5628. RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
  5629. RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
  5630. RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
  5631. enum agent_complete_reason reason;
  5632. ao2_lock(queue_data);
  5633. if (queue_data->dying) {
  5634. ao2_unlock(queue_data);
  5635. return;
  5636. }
  5637. if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->caller_uniqueid)) {
  5638. reason = CALLER;
  5639. } else if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->member_uniqueid)) {
  5640. reason = AGENT;
  5641. } else {
  5642. ao2_unlock(queue_data);
  5643. return;
  5644. }
  5645. chan = ast_channel_get_by_name(channel_blob->snapshot->name);
  5646. if (chan && (ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME) ||
  5647. !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER")) ||
  5648. !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER")))) {
  5649. /* Channel that is hanging up is doing it as part of a transfer.
  5650. * We'll get a transfer event later
  5651. */
  5652. ao2_unlock(queue_data);
  5653. return;
  5654. }
  5655. caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
  5656. member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
  5657. ao2_unlock(queue_data);
  5658. ast_debug(3, "Detected hangup of queue %s channel %s\n", reason == CALLER ? "caller" : "member",
  5659. channel_blob->snapshot->name);
  5660. ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
  5661. reason == CALLER ? "COMPLETECALLER" : "COMPLETEAGENT", "%ld|%ld|%d",
  5662. (long) (queue_data->starttime - queue_data->holdstart),
  5663. (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
  5664. send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
  5665. queue_data->holdstart, queue_data->starttime, reason);
  5666. update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
  5667. queue_data->starttime);
  5668. remove_stasis_subscriptions(queue_data);
  5669. }
  5670. /*!
  5671. * \internal
  5672. * \brief Callback for all stasis channel events
  5673. *
  5674. * Based on the event and the channels involved, the work is farmed out into
  5675. * subroutines for further processing.
  5676. */
  5677. static void queue_channel_cb(void *userdata, struct stasis_subscription *sub,
  5678. struct stasis_message *msg)
  5679. {
  5680. if (stasis_subscription_final_message(sub, msg)) {
  5681. ao2_cleanup(userdata);
  5682. }
  5683. }
  5684. /*!
  5685. * \internal
  5686. * \brief Create stasis subscriptions for a particular call in the queue.
  5687. *
  5688. * These subscriptions are created once the call has been answered. The subscriptions
  5689. * are put in place so that call progress may be tracked. Once the call can be determined
  5690. * to have ended, then messages are logged to the queue log and stasis events are emitted.
  5691. *
  5692. * \param qe The queue entry representing the caller
  5693. * \param peer The channel that has answered the call
  5694. * \param mem The queue member that answered the call
  5695. * \param holdstart The time at which the caller entered the queue
  5696. * \param starttime The time at which the call was answered
  5697. * \param callcompletedinsl Indicates if the call was answered within the configured service level of the queue.
  5698. * \retval 0 Success
  5699. * \retval non-zero Failure
  5700. */
  5701. static int setup_stasis_subs(struct queue_ent *qe, struct ast_channel *peer, struct member *mem,
  5702. time_t holdstart, time_t starttime, int callcompletedinsl)
  5703. {
  5704. struct queue_stasis_data *queue_data = queue_stasis_data_alloc(qe, peer, mem, holdstart, starttime, callcompletedinsl);
  5705. if (!queue_data) {
  5706. return -1;
  5707. }
  5708. queue_data->bridge_router = stasis_message_router_create_pool(ast_bridge_topic_all());
  5709. if (!queue_data->bridge_router) {
  5710. ao2_ref(queue_data, -1);
  5711. return -1;
  5712. }
  5713. stasis_message_router_add(queue_data->bridge_router, ast_channel_entered_bridge_type(),
  5714. handle_bridge_enter, queue_data);
  5715. stasis_message_router_add(queue_data->bridge_router, ast_blind_transfer_type(),
  5716. handle_blind_transfer, queue_data);
  5717. stasis_message_router_add(queue_data->bridge_router, ast_attended_transfer_type(),
  5718. handle_attended_transfer, queue_data);
  5719. stasis_message_router_set_default(queue_data->bridge_router,
  5720. queue_bridge_cb, queue_data);
  5721. queue_data->channel_router = stasis_message_router_create_pool(ast_channel_topic_all());
  5722. if (!queue_data->channel_router) {
  5723. /* Unsubscribing from the bridge router will remove the only ref of queue_data,
  5724. * thus beginning the destruction process
  5725. */
  5726. stasis_message_router_unsubscribe(queue_data->bridge_router);
  5727. queue_data->bridge_router = NULL;
  5728. return -1;
  5729. }
  5730. ao2_ref(queue_data, +1);
  5731. stasis_message_router_add(queue_data->channel_router, ast_local_optimization_begin_type(),
  5732. handle_local_optimization_begin, queue_data);
  5733. stasis_message_router_add(queue_data->channel_router, ast_local_optimization_end_type(),
  5734. handle_local_optimization_end, queue_data);
  5735. stasis_message_router_add(queue_data->channel_router, ast_channel_hangup_request_type(),
  5736. handle_hangup, queue_data);
  5737. stasis_message_router_set_default(queue_data->channel_router,
  5738. queue_channel_cb, queue_data);
  5739. return 0;
  5740. }
  5741. struct queue_end_bridge {
  5742. struct call_queue *q;
  5743. struct ast_channel *chan;
  5744. };
  5745. static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
  5746. {
  5747. struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
  5748. ao2_ref(qeb, +1);
  5749. qeb->chan = originator;
  5750. }
  5751. static void end_bridge_callback(void *data)
  5752. {
  5753. struct queue_end_bridge *qeb = data;
  5754. struct call_queue *q = qeb->q;
  5755. struct ast_channel *chan = qeb->chan;
  5756. if (ao2_ref(qeb, -1) == 1) {
  5757. set_queue_variables(q, chan);
  5758. /* This unrefs the reference we made in try_calling when we allocated qeb */
  5759. queue_t_unref(q, "Expire bridge_config reference");
  5760. }
  5761. }
  5762. /*!
  5763. * \internal
  5764. * \brief Setup the after bridge goto location on the peer.
  5765. * \since 12.0.0
  5766. *
  5767. * \param chan Calling channel for bridge.
  5768. * \param peer Peer channel for bridge.
  5769. * \param opts Dialing option flags.
  5770. * \param opt_args Dialing option argument strings.
  5771. *
  5772. * \return Nothing
  5773. */
  5774. static void setup_peer_after_bridge_goto(struct ast_channel *chan, struct ast_channel *peer, struct ast_flags *opts, char *opt_args[])
  5775. {
  5776. const char *context;
  5777. const char *extension;
  5778. int priority;
  5779. if (ast_test_flag(opts, OPT_CALLEE_GO_ON)) {
  5780. ast_channel_lock(chan);
  5781. context = ast_strdupa(ast_channel_context(chan));
  5782. extension = ast_strdupa(ast_channel_exten(chan));
  5783. priority = ast_channel_priority(chan);
  5784. ast_channel_unlock(chan);
  5785. ast_bridge_set_after_go_on(peer, context, extension, priority,
  5786. opt_args[OPT_ARG_CALLEE_GO_ON]);
  5787. }
  5788. }
  5789. static void escape_and_substitute(struct ast_channel *chan, const char *input,
  5790. char *output, size_t size)
  5791. {
  5792. const char *m = input;
  5793. char escaped[size];
  5794. char *p;
  5795. for (p = escaped; p < escaped + size - 1; p++, m++) {
  5796. switch (*m) {
  5797. case '^':
  5798. if (*(m + 1) == '{') {
  5799. *p = '$';
  5800. }
  5801. break;
  5802. case ',':
  5803. *p++ = '\\';
  5804. /* Fall through */
  5805. default:
  5806. *p = *m;
  5807. }
  5808. if (*m == '\0')
  5809. break;
  5810. }
  5811. if (p == escaped + size) {
  5812. escaped[size - 1] = '\0';
  5813. }
  5814. pbx_substitute_variables_helper(chan, escaped, output, size - 1);
  5815. }
  5816. static void setup_mixmonitor(struct queue_ent *qe, const char *filename)
  5817. {
  5818. char escaped_filename[256];
  5819. char file_with_ext[sizeof(escaped_filename) + sizeof(qe->parent->monfmt)];
  5820. char mixmonargs[1512];
  5821. char escaped_monitor_exec[1024];
  5822. const char *monitor_options;
  5823. const char *monitor_exec;
  5824. escaped_monitor_exec[0] = '\0';
  5825. if (filename) {
  5826. escape_and_substitute(qe->chan, filename, escaped_filename, sizeof(escaped_filename));
  5827. } else {
  5828. ast_copy_string(escaped_filename, ast_channel_uniqueid(qe->chan), sizeof(escaped_filename));
  5829. }
  5830. ast_channel_lock(qe->chan);
  5831. if ((monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC"))) {
  5832. monitor_exec = ast_strdupa(monitor_exec);
  5833. }
  5834. if ((monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS"))) {
  5835. monitor_options = ast_strdupa(monitor_options);
  5836. } else {
  5837. monitor_options = "";
  5838. }
  5839. ast_channel_unlock(qe->chan);
  5840. if (monitor_exec) {
  5841. escape_and_substitute(qe->chan, monitor_exec, escaped_monitor_exec, sizeof(escaped_monitor_exec));
  5842. }
  5843. snprintf(file_with_ext, sizeof(file_with_ext), "%s.%s", escaped_filename, qe->parent->monfmt);
  5844. if (!ast_strlen_zero(escaped_monitor_exec)) {
  5845. snprintf(mixmonargs, sizeof(mixmonargs), "b%s,%s", monitor_options, escaped_monitor_exec);
  5846. } else {
  5847. snprintf(mixmonargs, sizeof(mixmonargs), "b%s", monitor_options);
  5848. }
  5849. ast_debug(1, "Arguments being passed to MixMonitor: %s,%s\n", file_with_ext, mixmonargs);
  5850. if (ast_start_mixmonitor(qe->chan, file_with_ext, mixmonargs)) {
  5851. ast_log(LOG_WARNING, "Unable to start mixmonitor. Is the MixMonitor app loaded?\n");
  5852. }
  5853. }
  5854. /*!
  5855. * \internal
  5856. * \brief A large function which calls members, updates statistics, and bridges the caller and a member
  5857. *
  5858. * Here is the process of this function
  5859. * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
  5860. * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member.
  5861. * 3. Call ring_one to place a call to the appropriate member(s)
  5862. * 4. Call wait_for_answer to wait for an answer. If no one answers, return.
  5863. * 5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
  5864. * 6. Start the monitor or mixmonitor if the option is set
  5865. * 7. Remove the caller from the queue to allow other callers to advance
  5866. * 8. Bridge the call.
  5867. * 9. Do any post processing after the call has disconnected.
  5868. *
  5869. * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
  5870. * \param[in] opts the options passed as the third parameter to the Queue() application
  5871. * \param[in] opt_args the options passed as the third parameter to the Queue() application
  5872. * \param[in] announceoverride filename to play to user when waiting
  5873. * \param[in] url the url passed as the fourth parameter to the Queue() application
  5874. * \param[in,out] tries the number of times we have tried calling queue members
  5875. * \param[out] noption set if the call to Queue() has the 'n' option set.
  5876. * \param[in] agi the agi passed as the fifth parameter to the Queue() application
  5877. * \param[in] macro the macro passed as the sixth parameter to the Queue() application
  5878. * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
  5879. * \param[in] ringing 1 if the 'r' option is set, otherwise 0
  5880. */
  5881. static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
  5882. {
  5883. struct member *cur;
  5884. struct callattempt *outgoing = NULL; /* the list of calls we are building */
  5885. int to, orig;
  5886. char oldexten[AST_MAX_EXTENSION]="";
  5887. char oldcontext[AST_MAX_CONTEXT]="";
  5888. char queuename[256]="";
  5889. struct ast_channel *peer;
  5890. struct ast_channel *which;
  5891. struct callattempt *lpeer;
  5892. struct member *member;
  5893. struct ast_app *application;
  5894. int res = 0, bridge = 0;
  5895. int numbusies = 0;
  5896. int x=0;
  5897. char *announce = NULL;
  5898. char digit = 0;
  5899. time_t now = time(NULL);
  5900. struct ast_bridge_config bridge_config;
  5901. char nondataquality = 1;
  5902. char *agiexec = NULL;
  5903. char *macroexec = NULL;
  5904. char *gosubexec = NULL;
  5905. const char *monitorfilename;
  5906. char tmpid[256];
  5907. int forwardsallowed = 1;
  5908. int block_connected_line = 0;
  5909. struct ao2_iterator memi;
  5910. struct queue_end_bridge *queue_end_bridge = NULL;
  5911. int callcompletedinsl;
  5912. time_t starttime;
  5913. memset(&bridge_config, 0, sizeof(bridge_config));
  5914. tmpid[0] = 0;
  5915. time(&now);
  5916. /* If we've already exceeded our timeout, then just stop
  5917. * This should be extremely rare. queue_exec will take care
  5918. * of removing the caller and reporting the timeout as the reason.
  5919. */
  5920. if (qe->expire && now >= qe->expire) {
  5921. res = 0;
  5922. goto out;
  5923. }
  5924. if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER)) {
  5925. ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
  5926. }
  5927. if (ast_test_flag(&opts, OPT_CALLER_TRANSFER)) {
  5928. ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
  5929. }
  5930. if (ast_test_flag(&opts, OPT_CALLEE_AUTOMON)) {
  5931. ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
  5932. }
  5933. if (ast_test_flag(&opts, OPT_CALLER_AUTOMON)) {
  5934. ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
  5935. }
  5936. if (ast_test_flag(&opts, OPT_DATA_QUALITY)) {
  5937. nondataquality = 0;
  5938. }
  5939. if (ast_test_flag(&opts, OPT_CALLEE_HANGUP)) {
  5940. ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
  5941. }
  5942. if (ast_test_flag(&opts, OPT_CALLER_HANGUP)) {
  5943. ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
  5944. }
  5945. if (ast_test_flag(&opts, OPT_CALLEE_PARK)) {
  5946. ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
  5947. }
  5948. if (ast_test_flag(&opts, OPT_CALLER_PARK)) {
  5949. ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
  5950. }
  5951. if (ast_test_flag(&opts, OPT_NO_RETRY)) {
  5952. if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR
  5953. || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
  5954. (*tries)++;
  5955. } else {
  5956. *tries = ao2_container_count(qe->parent->members);
  5957. }
  5958. *noption = 1;
  5959. }
  5960. if (ast_test_flag(&opts, OPT_IGNORE_CALL_FW)) {
  5961. forwardsallowed = 0;
  5962. }
  5963. if (ast_test_flag(&opts, OPT_IGNORE_CONNECTEDLINE)) {
  5964. block_connected_line = 1;
  5965. }
  5966. if (ast_test_flag(&opts, OPT_CALLEE_AUTOMIXMON)) {
  5967. ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
  5968. }
  5969. if (ast_test_flag(&opts, OPT_CALLER_AUTOMIXMON)) {
  5970. ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
  5971. }
  5972. if (ast_test_flag(&opts, OPT_MARK_AS_ANSWERED)) {
  5973. qe->cancel_answered_elsewhere = 1;
  5974. }
  5975. /* if the calling channel has AST_CAUSE_ANSWERED_ELSEWHERE set, make sure this is inherited.
  5976. (this is mainly to support unreal/local channels)
  5977. */
  5978. if (ast_channel_hangupcause(qe->chan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
  5979. qe->cancel_answered_elsewhere = 1;
  5980. }
  5981. ao2_lock(qe->parent);
  5982. ast_debug(1, "%s is trying to call a queue member.\n",
  5983. ast_channel_name(qe->chan));
  5984. ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
  5985. if (!ast_strlen_zero(qe->announce)) {
  5986. announce = qe->announce;
  5987. }
  5988. if (!ast_strlen_zero(announceoverride)) {
  5989. announce = announceoverride;
  5990. }
  5991. memi = ao2_iterator_init(qe->parent->members, 0);
  5992. while ((cur = ao2_iterator_next(&memi))) {
  5993. struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
  5994. if (!tmp) {
  5995. ao2_ref(cur, -1);
  5996. ao2_iterator_destroy(&memi);
  5997. ao2_unlock(qe->parent);
  5998. goto out;
  5999. }
  6000. /*
  6001. * Seed the callattempt's connected line information with previously
  6002. * acquired connected line info from the queued channel. The
  6003. * previously acquired connected line info could have been set
  6004. * through the CONNECTED_LINE dialplan function.
  6005. */
  6006. ast_channel_lock(qe->chan);
  6007. ast_party_connected_line_copy(&tmp->connected, ast_channel_connected(qe->chan));
  6008. ast_channel_unlock(qe->chan);
  6009. tmp->block_connected_update = block_connected_line;
  6010. tmp->stillgoing = 1;
  6011. tmp->member = cur;/* Place the reference for cur into callattempt. */
  6012. tmp->lastcall = cur->lastcall;
  6013. tmp->lastqueue = cur->lastqueue;
  6014. ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
  6015. /* Special case: If we ring everyone, go ahead and ring them, otherwise
  6016. just calculate their metric for the appropriate strategy */
  6017. if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
  6018. /* Put them in the list of outgoing thingies... We're ready now.
  6019. XXX If we're forcibly removed, these outgoing calls won't get
  6020. hung up XXX */
  6021. tmp->q_next = outgoing;
  6022. outgoing = tmp;
  6023. /* If this line is up, don't try anybody else */
  6024. if (outgoing->chan && (ast_channel_state(outgoing->chan) == AST_STATE_UP))
  6025. break;
  6026. } else {
  6027. callattempt_free(tmp);
  6028. }
  6029. }
  6030. ao2_iterator_destroy(&memi);
  6031. if (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP) {
  6032. /* Application arguments have higher timeout priority (behaviour for <=1.6) */
  6033. if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout)) {
  6034. to = (qe->expire - now) * 1000;
  6035. } else {
  6036. to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
  6037. }
  6038. } else {
  6039. /* Config timeout is higher priority thatn application timeout */
  6040. if (qe->expire && qe->expire<=now) {
  6041. to = 0;
  6042. } else if (qe->parent->timeout) {
  6043. to = qe->parent->timeout * 1000;
  6044. } else {
  6045. to = -1;
  6046. }
  6047. }
  6048. orig = to;
  6049. ++qe->pending;
  6050. ao2_unlock(qe->parent);
  6051. ring_one(qe, outgoing, &numbusies);
  6052. lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,
  6053. ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),
  6054. forwardsallowed);
  6055. ao2_lock(qe->parent);
  6056. if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
  6057. store_next_rr(qe, outgoing);
  6058. }
  6059. if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
  6060. store_next_lin(qe, outgoing);
  6061. }
  6062. ao2_unlock(qe->parent);
  6063. peer = lpeer ? lpeer->chan : NULL;
  6064. if (!peer) {
  6065. qe->pending = 0;
  6066. if (to) {
  6067. /* Must gotten hung up */
  6068. res = -1;
  6069. } else {
  6070. /* User exited by pressing a digit */
  6071. res = digit;
  6072. }
  6073. if (res == -1) {
  6074. ast_debug(1, "%s: Nobody answered.\n", ast_channel_name(qe->chan));
  6075. }
  6076. } else { /* peer is valid */
  6077. RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
  6078. RAII_VAR(struct ast_str *, interfacevar, ast_str_create(325), ast_free);
  6079. /* Ah ha! Someone answered within the desired timeframe. Of course after this
  6080. we will always return with -1 so that it is hung up properly after the
  6081. conversation. */
  6082. if (!strcmp(ast_channel_tech(qe->chan)->type, "DAHDI")) {
  6083. ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
  6084. }
  6085. if (!strcmp(ast_channel_tech(peer)->type, "DAHDI")) {
  6086. ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
  6087. }
  6088. /* Update parameters for the queue */
  6089. time(&now);
  6090. recalc_holdtime(qe, (now - qe->start));
  6091. member = lpeer->member;
  6092. ao2_lock(qe->parent);
  6093. callcompletedinsl = member->callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
  6094. ao2_unlock(qe->parent);
  6095. /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
  6096. ao2_ref(member, 1);
  6097. hangupcalls(qe, outgoing, peer, qe->cancel_answered_elsewhere);
  6098. outgoing = NULL;
  6099. if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
  6100. int res2;
  6101. res2 = ast_autoservice_start(qe->chan);
  6102. if (!res2) {
  6103. if (qe->parent->memberdelay) {
  6104. ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
  6105. res2 = ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
  6106. }
  6107. if (!res2 && announce) {
  6108. if (play_file(peer, announce) < 0) {
  6109. ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", announce, ast_channel_name(peer));
  6110. }
  6111. }
  6112. if (!res2 && qe->parent->reportholdtime) {
  6113. if (!play_file(peer, qe->parent->sound_reporthold)) {
  6114. long holdtime, holdtimesecs;
  6115. time(&now);
  6116. holdtime = labs((now - qe->start) / 60);
  6117. holdtimesecs = labs((now - qe->start) % 60);
  6118. if (holdtime > 0) {
  6119. ast_say_number(peer, holdtime, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
  6120. if (play_file(peer, qe->parent->sound_minutes) < 0) {
  6121. ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, ast_channel_name(peer));
  6122. }
  6123. }
  6124. if (holdtimesecs > 1) {
  6125. ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
  6126. if (play_file(peer, qe->parent->sound_seconds) < 0) {
  6127. ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, ast_channel_name(peer));
  6128. }
  6129. }
  6130. }
  6131. }
  6132. ast_autoservice_stop(qe->chan);
  6133. }
  6134. if (ast_check_hangup(peer)) {
  6135. /* Agent must have hung up */
  6136. ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", ast_channel_name(peer));
  6137. ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "AGENTDUMP", "%s", "");
  6138. blob = ast_json_pack("{s: s, s: s, s: s}",
  6139. "Queue", queuename,
  6140. "Interface", member->interface,
  6141. "MemberName", member->membername);
  6142. queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_dump_type(), blob);
  6143. ast_channel_publish_dial(qe->chan, peer, member->interface, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(peer)));
  6144. ast_autoservice_chan_hangup_peer(qe->chan, peer);
  6145. pending_members_remove(member);
  6146. ao2_ref(member, -1);
  6147. goto out;
  6148. } else if (ast_check_hangup(qe->chan)) {
  6149. /* Caller must have hung up just before being connected */
  6150. ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", ast_channel_name(peer));
  6151. ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) (time(NULL) - qe->start));
  6152. record_abandoned(qe);
  6153. qe->handled = -1;
  6154. ast_channel_publish_dial(qe->chan, peer, member->interface, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(peer)));
  6155. ast_autoservice_chan_hangup_peer(qe->chan, peer);
  6156. pending_members_remove(member);
  6157. ao2_ref(member, -1);
  6158. return -1;
  6159. }
  6160. }
  6161. /* Stop music on hold */
  6162. if (ringing) {
  6163. ast_indicate(qe->chan,-1);
  6164. } else {
  6165. ast_moh_stop(qe->chan);
  6166. }
  6167. /* Make sure channels are compatible */
  6168. res = ast_channel_make_compatible(qe->chan, peer);
  6169. if (res < 0) {
  6170. ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "SYSCOMPAT", "%s", "");
  6171. ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(qe->chan), ast_channel_name(peer));
  6172. record_abandoned(qe);
  6173. ast_channel_publish_dial(qe->chan, peer, member->interface, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(peer)));
  6174. ast_autoservice_chan_hangup_peer(qe->chan, peer);
  6175. pending_members_remove(member);
  6176. ao2_ref(member, -1);
  6177. return -1;
  6178. }
  6179. /* Play announcement to the caller telling it's his turn if defined */
  6180. if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
  6181. if (play_file(qe->chan, qe->parent->sound_callerannounce)) {
  6182. ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
  6183. }
  6184. }
  6185. ao2_lock(qe->parent);
  6186. /* if setinterfacevar is defined, make member variables available to the channel */
  6187. /* use pbx_builtin_setvar to set a load of variables with one call */
  6188. if (qe->parent->setinterfacevar && interfacevar) {
  6189. ast_str_set(&interfacevar, 0, "MEMBERINTERFACE=%s,MEMBERNAME=%s,MEMBERCALLS=%d,MEMBERLASTCALL=%ld,MEMBERPENALTY=%d,MEMBERDYNAMIC=%d,MEMBERREALTIME=%d",
  6190. member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
  6191. pbx_builtin_setvar_multiple(qe->chan, ast_str_buffer(interfacevar));
  6192. pbx_builtin_setvar_multiple(peer, ast_str_buffer(interfacevar));
  6193. }
  6194. /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
  6195. /* use pbx_builtin_setvar to set a load of variables with one call */
  6196. if (qe->parent->setqueueentryvar && interfacevar) {
  6197. ast_str_set(&interfacevar, 0, "QEHOLDTIME=%ld,QEORIGINALPOS=%d",
  6198. (long) (time(NULL) - qe->start), qe->opos);
  6199. pbx_builtin_setvar_multiple(qe->chan, ast_str_buffer(interfacevar));
  6200. pbx_builtin_setvar_multiple(peer, ast_str_buffer(interfacevar));
  6201. }
  6202. ao2_unlock(qe->parent);
  6203. /* try to set queue variables if configured to do so*/
  6204. set_queue_variables(qe->parent, qe->chan);
  6205. set_queue_variables(qe->parent, peer);
  6206. setup_peer_after_bridge_goto(qe->chan, peer, &opts, opt_args);
  6207. ast_channel_lock(qe->chan);
  6208. if ((monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME"))) {
  6209. monitorfilename = ast_strdupa(monitorfilename);
  6210. }
  6211. ast_channel_unlock(qe->chan);
  6212. /* Begin Monitoring */
  6213. if (*qe->parent->monfmt) {
  6214. if (!qe->parent->montype) {
  6215. const char *monexec;
  6216. ast_debug(1, "Starting Monitor as requested.\n");
  6217. ast_channel_lock(qe->chan);
  6218. if ((monexec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC")) || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS")) {
  6219. which = qe->chan;
  6220. monexec = monexec ? ast_strdupa(monexec) : NULL;
  6221. } else {
  6222. which = peer;
  6223. }
  6224. ast_channel_unlock(qe->chan);
  6225. if (monitorfilename) {
  6226. ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT, NULL);
  6227. } else if (qe->chan) {
  6228. ast_monitor_start(which, qe->parent->monfmt, ast_channel_uniqueid(qe->chan), 1, X_REC_IN | X_REC_OUT, NULL);
  6229. } else {
  6230. /* Last ditch effort -- no channel, make up something */
  6231. snprintf(tmpid, sizeof(tmpid), "chan-%lx", (unsigned long)ast_random());
  6232. ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT, NULL);
  6233. }
  6234. if (!ast_strlen_zero(monexec)) {
  6235. ast_monitor_setjoinfiles(which, 1);
  6236. }
  6237. } else {
  6238. setup_mixmonitor(qe, monitorfilename);
  6239. }
  6240. }
  6241. /* Drop out of the queue at this point, to prepare for next caller */
  6242. leave_queue(qe);
  6243. if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
  6244. ast_debug(1, "app_queue: sendurl=%s.\n", url);
  6245. ast_channel_sendurl(peer, url);
  6246. }
  6247. /* run a macro for this connection if defined. The macro simply returns, no action is taken on the result */
  6248. /* use macro from dialplan if passed as a option, otherwise use the default queue macro */
  6249. if (!ast_strlen_zero(macro)) {
  6250. macroexec = ast_strdupa(macro);
  6251. } else {
  6252. if (qe->parent->membermacro) {
  6253. macroexec = ast_strdupa(qe->parent->membermacro);
  6254. }
  6255. }
  6256. if (!ast_strlen_zero(macroexec)) {
  6257. ast_debug(1, "app_queue: macro=%s.\n", macroexec);
  6258. ast_app_exec_macro(qe->chan, peer, macroexec);
  6259. }
  6260. /* run a gosub for this connection if defined. The gosub simply returns, no action is taken on the result */
  6261. /* use gosub from dialplan if passed as a option, otherwise use the default queue gosub */
  6262. if (!ast_strlen_zero(gosub)) {
  6263. gosubexec = ast_strdupa(gosub);
  6264. } else {
  6265. if (qe->parent->membergosub) {
  6266. gosubexec = ast_strdupa(qe->parent->membergosub);
  6267. }
  6268. }
  6269. if (!ast_strlen_zero(gosubexec)) {
  6270. char *gosub_args = NULL;
  6271. char *gosub_argstart;
  6272. ast_debug(1, "app_queue: gosub=%s.\n", gosubexec);
  6273. gosub_argstart = strchr(gosubexec, ',');
  6274. if (gosub_argstart) {
  6275. const char *what_is_s = "s";
  6276. *gosub_argstart = 0;
  6277. if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
  6278. ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
  6279. what_is_s = "~~s~~";
  6280. }
  6281. if (ast_asprintf(&gosub_args, "%s,%s,1(%s)", gosubexec, what_is_s, gosub_argstart + 1) < 0) {
  6282. gosub_args = NULL;
  6283. }
  6284. *gosub_argstart = ',';
  6285. } else {
  6286. const char *what_is_s = "s";
  6287. if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
  6288. ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
  6289. what_is_s = "~~s~~";
  6290. }
  6291. if (ast_asprintf(&gosub_args, "%s,%s,1", gosubexec, what_is_s) < 0) {
  6292. gosub_args = NULL;
  6293. }
  6294. }
  6295. if (gosub_args) {
  6296. ast_app_exec_sub(qe->chan, peer, gosub_args, 0);
  6297. ast_free(gosub_args);
  6298. } else {
  6299. ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
  6300. }
  6301. }
  6302. if (!ast_strlen_zero(agi)) {
  6303. ast_debug(1, "app_queue: agi=%s.\n", agi);
  6304. application = pbx_findapp("agi");
  6305. if (application) {
  6306. agiexec = ast_strdupa(agi);
  6307. pbx_exec(qe->chan, application, agiexec);
  6308. } else {
  6309. ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
  6310. }
  6311. }
  6312. qe->handled++;
  6313. ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) (time(NULL) - qe->start), ast_channel_uniqueid(peer),
  6314. (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
  6315. blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i}",
  6316. "Queue", queuename,
  6317. "Interface", member->interface,
  6318. "MemberName", member->membername,
  6319. "HoldTime", (long) (time(NULL) - qe->start),
  6320. "RingTime", (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
  6321. queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_connect_type(), blob);
  6322. ast_copy_string(oldcontext, ast_channel_context(qe->chan), sizeof(oldcontext));
  6323. ast_copy_string(oldexten, ast_channel_exten(qe->chan), sizeof(oldexten));
  6324. if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
  6325. queue_end_bridge->q = qe->parent;
  6326. queue_end_bridge->chan = qe->chan;
  6327. bridge_config.end_bridge_callback = end_bridge_callback;
  6328. bridge_config.end_bridge_callback_data = queue_end_bridge;
  6329. bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
  6330. /* Since queue_end_bridge can survive beyond the life of this call to Queue, we need
  6331. * to make sure to increase the refcount of this queue so it cannot be freed until we
  6332. * are done with it. We remove this reference in end_bridge_callback.
  6333. */
  6334. queue_t_ref(qe->parent, "For bridge_config reference");
  6335. }
  6336. ao2_lock(qe->parent);
  6337. time(&member->starttime);
  6338. starttime = member->starttime;
  6339. ao2_unlock(qe->parent);
  6340. /* As a queue member may end up in multiple calls at once if a transfer occurs with
  6341. * a Local channel in the mix we pass the current call information (starttime) to the
  6342. * Stasis subscriptions so when they update the queue member data it becomes a noop
  6343. * if this call is no longer between the caller and the queue member.
  6344. */
  6345. setup_stasis_subs(qe, peer, member, qe->start, starttime, callcompletedinsl);
  6346. bridge = ast_bridge_call_with_flags(qe->chan, peer, &bridge_config,
  6347. AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM | AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM);
  6348. res = bridge ? bridge : 1;
  6349. ao2_ref(member, -1);
  6350. }
  6351. out:
  6352. hangupcalls(qe, outgoing, NULL, qe->cancel_answered_elsewhere);
  6353. return res;
  6354. }
  6355. static int wait_a_bit(struct queue_ent *qe)
  6356. {
  6357. /* Don't need to hold the lock while we setup the outgoing calls */
  6358. int retrywait = qe->parent->retry * 1000;
  6359. int res = ast_waitfordigit(qe->chan, retrywait);
  6360. if (res > 0 && !valid_exit(qe, res)) {
  6361. res = 0;
  6362. }
  6363. return res;
  6364. }
  6365. static struct member *interface_exists(struct call_queue *q, const char *interface)
  6366. {
  6367. struct member *mem;
  6368. struct ao2_iterator mem_iter;
  6369. if (!q) {
  6370. return NULL;
  6371. }
  6372. mem_iter = ao2_iterator_init(q->members, 0);
  6373. while ((mem = ao2_iterator_next(&mem_iter))) {
  6374. if (!strcasecmp(interface, mem->interface)) {
  6375. ao2_iterator_destroy(&mem_iter);
  6376. return mem;
  6377. }
  6378. ao2_ref(mem, -1);
  6379. }
  6380. ao2_iterator_destroy(&mem_iter);
  6381. return NULL;
  6382. }
  6383. /*! \brief Dump all members in a specific queue to the database
  6384. * \code
  6385. * <pm_family>/<queuename> = <interface>;<penalty>;<paused>;<state_interface>[|...]
  6386. * \endcode
  6387. */
  6388. static void dump_queue_members(struct call_queue *pm_queue)
  6389. {
  6390. struct member *cur_member;
  6391. struct ast_str *value;
  6392. struct ao2_iterator mem_iter;
  6393. if (!pm_queue) {
  6394. return;
  6395. }
  6396. /* 4K is a reasonable default for most applications, but we grow to
  6397. * accommodate more if necessary. */
  6398. if (!(value = ast_str_create(4096))) {
  6399. return;
  6400. }
  6401. mem_iter = ao2_iterator_init(pm_queue->members, 0);
  6402. while ((cur_member = ao2_iterator_next(&mem_iter))) {
  6403. if (!cur_member->dynamic) {
  6404. ao2_ref(cur_member, -1);
  6405. continue;
  6406. }
  6407. ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s",
  6408. ast_str_strlen(value) ? "|" : "",
  6409. cur_member->interface,
  6410. cur_member->penalty,
  6411. cur_member->paused,
  6412. cur_member->membername,
  6413. cur_member->state_interface);
  6414. ao2_ref(cur_member, -1);
  6415. }
  6416. ao2_iterator_destroy(&mem_iter);
  6417. if (ast_str_strlen(value) && !cur_member) {
  6418. if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value))) {
  6419. ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
  6420. }
  6421. } else {
  6422. /* Delete the entry if the queue is empty or there is an error */
  6423. ast_db_del(pm_family, pm_queue->name);
  6424. }
  6425. ast_free(value);
  6426. }
  6427. /*! \brief Remove member from queue
  6428. * \retval RES_NOT_DYNAMIC when they aren't a RT member
  6429. * \retval RES_NOSUCHQUEUE queue does not exist
  6430. * \retval RES_OKAY removed member from queue
  6431. * \retval RES_EXISTS queue exists but no members
  6432. */
  6433. static int remove_from_queue(const char *queuename, const char *interface)
  6434. {
  6435. struct call_queue *q, tmpq = {
  6436. .name = queuename,
  6437. };
  6438. struct member *mem, tmpmem;
  6439. int res = RES_NOSUCHQUEUE;
  6440. ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
  6441. if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) {
  6442. ao2_lock(q);
  6443. if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
  6444. /* XXX future changes should beware of this assumption!! */
  6445. /*Change Penalty on realtime users*/
  6446. if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid) && negative_penalty_invalid) {
  6447. update_realtime_member_field(mem, q->name, "penalty", "-1");
  6448. } else if (!mem->dynamic) {
  6449. ao2_ref(mem, -1);
  6450. ao2_unlock(q);
  6451. queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
  6452. return RES_NOT_DYNAMIC;
  6453. }
  6454. queue_publish_member_blob(queue_member_removed_type(), queue_member_blob_create(q, mem));
  6455. member_remove_from_queue(q, mem);
  6456. ao2_ref(mem, -1);
  6457. if (queue_persistent_members) {
  6458. dump_queue_members(q);
  6459. }
  6460. if (!num_available_members(q)) {
  6461. ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
  6462. }
  6463. res = RES_OKAY;
  6464. } else {
  6465. res = RES_EXISTS;
  6466. }
  6467. ao2_unlock(q);
  6468. queue_t_unref(q, "Expiring temporary reference");
  6469. }
  6470. return res;
  6471. }
  6472. /*! \brief Add member to queue
  6473. * \retval RES_NOT_DYNAMIC when they aren't a RT member
  6474. * \retval RES_NOSUCHQUEUE queue does not exist
  6475. * \retval RES_OKAY added member from queue
  6476. * \retval RES_EXISTS queue exists but no members
  6477. * \retval RES_OUT_OF_MEMORY queue exists but not enough memory to create member
  6478. */
  6479. static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
  6480. {
  6481. struct call_queue *q;
  6482. struct member *new_member, *old_member;
  6483. int res = RES_NOSUCHQUEUE;
  6484. /*! \note Ensure the appropriate realtime queue is loaded. Note that this
  6485. * short-circuits if the queue is already in memory. */
  6486. if (!(q = find_load_queue_rt_friendly(queuename))) {
  6487. return res;
  6488. }
  6489. ao2_lock(q);
  6490. if ((old_member = interface_exists(q, interface)) == NULL) {
  6491. if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface, q->ringinuse))) {
  6492. new_member->ringinuse = q->ringinuse;
  6493. new_member->dynamic = 1;
  6494. member_add_to_queue(q, new_member);
  6495. queue_publish_member_blob(queue_member_added_type(), queue_member_blob_create(q, new_member));
  6496. if (is_member_available(q, new_member)) {
  6497. ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
  6498. }
  6499. ao2_ref(new_member, -1);
  6500. new_member = NULL;
  6501. if (dump) {
  6502. dump_queue_members(q);
  6503. }
  6504. res = RES_OKAY;
  6505. } else {
  6506. res = RES_OUTOFMEMORY;
  6507. }
  6508. } else {
  6509. ao2_ref(old_member, -1);
  6510. res = RES_EXISTS;
  6511. }
  6512. ao2_unlock(q);
  6513. queue_t_unref(q, "Expiring temporary reference");
  6514. return res;
  6515. }
  6516. static int publish_queue_member_pause(struct call_queue *q, struct member *member, const char *reason)
  6517. {
  6518. struct ast_json *json_blob = queue_member_blob_create(q, member);
  6519. if (!json_blob) {
  6520. return -1;
  6521. }
  6522. if (!ast_strlen_zero(reason)) {
  6523. ast_json_object_set(json_blob, "Reason", ast_json_string_create(reason));
  6524. }
  6525. queue_publish_member_blob(queue_member_pause_type(), json_blob);
  6526. return 0;
  6527. }
  6528. /*!
  6529. * \internal
  6530. * \brief Set the pause status of the specific queue member.
  6531. *
  6532. * \param q Which queue the member belongs.
  6533. * \param mem Queue member being paused/unpaused.
  6534. * \param reason Why is this happening (Can be NULL/empty for no reason given.)
  6535. * \param paused Set to 1 if the member is being paused or 0 to unpause.
  6536. *
  6537. * \pre The q is locked on entry.
  6538. *
  6539. * \return Nothing
  6540. */
  6541. static void set_queue_member_pause(struct call_queue *q, struct member *mem, const char *reason, int paused)
  6542. {
  6543. if (mem->paused == paused) {
  6544. ast_debug(1, "%spausing already-%spaused queue member %s:%s\n",
  6545. (paused ? "" : "un"), (paused ? "" : "un"), q->name, mem->interface);
  6546. }
  6547. if (mem->realtime) {
  6548. if (update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0")) {
  6549. ast_log(LOG_WARNING, "Failed %spause update of realtime queue member %s:%s\n",
  6550. (paused ? "" : "un"), q->name, mem->interface);
  6551. }
  6552. }
  6553. mem->paused = paused;
  6554. if (paused && !ast_strlen_zero(reason)) {
  6555. ast_copy_string(mem->reason_paused, reason, sizeof(mem->reason_paused));
  6556. } else {
  6557. mem->reason_paused[0] = '\0';
  6558. }
  6559. ast_devstate_changed(mem->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
  6560. AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", q->name, mem->interface);
  6561. if (queue_persistent_members) {
  6562. dump_queue_members(q);
  6563. }
  6564. if (is_member_available(q, mem)) {
  6565. ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE,
  6566. "Queue:%s_avail", q->name);
  6567. } else if (!num_available_members(q)) {
  6568. ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE,
  6569. "Queue:%s_avail", q->name);
  6570. }
  6571. ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"),
  6572. "%s", S_OR(reason, ""));
  6573. publish_queue_member_pause(q, mem, reason);
  6574. }
  6575. static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
  6576. {
  6577. int found = 0;
  6578. struct call_queue *q;
  6579. struct ao2_iterator queue_iter;
  6580. queue_iter = ao2_iterator_init(queues, 0);
  6581. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
  6582. ao2_lock(q);
  6583. if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
  6584. struct member *mem;
  6585. if ((mem = interface_exists(q, interface))) {
  6586. /*
  6587. * Before we do the PAUSE/UNPAUSE, log if this was a
  6588. * PAUSEALL/UNPAUSEALL but only on the first found entry.
  6589. */
  6590. ++found;
  6591. if (found == 1
  6592. && ast_strlen_zero(queuename)) {
  6593. /*
  6594. * XXX In all other cases, we use the queue name,
  6595. * but since this affects all queues, we cannot.
  6596. */
  6597. ast_queue_log("NONE", "NONE", mem->membername,
  6598. (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
  6599. }
  6600. set_queue_member_pause(q, mem, reason, paused);
  6601. ao2_ref(mem, -1);
  6602. }
  6603. if (!ast_strlen_zero(queuename)) {
  6604. ao2_unlock(q);
  6605. queue_t_unref(q, "Done with iterator");
  6606. break;
  6607. }
  6608. }
  6609. ao2_unlock(q);
  6610. queue_t_unref(q, "Done with iterator");
  6611. }
  6612. ao2_iterator_destroy(&queue_iter);
  6613. return found ? RESULT_SUCCESS : RESULT_FAILURE;
  6614. }
  6615. /*!
  6616. * \internal
  6617. * \brief helper function for set_member_penalty - given a queue, sets all member penalties with the interface
  6618. * \param[in] q queue which is having its member's penalty changed - must be unlocked prior to calling
  6619. * \param[in] interface String of interface used to search for queue members being changed
  6620. * \param[in] penalty Value penalty is being changed to for the member.
  6621. * \retval 0 if the there is no member with interface belonging to q and no change is made
  6622. * \retval 1 if the there is a member with interface belonging to q and changes are made
  6623. */
  6624. static int set_member_penalty_help_members(struct call_queue *q, const char *interface, int penalty)
  6625. {
  6626. struct member *mem;
  6627. int foundinterface = 0;
  6628. ao2_lock(q);
  6629. if ((mem = interface_exists(q, interface))) {
  6630. foundinterface++;
  6631. if (mem->realtime) {
  6632. char rtpenalty[80];
  6633. sprintf(rtpenalty, "%i", penalty);
  6634. update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
  6635. }
  6636. mem->penalty = penalty;
  6637. ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
  6638. queue_publish_member_blob(queue_member_penalty_type(), queue_member_blob_create(q, mem));
  6639. ao2_ref(mem, -1);
  6640. }
  6641. ao2_unlock(q);
  6642. return foundinterface;
  6643. }
  6644. /*!
  6645. * \internal
  6646. * \brief Set the ringinuse value of the specific queue member.
  6647. *
  6648. * \param q Which queue the member belongs.
  6649. * \param mem Queue member being set.
  6650. * \param ringinuse Set to 1 if the member is called when inuse.
  6651. *
  6652. * \pre The q is locked on entry.
  6653. *
  6654. * \return Nothing
  6655. */
  6656. static void set_queue_member_ringinuse(struct call_queue *q, struct member *mem, int ringinuse)
  6657. {
  6658. if (mem->realtime) {
  6659. update_realtime_member_field(mem, q->name, realtime_ringinuse_field,
  6660. ringinuse ? "1" : "0");
  6661. }
  6662. mem->ringinuse = ringinuse;
  6663. ast_queue_log(q->name, "NONE", mem->interface, "RINGINUSE", "%d", ringinuse);
  6664. queue_publish_member_blob(queue_member_ringinuse_type(), queue_member_blob_create(q, mem));
  6665. }
  6666. static int set_member_ringinuse_help_members(struct call_queue *q, const char *interface, int ringinuse)
  6667. {
  6668. struct member *mem;
  6669. int foundinterface = 0;
  6670. ao2_lock(q);
  6671. if ((mem = interface_exists(q, interface))) {
  6672. foundinterface++;
  6673. set_queue_member_ringinuse(q, mem, ringinuse);
  6674. ao2_ref(mem, -1);
  6675. }
  6676. ao2_unlock(q);
  6677. return foundinterface;
  6678. }
  6679. static int set_member_value_help_members(struct call_queue *q, const char *interface, int property, int value)
  6680. {
  6681. switch(property) {
  6682. case MEMBER_PENALTY:
  6683. return set_member_penalty_help_members(q, interface, value);
  6684. case MEMBER_RINGINUSE:
  6685. return set_member_ringinuse_help_members(q, interface, value);
  6686. default:
  6687. ast_log(LOG_ERROR, "Attempted to set invalid property\n");
  6688. return 0;
  6689. }
  6690. }
  6691. /*!
  6692. * \internal
  6693. * \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues.
  6694. * \param[in] queuename If specified, only act on a member if it belongs to this queue
  6695. * \param[in] interface Interface of queue member(s) having priority set.
  6696. * \param[in] property Which queue property is being set
  6697. * \param[in] penalty Value penalty is being changed to for each member
  6698. */
  6699. static int set_member_value(const char *queuename, const char *interface, int property, int value)
  6700. {
  6701. int foundinterface = 0, foundqueue = 0;
  6702. struct call_queue *q;
  6703. struct ast_config *queue_config = NULL;
  6704. struct ao2_iterator queue_iter;
  6705. /* property dependent restrictions on values should be checked in this switch */
  6706. switch (property) {
  6707. case MEMBER_PENALTY:
  6708. if (value < 0 && !negative_penalty_invalid) {
  6709. ast_log(LOG_ERROR, "Invalid penalty (%d)\n", value);
  6710. return RESULT_FAILURE;
  6711. }
  6712. }
  6713. if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */
  6714. if (ast_check_realtime("queues")) {
  6715. queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
  6716. if (queue_config) {
  6717. char *category = NULL;
  6718. while ((category = ast_category_browse(queue_config, category))) {
  6719. const char *name = ast_variable_retrieve(queue_config, category, "name");
  6720. if ((q = find_load_queue_rt_friendly(name))) {
  6721. foundqueue++;
  6722. foundinterface += set_member_value_help_members(q, interface, property, value);
  6723. queue_unref(q);
  6724. }
  6725. }
  6726. }
  6727. }
  6728. /* After hitting realtime queues, go back and get the regular ones. */
  6729. queue_iter = ao2_iterator_init(queues, 0);
  6730. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  6731. foundqueue++;
  6732. foundinterface += set_member_value_help_members(q, interface, property, value);
  6733. queue_unref(q);
  6734. }
  6735. ao2_iterator_destroy(&queue_iter);
  6736. } else { /* We actually have a queuename, so we can just act on the single queue. */
  6737. if ((q = find_load_queue_rt_friendly(queuename))) {
  6738. foundqueue++;
  6739. foundinterface += set_member_value_help_members(q, interface, property, value);
  6740. queue_unref(q);
  6741. }
  6742. }
  6743. if (foundinterface) {
  6744. return RESULT_SUCCESS;
  6745. } else if (!foundqueue) {
  6746. ast_log (LOG_ERROR, "Invalid queuename\n");
  6747. } else {
  6748. ast_log (LOG_ERROR, "Invalid interface\n");
  6749. }
  6750. return RESULT_FAILURE;
  6751. }
  6752. /* \brief Gets members penalty.
  6753. * \return Return the members penalty or RESULT_FAILURE on error.
  6754. */
  6755. static int get_member_penalty(char *queuename, char *interface)
  6756. {
  6757. int foundqueue = 0, penalty;
  6758. struct call_queue *q;
  6759. struct member *mem;
  6760. if ((q = find_load_queue_rt_friendly(queuename))) {
  6761. foundqueue = 1;
  6762. ao2_lock(q);
  6763. if ((mem = interface_exists(q, interface))) {
  6764. penalty = mem->penalty;
  6765. ao2_ref(mem, -1);
  6766. ao2_unlock(q);
  6767. queue_t_unref(q, "Search complete");
  6768. return penalty;
  6769. }
  6770. ao2_unlock(q);
  6771. queue_t_unref(q, "Search complete");
  6772. }
  6773. /* some useful debuging */
  6774. if (foundqueue) {
  6775. ast_log (LOG_ERROR, "Invalid queuename\n");
  6776. } else {
  6777. ast_log (LOG_ERROR, "Invalid interface\n");
  6778. }
  6779. return RESULT_FAILURE;
  6780. }
  6781. /*! \brief Reload dynamic queue members persisted into the astdb */
  6782. static void reload_queue_members(void)
  6783. {
  6784. char *cur_ptr;
  6785. const char *queue_name;
  6786. char *member;
  6787. char *interface;
  6788. char *membername = NULL;
  6789. char *state_interface;
  6790. char *penalty_tok;
  6791. int penalty = 0;
  6792. char *paused_tok;
  6793. int paused = 0;
  6794. struct ast_db_entry *db_tree;
  6795. struct ast_db_entry *entry;
  6796. struct call_queue *cur_queue;
  6797. char *queue_data;
  6798. /* Each key in 'pm_family' is the name of a queue */
  6799. db_tree = ast_db_gettree(pm_family, NULL);
  6800. for (entry = db_tree; entry; entry = entry->next) {
  6801. queue_name = entry->key + strlen(pm_family) + 2;
  6802. {
  6803. struct call_queue tmpq = {
  6804. .name = queue_name,
  6805. };
  6806. cur_queue = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Reload queue members");
  6807. }
  6808. if (!cur_queue) {
  6809. cur_queue = find_load_queue_rt_friendly(queue_name);
  6810. }
  6811. if (!cur_queue) {
  6812. /* If the queue no longer exists, remove it from the
  6813. * database */
  6814. ast_log(LOG_WARNING, "Error loading persistent queue: '%s': it does not exist\n", queue_name);
  6815. ast_db_del(pm_family, queue_name);
  6816. continue;
  6817. }
  6818. if (ast_db_get_allocated(pm_family, queue_name, &queue_data)) {
  6819. queue_t_unref(cur_queue, "Expire reload reference");
  6820. continue;
  6821. }
  6822. cur_ptr = queue_data;
  6823. while ((member = strsep(&cur_ptr, ",|"))) {
  6824. if (ast_strlen_zero(member)) {
  6825. continue;
  6826. }
  6827. interface = strsep(&member, ";");
  6828. penalty_tok = strsep(&member, ";");
  6829. paused_tok = strsep(&member, ";");
  6830. membername = strsep(&member, ";");
  6831. state_interface = strsep(&member, ";");
  6832. if (!penalty_tok) {
  6833. ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
  6834. break;
  6835. }
  6836. penalty = strtol(penalty_tok, NULL, 10);
  6837. if (errno == ERANGE) {
  6838. ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
  6839. break;
  6840. }
  6841. if (!paused_tok) {
  6842. ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
  6843. break;
  6844. }
  6845. paused = strtol(paused_tok, NULL, 10);
  6846. if ((errno == ERANGE) || paused < 0 || paused > 1) {
  6847. ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
  6848. break;
  6849. }
  6850. ast_debug(1, "Reload Members: Queue: %s Member: %s Name: %s Penalty: %d Paused: %d\n", queue_name, interface, membername, penalty, paused);
  6851. if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface) == RES_OUTOFMEMORY) {
  6852. ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
  6853. break;
  6854. }
  6855. }
  6856. queue_t_unref(cur_queue, "Expire reload reference");
  6857. ast_free(queue_data);
  6858. }
  6859. if (db_tree) {
  6860. ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
  6861. ast_db_freetree(db_tree);
  6862. }
  6863. }
  6864. /*! \brief PauseQueueMember application */
  6865. static int pqm_exec(struct ast_channel *chan, const char *data)
  6866. {
  6867. char *parse;
  6868. AST_DECLARE_APP_ARGS(args,
  6869. AST_APP_ARG(queuename);
  6870. AST_APP_ARG(interface);
  6871. AST_APP_ARG(options);
  6872. AST_APP_ARG(reason);
  6873. );
  6874. if (ast_strlen_zero(data)) {
  6875. ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename],interface[,options][,reason])\n");
  6876. return -1;
  6877. }
  6878. parse = ast_strdupa(data);
  6879. AST_STANDARD_APP_ARGS(args, parse);
  6880. if (ast_strlen_zero(args.interface)) {
  6881. ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
  6882. return -1;
  6883. }
  6884. if (set_member_paused(args.queuename, args.interface, args.reason, 1)) {
  6885. ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface);
  6886. pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
  6887. return 0;
  6888. }
  6889. pbx_builtin_setvar_helper(chan, "PQMSTATUS", "PAUSED");
  6890. return 0;
  6891. }
  6892. /*! \brief UnPauseQueueMember application */
  6893. static int upqm_exec(struct ast_channel *chan, const char *data)
  6894. {
  6895. char *parse;
  6896. AST_DECLARE_APP_ARGS(args,
  6897. AST_APP_ARG(queuename);
  6898. AST_APP_ARG(interface);
  6899. AST_APP_ARG(options);
  6900. AST_APP_ARG(reason);
  6901. );
  6902. if (ast_strlen_zero(data)) {
  6903. ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename],interface[,options[,reason]])\n");
  6904. return -1;
  6905. }
  6906. parse = ast_strdupa(data);
  6907. AST_STANDARD_APP_ARGS(args, parse);
  6908. if (ast_strlen_zero(args.interface)) {
  6909. ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
  6910. return -1;
  6911. }
  6912. if (set_member_paused(args.queuename, args.interface, args.reason, 0)) {
  6913. ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface);
  6914. pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
  6915. return 0;
  6916. }
  6917. pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "UNPAUSED");
  6918. return 0;
  6919. }
  6920. /*! \brief RemoveQueueMember application */
  6921. static int rqm_exec(struct ast_channel *chan, const char *data)
  6922. {
  6923. int res=-1;
  6924. char *parse, *temppos = NULL;
  6925. struct member *mem = NULL;
  6926. AST_DECLARE_APP_ARGS(args,
  6927. AST_APP_ARG(queuename);
  6928. AST_APP_ARG(interface);
  6929. );
  6930. if (ast_strlen_zero(data)) {
  6931. ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[,interface])\n");
  6932. return -1;
  6933. }
  6934. parse = ast_strdupa(data);
  6935. AST_STANDARD_APP_ARGS(args, parse);
  6936. if (ast_strlen_zero(args.interface)) {
  6937. args.interface = ast_strdupa(ast_channel_name(chan));
  6938. temppos = strrchr(args.interface, '-');
  6939. if (temppos) {
  6940. *temppos = '\0';
  6941. }
  6942. }
  6943. ast_debug(1, "queue: %s, member: %s\n", args.queuename, args.interface);
  6944. if (log_membername_as_agent) {
  6945. mem = find_member_by_queuename_and_interface(args.queuename, args.interface);
  6946. }
  6947. switch (remove_from_queue(args.queuename, args.interface)) {
  6948. case RES_OKAY:
  6949. if (!mem || ast_strlen_zero(mem->membername)) {
  6950. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "REMOVEMEMBER", "%s", "");
  6951. } else {
  6952. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), mem->membername, "REMOVEMEMBER", "%s", "");
  6953. }
  6954. ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename);
  6955. pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED");
  6956. res = 0;
  6957. break;
  6958. case RES_EXISTS:
  6959. ast_debug(1, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename);
  6960. pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE");
  6961. res = 0;
  6962. break;
  6963. case RES_NOSUCHQUEUE:
  6964. ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", args.queuename);
  6965. pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOSUCHQUEUE");
  6966. res = 0;
  6967. break;
  6968. case RES_NOT_DYNAMIC:
  6969. ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': '%s' is not a dynamic member\n", args.queuename, args.interface);
  6970. pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTDYNAMIC");
  6971. res = 0;
  6972. break;
  6973. }
  6974. if (mem) {
  6975. ao2_ref(mem, -1);
  6976. }
  6977. return res;
  6978. }
  6979. /*! \brief AddQueueMember application */
  6980. static int aqm_exec(struct ast_channel *chan, const char *data)
  6981. {
  6982. int res=-1;
  6983. char *parse, *temppos = NULL;
  6984. AST_DECLARE_APP_ARGS(args,
  6985. AST_APP_ARG(queuename);
  6986. AST_APP_ARG(interface);
  6987. AST_APP_ARG(penalty);
  6988. AST_APP_ARG(options);
  6989. AST_APP_ARG(membername);
  6990. AST_APP_ARG(state_interface);
  6991. );
  6992. int penalty = 0;
  6993. if (ast_strlen_zero(data)) {
  6994. ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface]]]]])\n");
  6995. return -1;
  6996. }
  6997. parse = ast_strdupa(data);
  6998. AST_STANDARD_APP_ARGS(args, parse);
  6999. if (ast_strlen_zero(args.interface)) {
  7000. args.interface = ast_strdupa(ast_channel_name(chan));
  7001. temppos = strrchr(args.interface, '-');
  7002. if (temppos) {
  7003. *temppos = '\0';
  7004. }
  7005. }
  7006. if (!ast_strlen_zero(args.penalty)) {
  7007. if ((sscanf(args.penalty, "%30d", &penalty) != 1) || penalty < 0) {
  7008. ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
  7009. penalty = 0;
  7010. }
  7011. }
  7012. switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface)) {
  7013. case RES_OKAY:
  7014. if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
  7015. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "ADDMEMBER", "%s", "");
  7016. } else {
  7017. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.membername, "ADDMEMBER", "%s", "");
  7018. }
  7019. ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
  7020. pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
  7021. res = 0;
  7022. break;
  7023. case RES_EXISTS:
  7024. ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
  7025. pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
  7026. res = 0;
  7027. break;
  7028. case RES_NOSUCHQUEUE:
  7029. ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
  7030. pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
  7031. res = 0;
  7032. break;
  7033. case RES_OUTOFMEMORY:
  7034. ast_log(LOG_ERROR, "Out of memory adding interface %s to queue %s\n", args.interface, args.queuename);
  7035. break;
  7036. }
  7037. return res;
  7038. }
  7039. /*! \brief QueueLog application */
  7040. static int ql_exec(struct ast_channel *chan, const char *data)
  7041. {
  7042. char *parse;
  7043. AST_DECLARE_APP_ARGS(args,
  7044. AST_APP_ARG(queuename);
  7045. AST_APP_ARG(uniqueid);
  7046. AST_APP_ARG(membername);
  7047. AST_APP_ARG(event);
  7048. AST_APP_ARG(params);
  7049. );
  7050. if (ast_strlen_zero(data)) {
  7051. ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo]\n");
  7052. return -1;
  7053. }
  7054. parse = ast_strdupa(data);
  7055. AST_STANDARD_APP_ARGS(args, parse);
  7056. if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.uniqueid)
  7057. || ast_strlen_zero(args.membername) || ast_strlen_zero(args.event)) {
  7058. ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo])\n");
  7059. return -1;
  7060. }
  7061. ast_queue_log(args.queuename, args.uniqueid, args.membername, args.event,
  7062. "%s", args.params ? args.params : "");
  7063. return 0;
  7064. }
  7065. /*! \brief Copy rule from global list into specified queue */
  7066. static void copy_rules(struct queue_ent *qe, const char *rulename)
  7067. {
  7068. struct penalty_rule *pr_iter;
  7069. struct rule_list *rl_iter;
  7070. const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
  7071. AST_LIST_LOCK(&rule_lists);
  7072. AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
  7073. if (!strcasecmp(rl_iter->name, tmp)) {
  7074. break;
  7075. }
  7076. }
  7077. if (rl_iter) {
  7078. AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
  7079. struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
  7080. if (!new_pr) {
  7081. ast_log(LOG_ERROR, "Memory allocation error when copying penalty rules! Aborting!\n");
  7082. break;
  7083. }
  7084. new_pr->time = pr_iter->time;
  7085. new_pr->max_value = pr_iter->max_value;
  7086. new_pr->min_value = pr_iter->min_value;
  7087. new_pr->max_relative = pr_iter->max_relative;
  7088. new_pr->min_relative = pr_iter->min_relative;
  7089. AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
  7090. }
  7091. }
  7092. AST_LIST_UNLOCK(&rule_lists);
  7093. }
  7094. /*!\brief The starting point for all queue calls
  7095. *
  7096. * The process involved here is to
  7097. * 1. Parse the options specified in the call to Queue()
  7098. * 2. Join the queue
  7099. * 3. Wait in a loop until it is our turn to try calling a queue member
  7100. * 4. Attempt to call a queue member
  7101. * 5. If 4. did not result in a bridged call, then check for between
  7102. * call options such as periodic announcements etc.
  7103. * 6. Try 4 again unless some condition (such as an expiration time) causes us to
  7104. * exit the queue.
  7105. */
  7106. static int queue_exec(struct ast_channel *chan, const char *data)
  7107. {
  7108. int res=-1;
  7109. int ringing=0;
  7110. const char *user_priority;
  7111. const char *max_penalty_str;
  7112. const char *min_penalty_str;
  7113. int prio;
  7114. int qcontinue = 0;
  7115. int max_penalty, min_penalty;
  7116. enum queue_result reason = QUEUE_UNKNOWN;
  7117. /* whether to exit Queue application after the timeout hits */
  7118. int tries = 0;
  7119. int noption = 0;
  7120. char *parse;
  7121. int makeannouncement = 0;
  7122. int position = 0;
  7123. AST_DECLARE_APP_ARGS(args,
  7124. AST_APP_ARG(queuename);
  7125. AST_APP_ARG(options);
  7126. AST_APP_ARG(url);
  7127. AST_APP_ARG(announceoverride);
  7128. AST_APP_ARG(queuetimeoutstr);
  7129. AST_APP_ARG(agi);
  7130. AST_APP_ARG(macro);
  7131. AST_APP_ARG(gosub);
  7132. AST_APP_ARG(rule);
  7133. AST_APP_ARG(position);
  7134. );
  7135. /* Our queue entry */
  7136. struct queue_ent qe = { 0 };
  7137. struct ast_flags opts = { 0, };
  7138. char *opt_args[OPT_ARG_ARRAY_SIZE];
  7139. int max_forwards;
  7140. if (ast_strlen_zero(data)) {
  7141. ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule[,position]]]]]]]]]\n");
  7142. return -1;
  7143. }
  7144. ast_channel_lock(chan);
  7145. max_forwards = ast_max_forwards_get(chan);
  7146. ast_channel_unlock(chan);
  7147. if (max_forwards <= 0) {
  7148. ast_log(LOG_WARNING, "Channel '%s' cannot enter queue. Max forwards exceeded\n", ast_channel_name(chan));
  7149. return -1;
  7150. }
  7151. parse = ast_strdupa(data);
  7152. AST_STANDARD_APP_ARGS(args, parse);
  7153. ast_debug(1, "queue: %s, options: %s, url: %s, announce: %s, timeout: %s, agi: %s, macro: %s, gosub: %s, rule: %s, position: %s\n",
  7154. args.queuename,
  7155. S_OR(args.options, ""),
  7156. S_OR(args.url, ""),
  7157. S_OR(args.announceoverride, ""),
  7158. S_OR(args.queuetimeoutstr, ""),
  7159. S_OR(args.agi, ""),
  7160. S_OR(args.macro, ""),
  7161. S_OR(args.gosub, ""),
  7162. S_OR(args.rule, ""),
  7163. S_OR(args.position, ""));
  7164. if (!ast_strlen_zero(args.options)) {
  7165. ast_app_parse_options(queue_exec_options, &opts, opt_args, args.options);
  7166. }
  7167. /* Setup our queue entry */
  7168. qe.start = time(NULL);
  7169. pbx_builtin_setvar_helper(chan, "ABANDONED", NULL);
  7170. /* set the expire time based on the supplied timeout; */
  7171. if (!ast_strlen_zero(args.queuetimeoutstr)) {
  7172. qe.expire = qe.start + atoi(args.queuetimeoutstr);
  7173. } else {
  7174. qe.expire = 0;
  7175. }
  7176. /* Get the priority from the variable ${QUEUE_PRIO} */
  7177. ast_channel_lock(chan);
  7178. user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
  7179. if (user_priority) {
  7180. if (sscanf(user_priority, "%30d", &prio) == 1) {
  7181. ast_debug(1, "%s: Got priority %d from ${QUEUE_PRIO}.\n", ast_channel_name(chan), prio);
  7182. } else {
  7183. ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
  7184. user_priority, ast_channel_name(chan));
  7185. prio = 0;
  7186. }
  7187. } else {
  7188. ast_debug(3, "NO QUEUE_PRIO variable found. Using default.\n");
  7189. prio = 0;
  7190. }
  7191. /* Get the maximum penalty from the variable ${QUEUE_MAX_PENALTY} */
  7192. if ((max_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MAX_PENALTY"))) {
  7193. if (sscanf(max_penalty_str, "%30d", &max_penalty) == 1) {
  7194. ast_debug(1, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n", ast_channel_name(chan), max_penalty);
  7195. } else {
  7196. ast_log(LOG_WARNING, "${QUEUE_MAX_PENALTY}: Invalid value (%s), channel %s.\n",
  7197. max_penalty_str, ast_channel_name(chan));
  7198. max_penalty = INT_MAX;
  7199. }
  7200. } else {
  7201. max_penalty = INT_MAX;
  7202. }
  7203. if ((min_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MIN_PENALTY"))) {
  7204. if (sscanf(min_penalty_str, "%30d", &min_penalty) == 1) {
  7205. ast_debug(1, "%s: Got min penalty %d from ${QUEUE_MIN_PENALTY}.\n", ast_channel_name(chan), min_penalty);
  7206. } else {
  7207. ast_log(LOG_WARNING, "${QUEUE_MIN_PENALTY}: Invalid value (%s), channel %s.\n",
  7208. min_penalty_str, ast_channel_name(chan));
  7209. min_penalty = INT_MAX;
  7210. }
  7211. } else {
  7212. min_penalty = INT_MAX;
  7213. }
  7214. ast_channel_unlock(chan);
  7215. if (ast_test_flag(&opts, OPT_RINGING)) {
  7216. ringing = 1;
  7217. }
  7218. if (ringing != 1 && ast_test_flag(&opts, OPT_RING_WHEN_RINGING)) {
  7219. qe.ring_when_ringing = 1;
  7220. }
  7221. if (ast_test_flag(&opts, OPT_GO_ON)) {
  7222. qcontinue = 1;
  7223. }
  7224. if (args.position) {
  7225. position = atoi(args.position);
  7226. if (position < 0) {
  7227. ast_log(LOG_WARNING, "Invalid position '%s' given for call to queue '%s'. Assuming no preference for position\n", args.position, args.queuename);
  7228. position = 0;
  7229. }
  7230. }
  7231. ast_debug(1, "queue: %s, expires: %ld, priority: %d\n",
  7232. args.queuename, (long)qe.expire, prio);
  7233. qe.chan = chan;
  7234. qe.prio = prio;
  7235. qe.max_penalty = max_penalty;
  7236. qe.min_penalty = min_penalty;
  7237. qe.last_pos_said = 0;
  7238. qe.last_pos = 0;
  7239. qe.last_periodic_announce_time = time(NULL);
  7240. qe.last_periodic_announce_sound = 0;
  7241. qe.valid_digits = 0;
  7242. if (join_queue(args.queuename, &qe, &reason, position)) {
  7243. ast_log(LOG_WARNING, "Unable to join queue '%s'\n", args.queuename);
  7244. set_queue_result(chan, reason);
  7245. return 0;
  7246. }
  7247. ast_assert(qe.parent != NULL);
  7248. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "ENTERQUEUE", "%s|%s|%d",
  7249. S_OR(args.url, ""),
  7250. S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
  7251. qe.opos);
  7252. copy_rules(&qe, args.rule);
  7253. qe.pr = AST_LIST_FIRST(&qe.qe_rules);
  7254. check_turns:
  7255. if (ringing) {
  7256. ast_indicate(chan, AST_CONTROL_RINGING);
  7257. } else {
  7258. ast_moh_start(chan, qe.moh, NULL);
  7259. }
  7260. /* This is the wait loop for callers 2 through maxlen */
  7261. res = wait_our_turn(&qe, ringing, &reason);
  7262. if (res) {
  7263. goto stop;
  7264. }
  7265. makeannouncement = qe.parent->announce_to_first_user;
  7266. for (;;) {
  7267. /* This is the wait loop for the head caller*/
  7268. /* To exit, they may get their call answered; */
  7269. /* they may dial a digit from the queue context; */
  7270. /* or, they may timeout. */
  7271. /* Leave if we have exceeded our queuetimeout */
  7272. if (qe.expire && (time(NULL) >= qe.expire)) {
  7273. record_abandoned(&qe);
  7274. reason = QUEUE_TIMEOUT;
  7275. res = 0;
  7276. ast_queue_log(args.queuename, ast_channel_uniqueid(chan),"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
  7277. qe.pos, qe.opos, (long) (time(NULL) - qe.start));
  7278. break;
  7279. }
  7280. if (makeannouncement) {
  7281. /* Make a position announcement, if enabled */
  7282. if (qe.parent->announcefrequency) {
  7283. if ((res = say_position(&qe, ringing))) {
  7284. goto stop;
  7285. }
  7286. }
  7287. }
  7288. makeannouncement = 1;
  7289. /* Make a periodic announcement, if enabled */
  7290. if (qe.parent->periodicannouncefrequency) {
  7291. if ((res = say_periodic_announcement(&qe, ringing))) {
  7292. goto stop;
  7293. }
  7294. }
  7295. /* Leave if we have exceeded our queuetimeout */
  7296. if (qe.expire && (time(NULL) >= qe.expire)) {
  7297. record_abandoned(&qe);
  7298. reason = QUEUE_TIMEOUT;
  7299. res = 0;
  7300. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHTIMEOUT",
  7301. "%d|%d|%ld", qe.pos, qe.opos, (long) (time(NULL) - qe.start));
  7302. break;
  7303. }
  7304. /* see if we need to move to the next penalty level for this queue */
  7305. while (qe.pr && ((time(NULL) - qe.start) > qe.pr->time)) {
  7306. update_qe_rule(&qe);
  7307. }
  7308. /* Try calling all queue members for 'timeout' seconds */
  7309. res = try_calling(&qe, opts, opt_args, args.announceoverride, args.url, &tries, &noption, args.agi, args.macro, args.gosub, ringing);
  7310. if (res) {
  7311. goto stop;
  7312. }
  7313. if (qe.parent->leavewhenempty) {
  7314. int status = 0;
  7315. if ((status = get_member_status(qe.parent, qe.max_penalty, qe.min_penalty, qe.parent->leavewhenempty, 0))) {
  7316. record_abandoned(&qe);
  7317. reason = QUEUE_LEAVEEMPTY;
  7318. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe.pos, qe.opos, (long)(time(NULL) - qe.start));
  7319. res = 0;
  7320. break;
  7321. }
  7322. }
  7323. /* exit after 'timeout' cycle if 'n' option enabled */
  7324. if (noption && tries >= ao2_container_count(qe.parent->members)) {
  7325. ast_verb(3, "Exiting on time-out cycle\n");
  7326. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHTIMEOUT",
  7327. "%d|%d|%ld", qe.pos, qe.opos, (long) (time(NULL) - qe.start));
  7328. record_abandoned(&qe);
  7329. reason = QUEUE_TIMEOUT;
  7330. res = 0;
  7331. break;
  7332. }
  7333. /* Leave if we have exceeded our queuetimeout */
  7334. if (qe.expire && (time(NULL) >= qe.expire)) {
  7335. record_abandoned(&qe);
  7336. reason = QUEUE_TIMEOUT;
  7337. res = 0;
  7338. ast_queue_log(qe.parent->name, ast_channel_uniqueid(qe.chan),"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld", qe.pos, qe.opos, (long) (time(NULL) - qe.start));
  7339. break;
  7340. }
  7341. /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */
  7342. res = wait_a_bit(&qe);
  7343. if (res) {
  7344. goto stop;
  7345. }
  7346. /* If using dynamic realtime members, we should regenerate the member list for this queue */
  7347. update_realtime_members(qe.parent);
  7348. /* Since this is a priority queue and
  7349. * it is not sure that we are still at the head
  7350. * of the queue, go and check for our turn again.
  7351. */
  7352. if (!is_our_turn(&qe)) {
  7353. ast_debug(1, "Darn priorities, going back in queue (%s)!\n", ast_channel_name(qe.chan));
  7354. goto check_turns;
  7355. }
  7356. }
  7357. stop:
  7358. if (res) {
  7359. if (res < 0) {
  7360. if (!qe.handled) {
  7361. record_abandoned(&qe);
  7362. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "ABANDON",
  7363. "%d|%d|%ld", qe.pos, qe.opos,
  7364. (long) (time(NULL) - qe.start));
  7365. res = -1;
  7366. } else if (reason == QUEUE_LEAVEEMPTY) {
  7367. /* Return back to dialplan, don't hang up */
  7368. res = 0;
  7369. } else if (qcontinue) {
  7370. reason = QUEUE_CONTINUE;
  7371. res = 0;
  7372. }
  7373. } else if (qe.valid_digits) {
  7374. ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHKEY",
  7375. "%s|%d|%d|%ld", qe.digits, qe.pos, qe.opos, (long) (time(NULL) - qe.start));
  7376. }
  7377. }
  7378. /* Don't allow return code > 0 */
  7379. if (res >= 0) {
  7380. res = 0;
  7381. if (ringing) {
  7382. ast_indicate(chan, -1);
  7383. } else {
  7384. ast_moh_stop(chan);
  7385. }
  7386. ast_stopstream(chan);
  7387. }
  7388. set_queue_variables(qe.parent, qe.chan);
  7389. leave_queue(&qe);
  7390. if (reason != QUEUE_UNKNOWN)
  7391. set_queue_result(chan, reason);
  7392. /*
  7393. * every queue_ent is given a reference to it's parent
  7394. * call_queue when it joins the queue. This ref must be taken
  7395. * away right before the queue_ent is destroyed. In this case
  7396. * the queue_ent is about to be returned on the stack
  7397. */
  7398. qe.parent = queue_unref(qe.parent);
  7399. return res;
  7400. }
  7401. /*!
  7402. * \brief create interface var with all queue details.
  7403. * \retval 0 on success
  7404. * \retval -1 on error
  7405. */
  7406. static int queue_function_var(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  7407. {
  7408. int res = -1;
  7409. struct call_queue *q;
  7410. char interfacevar[256] = "";
  7411. float sl = 0;
  7412. if (ast_strlen_zero(data)) {
  7413. ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
  7414. return -1;
  7415. }
  7416. if ((q = find_load_queue_rt_friendly(data))) {
  7417. ao2_lock(q);
  7418. if (q->setqueuevar) {
  7419. sl = 0;
  7420. res = 0;
  7421. if (q->callscompleted > 0) {
  7422. sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
  7423. }
  7424. snprintf(interfacevar, sizeof(interfacevar),
  7425. "QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
  7426. q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
  7427. pbx_builtin_setvar_multiple(chan, interfacevar);
  7428. }
  7429. ao2_unlock(q);
  7430. queue_t_unref(q, "Done with QUEUE() function");
  7431. } else {
  7432. ast_log(LOG_WARNING, "queue %s was not found\n", data);
  7433. }
  7434. snprintf(buf, len, "%d", res);
  7435. return 0;
  7436. }
  7437. /*!
  7438. * \brief Check if a given queue exists
  7439. *
  7440. */
  7441. static int queue_function_exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  7442. {
  7443. struct call_queue *q;
  7444. buf[0] = '\0';
  7445. if (ast_strlen_zero(data)) {
  7446. ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
  7447. return -1;
  7448. }
  7449. q = find_load_queue_rt_friendly(data);
  7450. snprintf(buf, len, "%d", q != NULL? 1 : 0);
  7451. if (q) {
  7452. queue_t_unref(q, "Done with temporary reference in QUEUE_EXISTS()");
  7453. }
  7454. return 0;
  7455. }
  7456. static struct member *get_interface_helper(struct call_queue *q, const char *interface)
  7457. {
  7458. struct member *m;
  7459. if (ast_strlen_zero(interface)) {
  7460. ast_log(LOG_ERROR, "QUEUE_MEMBER: Missing required interface argument.\n");
  7461. return NULL;
  7462. }
  7463. m = interface_exists(q, interface);
  7464. if (!m) {
  7465. ast_log(LOG_ERROR, "Queue member interface '%s' not in queue '%s'.\n",
  7466. interface, q->name);
  7467. }
  7468. return m;
  7469. }
  7470. /*!
  7471. * \brief Get number either busy / free / ready or total members of a specific queue
  7472. * \brief Get or set member properties penalty / paused / ringinuse
  7473. * \retval number of members (busy / free / ready / total) or member info (penalty / paused / ringinuse)
  7474. * \retval -1 on error
  7475. */
  7476. static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  7477. {
  7478. int count = 0;
  7479. struct member *m;
  7480. struct ao2_iterator mem_iter;
  7481. struct call_queue *q;
  7482. AST_DECLARE_APP_ARGS(args,
  7483. AST_APP_ARG(queuename);
  7484. AST_APP_ARG(option);
  7485. AST_APP_ARG(interface);
  7486. );
  7487. /* Make sure the returned value on error is zero length string. */
  7488. buf[0] = '\0';
  7489. if (ast_strlen_zero(data)) {
  7490. ast_log(LOG_ERROR,
  7491. "Missing required argument. %s(<queuename>,<option>[,<interface>])\n",
  7492. cmd);
  7493. return -1;
  7494. }
  7495. AST_STANDARD_APP_ARGS(args, data);
  7496. if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.option)) {
  7497. ast_log(LOG_ERROR,
  7498. "Missing required argument. %s(<queuename>,<option>[,<interface>])\n",
  7499. cmd);
  7500. return -1;
  7501. }
  7502. if ((q = find_load_queue_rt_friendly(args.queuename))) {
  7503. ao2_lock(q);
  7504. if (!strcasecmp(args.option, "logged")) {
  7505. mem_iter = ao2_iterator_init(q->members, 0);
  7506. while ((m = ao2_iterator_next(&mem_iter))) {
  7507. /* Count the agents who are logged in and presently answering calls */
  7508. if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
  7509. count++;
  7510. }
  7511. ao2_ref(m, -1);
  7512. }
  7513. ao2_iterator_destroy(&mem_iter);
  7514. } else if (!strcasecmp(args.option, "free")) {
  7515. mem_iter = ao2_iterator_init(q->members, 0);
  7516. while ((m = ao2_iterator_next(&mem_iter))) {
  7517. /* Count the agents who are logged in and presently answering calls */
  7518. if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused)) {
  7519. count++;
  7520. }
  7521. ao2_ref(m, -1);
  7522. }
  7523. ao2_iterator_destroy(&mem_iter);
  7524. } else if (!strcasecmp(args.option, "ready")) {
  7525. time_t now;
  7526. time(&now);
  7527. mem_iter = ao2_iterator_init(q->members, 0);
  7528. while ((m = ao2_iterator_next(&mem_iter))) {
  7529. /* Count the agents who are logged in, not paused and not wrapping up */
  7530. if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused) &&
  7531. !(m->lastcall && q->wrapuptime && ((now - q->wrapuptime) < m->lastcall))) {
  7532. count++;
  7533. }
  7534. ao2_ref(m, -1);
  7535. }
  7536. ao2_iterator_destroy(&mem_iter);
  7537. } else if (!strcasecmp(args.option, "count")) {
  7538. count = ao2_container_count(q->members);
  7539. } else if (!strcasecmp(args.option, "penalty")) {
  7540. m = get_interface_helper(q, args.interface);
  7541. if (m) {
  7542. count = m->penalty;
  7543. ao2_ref(m, -1);
  7544. }
  7545. } else if (!strcasecmp(args.option, "paused")) {
  7546. m = get_interface_helper(q, args.interface);
  7547. if (m) {
  7548. count = m->paused;
  7549. ao2_ref(m, -1);
  7550. }
  7551. } else if ((!strcasecmp(args.option, "ignorebusy") /* ignorebusy is legacy */
  7552. || !strcasecmp(args.option, "ringinuse"))) {
  7553. m = get_interface_helper(q, args.interface);
  7554. if (m) {
  7555. count = m->ringinuse;
  7556. ao2_ref(m, -1);
  7557. }
  7558. } else {
  7559. ast_log(LOG_ERROR, "%s: Invalid option '%s' provided.\n", cmd, args.option);
  7560. }
  7561. ao2_unlock(q);
  7562. queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
  7563. } else {
  7564. ast_log(LOG_WARNING, "queue %s was not found\n", args.queuename);
  7565. }
  7566. snprintf(buf, len, "%d", count);
  7567. return 0;
  7568. }
  7569. /*! \brief Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ringinuse. */
  7570. static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
  7571. {
  7572. int memvalue;
  7573. AST_DECLARE_APP_ARGS(args,
  7574. AST_APP_ARG(queuename);
  7575. AST_APP_ARG(option);
  7576. AST_APP_ARG(interface);
  7577. );
  7578. if (ast_strlen_zero(data)) {
  7579. ast_log(LOG_ERROR,
  7580. "Missing required argument. %s([<queuename>],<option>,<interface>)\n",
  7581. cmd);
  7582. return -1;
  7583. }
  7584. AST_STANDARD_APP_ARGS(args, data);
  7585. if (ast_strlen_zero(args.option)
  7586. || ast_strlen_zero(args.interface)) {
  7587. ast_log(LOG_ERROR,
  7588. "Missing required argument. %s([<queuename>],<option>,<interface>)\n",
  7589. cmd);
  7590. return -1;
  7591. }
  7592. /*
  7593. * If queuename is empty then the option will be
  7594. * set for the interface in all queues.
  7595. */
  7596. memvalue = atoi(value);
  7597. if (!strcasecmp(args.option, "penalty")) {
  7598. if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, memvalue)) {
  7599. ast_log(LOG_ERROR, "Invalid interface, queue, or penalty\n");
  7600. return -1;
  7601. }
  7602. } else if (!strcasecmp(args.option, "paused")) {
  7603. memvalue = (memvalue <= 0) ? 0 : 1;
  7604. if (set_member_paused(args.queuename, args.interface, NULL, memvalue)) {
  7605. ast_log(LOG_ERROR, "Invalid interface or queue\n");
  7606. return -1;
  7607. }
  7608. } else if (!strcasecmp(args.option, "ignorebusy") /* ignorebusy is legacy */
  7609. || !strcasecmp(args.option, "ringinuse")) {
  7610. memvalue = (memvalue <= 0) ? 0 : 1;
  7611. if (set_member_value(args.queuename, args.interface, MEMBER_RINGINUSE, memvalue)) {
  7612. ast_log(LOG_ERROR, "Invalid interface or queue\n");
  7613. return -1;
  7614. }
  7615. } else {
  7616. ast_log(LOG_ERROR, "%s: Invalid option '%s' provided.\n", cmd, args.option);
  7617. return -1;
  7618. }
  7619. return 0;
  7620. }
  7621. /*!
  7622. * \brief Get the total number of members in a specific queue (Deprecated)
  7623. * \retval number of members
  7624. * \retval -1 on error
  7625. */
  7626. static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  7627. {
  7628. int count = 0;
  7629. struct member *m;
  7630. struct call_queue *q;
  7631. struct ao2_iterator mem_iter;
  7632. static int depflag = 1;
  7633. if (depflag) {
  7634. depflag = 0;
  7635. ast_log(LOG_NOTICE, "The function QUEUE_MEMBER_COUNT has been deprecated in favor of the QUEUE_MEMBER function and will not be in further releases.\n");
  7636. }
  7637. if (ast_strlen_zero(data)) {
  7638. ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
  7639. return -1;
  7640. }
  7641. if ((q = find_load_queue_rt_friendly(data))) {
  7642. ao2_lock(q);
  7643. mem_iter = ao2_iterator_init(q->members, 0);
  7644. while ((m = ao2_iterator_next(&mem_iter))) {
  7645. /* Count the agents who are logged in and presently answering calls */
  7646. if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
  7647. count++;
  7648. }
  7649. ao2_ref(m, -1);
  7650. }
  7651. ao2_iterator_destroy(&mem_iter);
  7652. ao2_unlock(q);
  7653. queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER_COUNT");
  7654. } else {
  7655. ast_log(LOG_WARNING, "queue %s was not found\n", data);
  7656. }
  7657. snprintf(buf, len, "%d", count);
  7658. return 0;
  7659. }
  7660. /*! \brief Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue */
  7661. static int queue_function_queuewaitingcount(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  7662. {
  7663. int count = 0;
  7664. struct call_queue *q, tmpq = {
  7665. .name = data,
  7666. };
  7667. struct ast_variable *var = NULL;
  7668. buf[0] = '\0';
  7669. if (ast_strlen_zero(data)) {
  7670. ast_log(LOG_ERROR, "QUEUE_WAITING_COUNT requires an argument: queuename\n");
  7671. return -1;
  7672. }
  7673. if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_WAITING_COUNT()"))) {
  7674. ao2_lock(q);
  7675. count = q->count;
  7676. ao2_unlock(q);
  7677. queue_t_unref(q, "Done with reference in QUEUE_WAITING_COUNT()");
  7678. } else if ((var = ast_load_realtime("queues", "name", data, SENTINEL))) {
  7679. /* if the queue is realtime but was not found in memory, this
  7680. * means that the queue had been deleted from memory since it was
  7681. * "dead." This means it has a 0 waiting count
  7682. */
  7683. count = 0;
  7684. ast_variables_destroy(var);
  7685. } else {
  7686. ast_log(LOG_WARNING, "queue %s was not found\n", data);
  7687. }
  7688. snprintf(buf, len, "%d", count);
  7689. return 0;
  7690. }
  7691. /*! \brief Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue */
  7692. static int queue_function_queuememberlist(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  7693. {
  7694. struct call_queue *q;
  7695. struct member *m;
  7696. /* Ensure an otherwise empty list doesn't return garbage */
  7697. buf[0] = '\0';
  7698. if (ast_strlen_zero(data)) {
  7699. ast_log(LOG_ERROR, "QUEUE_MEMBER_LIST requires an argument: queuename\n");
  7700. return -1;
  7701. }
  7702. if ((q = find_load_queue_rt_friendly(data))) {
  7703. int buflen = 0, count = 0;
  7704. struct ao2_iterator mem_iter;
  7705. ao2_lock(q);
  7706. mem_iter = ao2_iterator_init(q->members, 0);
  7707. while ((m = ao2_iterator_next(&mem_iter))) {
  7708. /* strcat() is always faster than printf() */
  7709. if (count++) {
  7710. strncat(buf + buflen, ",", len - buflen - 1);
  7711. buflen++;
  7712. }
  7713. strncat(buf + buflen, m->interface, len - buflen - 1);
  7714. buflen += strlen(m->interface);
  7715. /* Safeguard against overflow (negative length) */
  7716. if (buflen >= len - 2) {
  7717. ao2_ref(m, -1);
  7718. ast_log(LOG_WARNING, "Truncating list\n");
  7719. break;
  7720. }
  7721. ao2_ref(m, -1);
  7722. }
  7723. ao2_iterator_destroy(&mem_iter);
  7724. ao2_unlock(q);
  7725. queue_t_unref(q, "Done with QUEUE_MEMBER_LIST()");
  7726. } else
  7727. ast_log(LOG_WARNING, "queue %s was not found\n", data);
  7728. /* We should already be terminated, but let's make sure. */
  7729. buf[len - 1] = '\0';
  7730. return 0;
  7731. }
  7732. /*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty. */
  7733. static int queue_function_memberpenalty_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  7734. {
  7735. int penalty;
  7736. AST_DECLARE_APP_ARGS(args,
  7737. AST_APP_ARG(queuename);
  7738. AST_APP_ARG(interface);
  7739. );
  7740. /* Make sure the returned value on error is NULL. */
  7741. buf[0] = '\0';
  7742. if (ast_strlen_zero(data)) {
  7743. ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
  7744. return -1;
  7745. }
  7746. AST_STANDARD_APP_ARGS(args, data);
  7747. if (args.argc < 2) {
  7748. ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
  7749. return -1;
  7750. }
  7751. penalty = get_member_penalty (args.queuename, args.interface);
  7752. if (penalty >= 0) { /* remember that buf is already '\0' */
  7753. snprintf (buf, len, "%d", penalty);
  7754. }
  7755. return 0;
  7756. }
  7757. /*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty. */
  7758. static int queue_function_memberpenalty_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
  7759. {
  7760. int penalty;
  7761. AST_DECLARE_APP_ARGS(args,
  7762. AST_APP_ARG(queuename);
  7763. AST_APP_ARG(interface);
  7764. );
  7765. if (ast_strlen_zero(data)) {
  7766. ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
  7767. return -1;
  7768. }
  7769. AST_STANDARD_APP_ARGS(args, data);
  7770. if (args.argc < 2) {
  7771. ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
  7772. return -1;
  7773. }
  7774. penalty = atoi(value);
  7775. if (ast_strlen_zero(args.interface)) {
  7776. ast_log (LOG_ERROR, "<interface> parameter can't be null\n");
  7777. return -1;
  7778. }
  7779. /* if queuename = NULL then penalty will be set for interface in all the queues. */
  7780. if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, penalty)) {
  7781. ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
  7782. return -1;
  7783. }
  7784. return 0;
  7785. }
  7786. static struct ast_custom_function queueexists_function = {
  7787. .name = "QUEUE_EXISTS",
  7788. .read = queue_function_exists,
  7789. };
  7790. static struct ast_custom_function queuevar_function = {
  7791. .name = "QUEUE_VARIABLES",
  7792. .read = queue_function_var,
  7793. };
  7794. static struct ast_custom_function queuemembercount_function = {
  7795. .name = "QUEUE_MEMBER",
  7796. .read = queue_function_mem_read,
  7797. .write = queue_function_mem_write,
  7798. };
  7799. static struct ast_custom_function queuemembercount_dep = {
  7800. .name = "QUEUE_MEMBER_COUNT",
  7801. .read = queue_function_qac_dep,
  7802. };
  7803. static struct ast_custom_function queuewaitingcount_function = {
  7804. .name = "QUEUE_WAITING_COUNT",
  7805. .read = queue_function_queuewaitingcount,
  7806. };
  7807. static struct ast_custom_function queuememberlist_function = {
  7808. .name = "QUEUE_MEMBER_LIST",
  7809. .read = queue_function_queuememberlist,
  7810. };
  7811. static struct ast_custom_function queuememberpenalty_function = {
  7812. .name = "QUEUE_MEMBER_PENALTY",
  7813. .read = queue_function_memberpenalty_read,
  7814. .write = queue_function_memberpenalty_write,
  7815. };
  7816. /*! Set the global queue rules parameters as defined in the "general" section of queuerules.conf */
  7817. static void queue_rules_set_global_params(struct ast_config *cfg)
  7818. {
  7819. const char *general_val = NULL;
  7820. realtime_rules = 0;
  7821. if ((general_val = ast_variable_retrieve(cfg, "general", "realtime_rules"))) {
  7822. realtime_rules = ast_true(general_val);
  7823. }
  7824. }
  7825. /*! \brief Reload the rules defined in queuerules.conf
  7826. *
  7827. * \param reload If 1, then only process queuerules.conf if the file
  7828. * has changed since the last time we inspected it.
  7829. * \return Always returns AST_MODULE_LOAD_SUCCESS
  7830. */
  7831. static int reload_queue_rules(int reload)
  7832. {
  7833. struct ast_config *cfg;
  7834. struct rule_list *rl_iter, *new_rl;
  7835. struct penalty_rule *pr_iter;
  7836. char *rulecat = NULL;
  7837. struct ast_variable *rulevar = NULL;
  7838. struct ast_flags config_flags = { (reload && !realtime_rules) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
  7839. if (!(cfg = ast_config_load("queuerules.conf", config_flags))) {
  7840. ast_log(LOG_NOTICE, "No queuerules.conf file found, queues will not follow penalty rules\n");
  7841. return AST_MODULE_LOAD_SUCCESS;
  7842. } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
  7843. ast_log(LOG_NOTICE, "queuerules.conf has not changed since it was last loaded. Not taking any action.\n");
  7844. return AST_MODULE_LOAD_SUCCESS;
  7845. } else if (cfg == CONFIG_STATUS_FILEINVALID) {
  7846. ast_log(LOG_ERROR, "Config file queuerules.conf is in an invalid format. Aborting.\n");
  7847. return AST_MODULE_LOAD_SUCCESS;
  7848. }
  7849. AST_LIST_LOCK(&rule_lists);
  7850. while ((rl_iter = AST_LIST_REMOVE_HEAD(&rule_lists, list))) {
  7851. while ((pr_iter = AST_LIST_REMOVE_HEAD(&rl_iter->rules, list)))
  7852. ast_free(pr_iter);
  7853. ast_free(rl_iter);
  7854. }
  7855. while ((rulecat = ast_category_browse(cfg, rulecat))) {
  7856. if (!strcasecmp(rulecat, "general")) {
  7857. queue_rules_set_global_params(cfg);
  7858. continue;
  7859. }
  7860. if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
  7861. AST_LIST_UNLOCK(&rule_lists);
  7862. ast_config_destroy(cfg);
  7863. return AST_MODULE_LOAD_DECLINE;
  7864. } else {
  7865. ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name));
  7866. AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
  7867. for (rulevar = ast_variable_browse(cfg, rulecat); rulevar; rulevar = rulevar->next)
  7868. if(!strcasecmp(rulevar->name, "penaltychange"))
  7869. insert_penaltychange(new_rl->name, rulevar->value, rulevar->lineno);
  7870. else
  7871. ast_log(LOG_WARNING, "Don't know how to handle rule type '%s' on line %d\n", rulevar->name, rulevar->lineno);
  7872. }
  7873. }
  7874. ast_config_destroy(cfg);
  7875. if (realtime_rules && load_realtime_rules()) {
  7876. AST_LIST_UNLOCK(&rule_lists);
  7877. return AST_MODULE_LOAD_DECLINE;
  7878. }
  7879. AST_LIST_UNLOCK(&rule_lists);
  7880. return AST_MODULE_LOAD_SUCCESS;
  7881. }
  7882. /*! Set the global queue parameters as defined in the "general" section of queues.conf */
  7883. static void queue_set_global_params(struct ast_config *cfg)
  7884. {
  7885. const char *general_val = NULL;
  7886. queue_persistent_members = 0;
  7887. if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) {
  7888. queue_persistent_members = ast_true(general_val);
  7889. }
  7890. autofill_default = 0;
  7891. if ((general_val = ast_variable_retrieve(cfg, "general", "autofill"))) {
  7892. autofill_default = ast_true(general_val);
  7893. }
  7894. montype_default = 0;
  7895. if ((general_val = ast_variable_retrieve(cfg, "general", "monitor-type"))) {
  7896. if (!strcasecmp(general_val, "mixmonitor"))
  7897. montype_default = 1;
  7898. }
  7899. update_cdr = 0;
  7900. if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr"))) {
  7901. update_cdr = ast_true(general_val);
  7902. }
  7903. shared_lastcall = 0;
  7904. if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall"))) {
  7905. shared_lastcall = ast_true(general_val);
  7906. }
  7907. negative_penalty_invalid = 0;
  7908. if ((general_val = ast_variable_retrieve(cfg, "general", "negative_penalty_invalid"))) {
  7909. negative_penalty_invalid = ast_true(general_val);
  7910. }
  7911. log_membername_as_agent = 0;
  7912. if ((general_val = ast_variable_retrieve(cfg, "general", "log_membername_as_agent"))) {
  7913. log_membername_as_agent = ast_true(general_val);
  7914. }
  7915. }
  7916. /*! \brief reload information pertaining to a single member
  7917. *
  7918. * This function is called when a member = line is encountered in
  7919. * queues.conf.
  7920. *
  7921. * \param memberdata The part after member = in the config file
  7922. * \param q The queue to which this member belongs
  7923. */
  7924. static void reload_single_member(const char *memberdata, struct call_queue *q)
  7925. {
  7926. char *membername, *interface, *state_interface, *tmp;
  7927. char *parse;
  7928. struct member *cur, *newm;
  7929. struct member tmpmem;
  7930. int penalty;
  7931. int ringinuse;
  7932. AST_DECLARE_APP_ARGS(args,
  7933. AST_APP_ARG(interface);
  7934. AST_APP_ARG(penalty);
  7935. AST_APP_ARG(membername);
  7936. AST_APP_ARG(state_interface);
  7937. AST_APP_ARG(ringinuse);
  7938. );
  7939. if (ast_strlen_zero(memberdata)) {
  7940. ast_log(LOG_WARNING, "Empty queue member definition. Moving on!\n");
  7941. return;
  7942. }
  7943. /* Add a new member */
  7944. parse = ast_strdupa(memberdata);
  7945. AST_STANDARD_APP_ARGS(args, parse);
  7946. interface = args.interface;
  7947. if (!ast_strlen_zero(args.penalty)) {
  7948. tmp = args.penalty;
  7949. ast_strip(tmp);
  7950. penalty = atoi(tmp);
  7951. if (penalty < 0) {
  7952. penalty = 0;
  7953. }
  7954. } else {
  7955. penalty = 0;
  7956. }
  7957. if (!ast_strlen_zero(args.membername)) {
  7958. membername = args.membername;
  7959. ast_strip(membername);
  7960. } else {
  7961. membername = interface;
  7962. }
  7963. if (!ast_strlen_zero(args.state_interface)) {
  7964. state_interface = args.state_interface;
  7965. ast_strip(state_interface);
  7966. } else {
  7967. state_interface = interface;
  7968. }
  7969. if (!ast_strlen_zero(args.ringinuse)) {
  7970. tmp = args.ringinuse;
  7971. ast_strip(tmp);
  7972. if (ast_true(tmp)) {
  7973. ringinuse = 1;
  7974. } else if (ast_false(tmp)) {
  7975. ringinuse = 0;
  7976. } else {
  7977. ast_log(LOG_ERROR, "Member %s has an invalid ringinuse value. Using %s ringinuse value.\n",
  7978. membername, q->name);
  7979. ringinuse = q->ringinuse;
  7980. }
  7981. } else {
  7982. ringinuse = q->ringinuse;
  7983. }
  7984. /* Find the old position in the list */
  7985. ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
  7986. cur = ao2_find(q->members, &tmpmem, OBJ_POINTER);
  7987. if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse))) {
  7988. if (cur) {
  7989. /* Round Robin Queue Position must be copied if this is replacing an existing member */
  7990. ao2_lock(q->members);
  7991. newm->queuepos = cur->queuepos;
  7992. ao2_link(q->members, newm);
  7993. ao2_unlink(q->members, cur);
  7994. ao2_unlock(q->members);
  7995. } else {
  7996. /* Otherwise we need to add using the function that will apply a round robin queue position manually. */
  7997. member_add_to_queue(q, newm);
  7998. }
  7999. ao2_ref(newm, -1);
  8000. }
  8001. newm = NULL;
  8002. if (cur) {
  8003. ao2_ref(cur, -1);
  8004. }
  8005. }
  8006. static int mark_member_dead(void *obj, void *arg, int flags)
  8007. {
  8008. struct member *member = obj;
  8009. if (!member->dynamic && !member->realtime) {
  8010. member->delme = 1;
  8011. }
  8012. return 0;
  8013. }
  8014. static int kill_dead_members(void *obj, void *arg, int flags)
  8015. {
  8016. struct member *member = obj;
  8017. if (!member->delme) {
  8018. member->status = get_queue_member_status(member);
  8019. return 0;
  8020. } else {
  8021. return CMP_MATCH;
  8022. }
  8023. }
  8024. /*! \brief Reload information pertaining to a particular queue
  8025. *
  8026. * Once we have isolated a queue within reload_queues, we call this. This will either
  8027. * reload information for the queue or if we're just reloading member information, we'll just
  8028. * reload that without touching other settings within the queue
  8029. *
  8030. * \param cfg The configuration which we are reading
  8031. * \param mask Tells us what information we need to reload
  8032. * \param queuename The name of the queue we are reloading information from
  8033. * \retval void
  8034. */
  8035. static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, const char *queuename)
  8036. {
  8037. int new;
  8038. struct call_queue *q = NULL;
  8039. /*We're defining a queue*/
  8040. struct call_queue tmpq = {
  8041. .name = queuename,
  8042. };
  8043. const char *tmpvar;
  8044. const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
  8045. const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
  8046. int prev_weight = 0;
  8047. struct ast_variable *var;
  8048. if (!(q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find queue for reload"))) {
  8049. if (queue_reload) {
  8050. /* Make one then */
  8051. if (!(q = alloc_queue(queuename))) {
  8052. return;
  8053. }
  8054. } else {
  8055. /* Since we're not reloading queues, this means that we found a queue
  8056. * in the configuration file which we don't know about yet. Just return.
  8057. */
  8058. return;
  8059. }
  8060. new = 1;
  8061. } else {
  8062. new = 0;
  8063. }
  8064. if (!new) {
  8065. ao2_lock(q);
  8066. prev_weight = q->weight ? 1 : 0;
  8067. }
  8068. /* Check if we already found a queue with this name in the config file */
  8069. if (q->found) {
  8070. ast_log(LOG_WARNING, "Queue '%s' already defined! Skipping!\n", queuename);
  8071. if (!new) {
  8072. /* It should be impossible to *not* hit this case*/
  8073. ao2_unlock(q);
  8074. }
  8075. queue_t_unref(q, "We exist! Expiring temporary pointer");
  8076. return;
  8077. }
  8078. /* Due to the fact that the "linear" strategy will have a different allocation
  8079. * scheme for queue members, we must devise the queue's strategy before other initializations.
  8080. * To be specific, the linear strategy needs to function like a linked list, meaning the ao2
  8081. * container used will have only a single bucket instead of the typical number.
  8082. */
  8083. if (queue_reload) {
  8084. if ((tmpvar = ast_variable_retrieve(cfg, queuename, "strategy"))) {
  8085. q->strategy = strat2int(tmpvar);
  8086. if (q->strategy < 0) {
  8087. ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
  8088. tmpvar, q->name);
  8089. q->strategy = QUEUE_STRATEGY_RINGALL;
  8090. }
  8091. } else {
  8092. q->strategy = QUEUE_STRATEGY_RINGALL;
  8093. }
  8094. init_queue(q);
  8095. }
  8096. if (member_reload) {
  8097. ao2_callback(q->members, OBJ_NODATA, mark_member_dead, NULL);
  8098. q->found = 1;
  8099. }
  8100. /* On the first pass we just read the parameters of the queue */
  8101. for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
  8102. if (queue_reload && strcasecmp(var->name, "member")) {
  8103. queue_set_param(q, var->name, var->value, var->lineno, 1);
  8104. }
  8105. }
  8106. /* On the second pass, we read members */
  8107. for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
  8108. if (member_reload && !strcasecmp(var->name, "member")) {
  8109. reload_single_member(var->value, q);
  8110. }
  8111. }
  8112. /* At this point, we've determined if the queue has a weight, so update use_weight
  8113. * as appropriate
  8114. */
  8115. if (!q->weight && prev_weight) {
  8116. ast_atomic_fetchadd_int(&use_weight, -1);
  8117. } else if (q->weight && !prev_weight) {
  8118. ast_atomic_fetchadd_int(&use_weight, +1);
  8119. }
  8120. /* Free remaining members marked as delme */
  8121. if (member_reload) {
  8122. ao2_lock(q->members);
  8123. ao2_callback(q->members, OBJ_NODATA | OBJ_MULTIPLE, queue_delme_members_decrement_followers, q);
  8124. ao2_callback(q->members, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_members, q);
  8125. ao2_unlock(q->members);
  8126. }
  8127. if (new) {
  8128. queues_t_link(queues, q, "Add queue to container");
  8129. } else {
  8130. ao2_unlock(q);
  8131. }
  8132. queue_t_unref(q, "Expiring creation reference");
  8133. }
  8134. static int mark_unfound(void *obj, void *arg, int flags)
  8135. {
  8136. struct call_queue *q = obj;
  8137. char *queuename = arg;
  8138. if (!q->realtime && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
  8139. q->found = 0;
  8140. }
  8141. return 0;
  8142. }
  8143. static int kill_if_unfound(void *obj, void *arg, int flags)
  8144. {
  8145. struct call_queue *q = obj;
  8146. char *queuename = arg;
  8147. if (!q->realtime && !q->found && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
  8148. q->dead = 1;
  8149. return CMP_MATCH;
  8150. } else {
  8151. return 0;
  8152. }
  8153. }
  8154. /*! \brief reload the queues.conf file
  8155. *
  8156. * This function reloads the information in the general section of the queues.conf
  8157. * file and potentially more, depending on the value of mask.
  8158. *
  8159. * \param reload 0 if we are calling this the first time, 1 every other time
  8160. * \param mask Gives flags telling us what information to actually reload
  8161. * \param queuename If set to a non-zero string, then only reload information from
  8162. * that particular queue. Otherwise inspect all queues
  8163. * \retval -1 Failure occurred
  8164. * \retval 0 All clear!
  8165. */
  8166. static int reload_queues(int reload, struct ast_flags *mask, const char *queuename)
  8167. {
  8168. struct ast_config *cfg;
  8169. char *cat;
  8170. struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
  8171. const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
  8172. if (!(cfg = ast_config_load("queues.conf", config_flags))) {
  8173. ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");
  8174. return -1;
  8175. } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
  8176. return 0;
  8177. } else if (cfg == CONFIG_STATUS_FILEINVALID) {
  8178. ast_log(LOG_ERROR, "Config file queues.conf is in an invalid format. Aborting.\n");
  8179. return -1;
  8180. }
  8181. /* We've made it here, so it looks like we're doing operations on all queues. */
  8182. ao2_lock(queues);
  8183. /* Mark non-realtime queues not found at the beginning. */
  8184. ao2_callback(queues, OBJ_NODATA, mark_unfound, (char *) queuename);
  8185. /* Chug through config file. */
  8186. cat = NULL;
  8187. while ((cat = ast_category_browse(cfg, cat)) ) {
  8188. if (!strcasecmp(cat, "general") && queue_reload) {
  8189. queue_set_global_params(cfg);
  8190. continue;
  8191. }
  8192. if (ast_strlen_zero(queuename) || !strcasecmp(cat, queuename))
  8193. reload_single_queue(cfg, mask, cat);
  8194. }
  8195. ast_config_destroy(cfg);
  8196. if (queue_reload) {
  8197. /* Unlink and mark dead all non-realtime queues that were not found in the configuration file. */
  8198. ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NOLOCK, kill_if_unfound, (char *) queuename);
  8199. }
  8200. ao2_unlock(queues);
  8201. return 0;
  8202. }
  8203. /*! \brief Facilitates resetting statistics for a queue
  8204. *
  8205. * This function actually does not reset any statistics, but
  8206. * rather finds a call_queue struct which corresponds to the
  8207. * passed-in queue name and passes that structure to the
  8208. * clear_queue function. If no queuename is passed in, then
  8209. * all queues will have their statistics reset.
  8210. *
  8211. * \param queuename The name of the queue to reset the statistics
  8212. * for. If this is NULL or zero-length, then this means to reset
  8213. * the statistics for all queues
  8214. * \retval void
  8215. */
  8216. static int clear_stats(const char *queuename)
  8217. {
  8218. struct call_queue *q;
  8219. struct ao2_iterator queue_iter;
  8220. queue_iter = ao2_iterator_init(queues, 0);
  8221. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  8222. ao2_lock(q);
  8223. if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
  8224. clear_queue(q);
  8225. ao2_unlock(q);
  8226. queue_t_unref(q, "Done with iterator");
  8227. }
  8228. ao2_iterator_destroy(&queue_iter);
  8229. return 0;
  8230. }
  8231. /*! \brief The command center for all reload operations
  8232. *
  8233. * Whenever any piece of queue information is to be reloaded, this function
  8234. * is called. It interprets the flags set in the mask parameter and acts
  8235. * based on how they are set.
  8236. *
  8237. * \param reload True if we are reloading information, false if we are loading
  8238. * information for the first time.
  8239. * \param mask A bitmask which tells the handler what actions to take
  8240. * \param queuename The name of the queue on which we wish to take action
  8241. * \retval 0 All reloads were successful
  8242. * \retval non-zero There was a failure
  8243. */
  8244. static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
  8245. {
  8246. int res = 0;
  8247. if (ast_test_flag(mask, QUEUE_RELOAD_RULES)) {
  8248. res |= reload_queue_rules(reload);
  8249. }
  8250. if (ast_test_flag(mask, QUEUE_RESET_STATS)) {
  8251. res |= clear_stats(queuename);
  8252. }
  8253. if (ast_test_flag(mask, (QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER))) {
  8254. res |= reload_queues(reload, mask, queuename);
  8255. }
  8256. return res;
  8257. }
  8258. /*! \brief direct ouput to manager or cli with proper terminator */
  8259. static void do_print(struct mansession *s, int fd, const char *str)
  8260. {
  8261. if (s) {
  8262. astman_append(s, "%s\r\n", str);
  8263. } else {
  8264. ast_cli(fd, "%s\n", str);
  8265. }
  8266. }
  8267. /*!
  8268. * \brief Show queue(s) status and statistics
  8269. *
  8270. * List the queues strategy, calls processed, members logged in,
  8271. * other queue statistics such as avg hold time.
  8272. */
  8273. static char *__queues_show(struct mansession *s, int fd, int argc, const char * const *argv)
  8274. {
  8275. struct call_queue *q;
  8276. struct ast_str *out = ast_str_alloca(512);
  8277. int found = 0;
  8278. time_t now = time(NULL);
  8279. struct ao2_iterator queue_iter;
  8280. struct ao2_iterator mem_iter;
  8281. if (argc != 2 && argc != 3) {
  8282. return CLI_SHOWUSAGE;
  8283. }
  8284. if (argc == 3) { /* specific queue */
  8285. if ((q = find_load_queue_rt_friendly(argv[2]))) {
  8286. queue_t_unref(q, "Done with temporary pointer");
  8287. }
  8288. } else if (ast_check_realtime("queues")) {
  8289. /* This block is to find any queues which are defined in realtime but
  8290. * which have not yet been added to the in-core container
  8291. */
  8292. struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
  8293. if (cfg) {
  8294. char *category = NULL;
  8295. while ((category = ast_category_browse(cfg, category))) {
  8296. const char *queuename = ast_variable_retrieve(cfg, category, "name");
  8297. if ((q = find_load_queue_rt_friendly(queuename))) {
  8298. queue_t_unref(q, "Done with temporary pointer");
  8299. }
  8300. }
  8301. ast_config_destroy(cfg);
  8302. }
  8303. }
  8304. ao2_lock(queues);
  8305. queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK);
  8306. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  8307. float sl;
  8308. struct call_queue *realtime_queue = NULL;
  8309. ao2_lock(q);
  8310. /* This check is to make sure we don't print information for realtime
  8311. * queues which have been deleted from realtime but which have not yet
  8312. * been deleted from the in-core container. Only do this if we're not
  8313. * looking for a specific queue.
  8314. */
  8315. if (argc < 3 && q->realtime) {
  8316. realtime_queue = find_load_queue_rt_friendly(q->name);
  8317. if (!realtime_queue) {
  8318. ao2_unlock(q);
  8319. queue_t_unref(q, "Done with iterator");
  8320. continue;
  8321. }
  8322. queue_t_unref(realtime_queue, "Queue is already in memory");
  8323. }
  8324. if (argc == 3 && strcasecmp(q->name, argv[2])) {
  8325. ao2_unlock(q);
  8326. queue_t_unref(q, "Done with iterator");
  8327. continue;
  8328. }
  8329. found = 1;
  8330. ast_str_set(&out, 0, "%s has %d calls (max ", q->name, q->count);
  8331. if (q->maxlen) {
  8332. ast_str_append(&out, 0, "%d", q->maxlen);
  8333. } else {
  8334. ast_str_append(&out, 0, "unlimited");
  8335. }
  8336. sl = 0;
  8337. if (q->callscompleted > 0) {
  8338. sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
  8339. }
  8340. ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime, %ds talktime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds",
  8341. int2strat(q->strategy), q->holdtime, q->talktime, q->weight,
  8342. q->callscompleted, q->callsabandoned,sl,q->servicelevel);
  8343. do_print(s, fd, ast_str_buffer(out));
  8344. if (!ao2_container_count(q->members)) {
  8345. do_print(s, fd, " No Members");
  8346. } else {
  8347. struct member *mem;
  8348. do_print(s, fd, " Members: ");
  8349. mem_iter = ao2_iterator_init(q->members, 0);
  8350. while ((mem = ao2_iterator_next(&mem_iter))) {
  8351. ast_str_set(&out, 0, " %s", mem->membername);
  8352. if (strcasecmp(mem->membername, mem->interface)) {
  8353. ast_str_append(&out, 0, " (%s", mem->interface);
  8354. if (!ast_strlen_zero(mem->state_interface)
  8355. && strcmp(mem->state_interface, mem->interface)) {
  8356. ast_str_append(&out, 0, " from %s", mem->state_interface);
  8357. }
  8358. ast_str_append(&out, 0, ")");
  8359. }
  8360. if (mem->penalty) {
  8361. ast_str_append(&out, 0, " with penalty %d", mem->penalty);
  8362. }
  8363. ast_str_append(&out, 0, " (ringinuse %s)", mem->ringinuse ? "enabled" : "disabled");
  8364. ast_str_append(&out, 0, "%s%s%s%s%s%s%s%s%s%s%s%s (%s%s%s)",
  8365. mem->dynamic ? ast_term_color(COLOR_CYAN, COLOR_BLACK) : "", mem->dynamic ? " (dynamic)" : "", ast_term_reset(),
  8366. mem->realtime ? ast_term_color(COLOR_MAGENTA, COLOR_BLACK) : "", mem->realtime ? " (realtime)" : "", ast_term_reset(),
  8367. mem->paused ? ast_term_color(COLOR_BROWN, COLOR_BLACK) : "", mem->paused ? " (paused)" : "", ast_term_reset(),
  8368. mem->starttime ? ast_term_color(COLOR_BROWN, COLOR_BLACK) : "", mem->starttime ? " (in call)" : "", ast_term_reset(),
  8369. ast_term_color(
  8370. mem->status == AST_DEVICE_UNAVAILABLE || mem->status == AST_DEVICE_UNKNOWN ?
  8371. COLOR_RED : COLOR_GREEN, COLOR_BLACK),
  8372. ast_devstate2str(mem->status), ast_term_reset());
  8373. if (mem->calls) {
  8374. ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
  8375. mem->calls, (long) (time(NULL) - mem->lastcall));
  8376. } else {
  8377. ast_str_append(&out, 0, " has taken no calls yet");
  8378. }
  8379. do_print(s, fd, ast_str_buffer(out));
  8380. ao2_ref(mem, -1);
  8381. }
  8382. ao2_iterator_destroy(&mem_iter);
  8383. }
  8384. if (!q->head) {
  8385. do_print(s, fd, " No Callers");
  8386. } else {
  8387. struct queue_ent *qe;
  8388. int pos = 1;
  8389. do_print(s, fd, " Callers: ");
  8390. for (qe = q->head; qe; qe = qe->next) {
  8391. ast_str_set(&out, 0, " %d. %s (wait: %ld:%2.2ld, prio: %d)",
  8392. pos++, ast_channel_name(qe->chan), (long) (now - qe->start) / 60,
  8393. (long) (now - qe->start) % 60, qe->prio);
  8394. do_print(s, fd, ast_str_buffer(out));
  8395. }
  8396. }
  8397. do_print(s, fd, ""); /* blank line between entries */
  8398. ao2_unlock(q);
  8399. queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */
  8400. }
  8401. ao2_iterator_destroy(&queue_iter);
  8402. ao2_unlock(queues);
  8403. if (!found) {
  8404. if (argc == 3) {
  8405. ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
  8406. } else {
  8407. ast_str_set(&out, 0, "No queues.");
  8408. }
  8409. do_print(s, fd, ast_str_buffer(out));
  8410. }
  8411. return CLI_SUCCESS;
  8412. }
  8413. /*!
  8414. * \brief Check if a given word is in a space-delimited list
  8415. *
  8416. * \param list Space delimited list of words
  8417. * \param word The word used to search the list
  8418. *
  8419. * \note This function will not return 1 if the word is at the very end of the
  8420. * list (followed immediately by a \0, not a space) since it is used for
  8421. * checking tab-completion and a word at the end is still being tab-completed.
  8422. *
  8423. * \return Returns 1 if the word is found
  8424. * \return Returns 0 if the word is not found
  8425. */
  8426. static int word_in_list(const char *list, const char *word) {
  8427. int list_len, word_len = strlen(word);
  8428. const char *find, *end_find, *end_list;
  8429. /* strip whitespace from front */
  8430. while(isspace(*list)) {
  8431. list++;
  8432. }
  8433. while((find = strstr(list, word))) {
  8434. /* beginning of find starts inside another word? */
  8435. if (find != list && *(find - 1) != ' ') {
  8436. list = find;
  8437. /* strip word from front */
  8438. while(!isspace(*list) && *list != '\0') {
  8439. list++;
  8440. }
  8441. /* strip whitespace from front */
  8442. while(isspace(*list)) {
  8443. list++;
  8444. }
  8445. continue;
  8446. }
  8447. /* end of find ends inside another word or at very end of list? */
  8448. list_len = strlen(list);
  8449. end_find = find + word_len;
  8450. end_list = list + list_len;
  8451. if (end_find == end_list || *end_find != ' ') {
  8452. list = find;
  8453. /* strip word from front */
  8454. while(!isspace(*list) && *list != '\0') {
  8455. list++;
  8456. }
  8457. /* strip whitespace from front */
  8458. while(isspace(*list)) {
  8459. list++;
  8460. }
  8461. continue;
  8462. }
  8463. /* terminating conditions satisfied, word at beginning or separated by ' ' */
  8464. return 1;
  8465. }
  8466. return 0;
  8467. }
  8468. /*!
  8469. * \brief Check if a given word is in a space-delimited list
  8470. *
  8471. * \param line The line as typed not including the current word being completed
  8472. * \param word The word currently being completed
  8473. * \param pos The number of completed words in line
  8474. * \param state The nth desired completion option
  8475. * \param word_list_offset Offset into the line where the list of queues begins. If non-zero, queues in the list will not be offered for further completion.
  8476. *
  8477. * \return Returns the queue tab-completion for the given word and state
  8478. */
  8479. static char *complete_queue(const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
  8480. {
  8481. struct call_queue *q;
  8482. char *ret = NULL;
  8483. int which = 0;
  8484. int wordlen = strlen(word);
  8485. struct ao2_iterator queue_iter;
  8486. const char *word_list = NULL;
  8487. /* for certain commands, already completed items should be left out of
  8488. * the list */
  8489. if (word_list_offset && strlen(line) >= word_list_offset) {
  8490. word_list = line + word_list_offset;
  8491. }
  8492. queue_iter = ao2_iterator_init(queues, 0);
  8493. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  8494. if (!strncasecmp(word, q->name, wordlen) && ++which > state
  8495. && (!word_list_offset || !word_in_list(word_list, q->name))) {
  8496. ret = ast_strdup(q->name);
  8497. queue_t_unref(q, "Done with iterator");
  8498. break;
  8499. }
  8500. queue_t_unref(q, "Done with iterator");
  8501. }
  8502. ao2_iterator_destroy(&queue_iter);
  8503. /* Pretend "rules" is at the end of the queues list in certain
  8504. * circumstances since it is an alternate command that should be
  8505. * tab-completable for "queue show" */
  8506. if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
  8507. ret = ast_strdup("rules");
  8508. }
  8509. return ret;
  8510. }
  8511. static char *complete_queue_show(const char *line, const char *word, int pos, int state)
  8512. {
  8513. if (pos == 2) {
  8514. return complete_queue(line, word, pos, state, 0);
  8515. }
  8516. return NULL;
  8517. }
  8518. static char *queue_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  8519. {
  8520. switch ( cmd ) {
  8521. case CLI_INIT:
  8522. e->command = "queue show";
  8523. e->usage =
  8524. "Usage: queue show\n"
  8525. " Provides summary information on a specified queue.\n";
  8526. return NULL;
  8527. case CLI_GENERATE:
  8528. return complete_queue_show(a->line, a->word, a->pos, a->n);
  8529. }
  8530. return __queues_show(NULL, a->fd, a->argc, a->argv);
  8531. }
  8532. /*!\brief callback to display queues status in manager
  8533. \addtogroup Group_AMI
  8534. */
  8535. static int manager_queues_show(struct mansession *s, const struct message *m)
  8536. {
  8537. static const char * const a[] = { "queue", "show" };
  8538. __queues_show(s, -1, 2, a);
  8539. astman_append(s, "\r\n\r\n"); /* Properly terminate Manager output */
  8540. return RESULT_SUCCESS;
  8541. }
  8542. static int manager_queue_rule_show(struct mansession *s, const struct message *m)
  8543. {
  8544. const char *rule = astman_get_header(m, "Rule");
  8545. const char *id = astman_get_header(m, "ActionID");
  8546. struct rule_list *rl_iter;
  8547. struct penalty_rule *pr_iter;
  8548. astman_append(s, "Response: Success\r\n");
  8549. if (!ast_strlen_zero(id)) {
  8550. astman_append(s, "ActionID: %s\r\n", id);
  8551. }
  8552. AST_LIST_LOCK(&rule_lists);
  8553. AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
  8554. if (ast_strlen_zero(rule) || !strcasecmp(rule, rl_iter->name)) {
  8555. astman_append(s, "RuleList: %s\r\n", rl_iter->name);
  8556. AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
  8557. astman_append(s, "Rule: %d,%s%d,%s%d\r\n", pr_iter->time, pr_iter->max_relative && pr_iter->max_value >= 0 ? "+" : "", pr_iter->max_value, pr_iter->min_relative && pr_iter->min_value >= 0 ? "+" : "", pr_iter->min_value );
  8558. }
  8559. if (!ast_strlen_zero(rule)) {
  8560. break;
  8561. }
  8562. }
  8563. }
  8564. AST_LIST_UNLOCK(&rule_lists);
  8565. /*
  8566. * Two blank lines instead of one because the Response and
  8567. * ActionID headers used to not be present.
  8568. */
  8569. astman_append(s, "\r\n\r\n");
  8570. return RESULT_SUCCESS;
  8571. }
  8572. /*! \brief Summary of queue info via the AMI */
  8573. static int manager_queues_summary(struct mansession *s, const struct message *m)
  8574. {
  8575. time_t now;
  8576. int qmemcount = 0;
  8577. int qmemavail = 0;
  8578. int qchancount = 0;
  8579. int qlongestholdtime = 0;
  8580. int qsummaries = 0;
  8581. const char *id = astman_get_header(m, "ActionID");
  8582. const char *queuefilter = astman_get_header(m, "Queue");
  8583. char idText[256];
  8584. struct call_queue *q;
  8585. struct queue_ent *qe;
  8586. struct member *mem;
  8587. struct ao2_iterator queue_iter;
  8588. struct ao2_iterator mem_iter;
  8589. astman_send_listack(s, m, "Queue summary will follow", "start");
  8590. time(&now);
  8591. idText[0] = '\0';
  8592. if (!ast_strlen_zero(id)) {
  8593. snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
  8594. }
  8595. queue_iter = ao2_iterator_init(queues, 0);
  8596. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  8597. ao2_lock(q);
  8598. /* List queue properties */
  8599. if (ast_strlen_zero(queuefilter) || !strcasecmp(q->name, queuefilter)) {
  8600. /* Reset the necessary local variables if no queuefilter is set*/
  8601. qmemcount = 0;
  8602. qmemavail = 0;
  8603. qchancount = 0;
  8604. qlongestholdtime = 0;
  8605. /* List Queue Members */
  8606. mem_iter = ao2_iterator_init(q->members, 0);
  8607. while ((mem = ao2_iterator_next(&mem_iter))) {
  8608. if ((mem->status != AST_DEVICE_UNAVAILABLE) && (mem->status != AST_DEVICE_INVALID)) {
  8609. ++qmemcount;
  8610. if (member_status_available(mem->status) && !mem->paused) {
  8611. ++qmemavail;
  8612. }
  8613. }
  8614. ao2_ref(mem, -1);
  8615. }
  8616. ao2_iterator_destroy(&mem_iter);
  8617. for (qe = q->head; qe; qe = qe->next) {
  8618. if ((now - qe->start) > qlongestholdtime) {
  8619. qlongestholdtime = now - qe->start;
  8620. }
  8621. ++qchancount;
  8622. }
  8623. astman_append(s, "Event: QueueSummary\r\n"
  8624. "Queue: %s\r\n"
  8625. "LoggedIn: %d\r\n"
  8626. "Available: %d\r\n"
  8627. "Callers: %d\r\n"
  8628. "HoldTime: %d\r\n"
  8629. "TalkTime: %d\r\n"
  8630. "LongestHoldTime: %d\r\n"
  8631. "%s"
  8632. "\r\n",
  8633. q->name, qmemcount, qmemavail, qchancount, q->holdtime, q->talktime, qlongestholdtime, idText);
  8634. ++qsummaries;
  8635. }
  8636. ao2_unlock(q);
  8637. queue_t_unref(q, "Done with iterator");
  8638. }
  8639. ao2_iterator_destroy(&queue_iter);
  8640. astman_send_list_complete_start(s, m, "QueueSummaryComplete", qsummaries);
  8641. astman_send_list_complete_end(s);
  8642. return RESULT_SUCCESS;
  8643. }
  8644. /*! \brief Queue status info via AMI */
  8645. static int manager_queues_status(struct mansession *s, const struct message *m)
  8646. {
  8647. time_t now;
  8648. int pos;
  8649. int q_items = 0;
  8650. const char *id = astman_get_header(m,"ActionID");
  8651. const char *queuefilter = astman_get_header(m,"Queue");
  8652. const char *memberfilter = astman_get_header(m,"Member");
  8653. char idText[256];
  8654. struct call_queue *q;
  8655. struct queue_ent *qe;
  8656. float sl = 0;
  8657. struct member *mem;
  8658. struct ao2_iterator queue_iter;
  8659. struct ao2_iterator mem_iter;
  8660. astman_send_listack(s, m, "Queue status will follow", "start");
  8661. time(&now);
  8662. idText[0] = '\0';
  8663. if (!ast_strlen_zero(id)) {
  8664. snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
  8665. }
  8666. queue_iter = ao2_iterator_init(queues, 0);
  8667. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  8668. ao2_lock(q);
  8669. /* List queue properties */
  8670. if (ast_strlen_zero(queuefilter) || !strcasecmp(q->name, queuefilter)) {
  8671. sl = ((q->callscompleted > 0) ? 100 * ((float)q->callscompletedinsl / (float)q->callscompleted) : 0);
  8672. astman_append(s, "Event: QueueParams\r\n"
  8673. "Queue: %s\r\n"
  8674. "Max: %d\r\n"
  8675. "Strategy: %s\r\n"
  8676. "Calls: %d\r\n"
  8677. "Holdtime: %d\r\n"
  8678. "TalkTime: %d\r\n"
  8679. "Completed: %d\r\n"
  8680. "Abandoned: %d\r\n"
  8681. "ServiceLevel: %d\r\n"
  8682. "ServicelevelPerf: %2.1f\r\n"
  8683. "Weight: %d\r\n"
  8684. "%s"
  8685. "\r\n",
  8686. q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted,
  8687. q->callsabandoned, q->servicelevel, sl, q->weight, idText);
  8688. ++q_items;
  8689. /* List Queue Members */
  8690. mem_iter = ao2_iterator_init(q->members, 0);
  8691. while ((mem = ao2_iterator_next(&mem_iter))) {
  8692. if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter) || !strcmp(mem->membername, memberfilter)) {
  8693. astman_append(s, "Event: QueueMember\r\n"
  8694. "Queue: %s\r\n"
  8695. "Name: %s\r\n"
  8696. "Location: %s\r\n"
  8697. "StateInterface: %s\r\n"
  8698. "Membership: %s\r\n"
  8699. "Penalty: %d\r\n"
  8700. "CallsTaken: %d\r\n"
  8701. "LastCall: %d\r\n"
  8702. "InCall: %d\r\n"
  8703. "Status: %d\r\n"
  8704. "Paused: %d\r\n"
  8705. "PausedReason: %s\r\n"
  8706. "%s"
  8707. "\r\n",
  8708. q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
  8709. mem->penalty, mem->calls, (int)mem->lastcall, mem->starttime ? 1 : 0, mem->status,
  8710. mem->paused, mem->reason_paused, idText);
  8711. ++q_items;
  8712. }
  8713. ao2_ref(mem, -1);
  8714. }
  8715. ao2_iterator_destroy(&mem_iter);
  8716. /* List Queue Entries */
  8717. pos = 1;
  8718. for (qe = q->head; qe; qe = qe->next) {
  8719. astman_append(s, "Event: QueueEntry\r\n"
  8720. "Queue: %s\r\n"
  8721. "Position: %d\r\n"
  8722. "Channel: %s\r\n"
  8723. "Uniqueid: %s\r\n"
  8724. "CallerIDNum: %s\r\n"
  8725. "CallerIDName: %s\r\n"
  8726. "ConnectedLineNum: %s\r\n"
  8727. "ConnectedLineName: %s\r\n"
  8728. "Wait: %ld\r\n"
  8729. "Priority: %d\r\n"
  8730. "%s"
  8731. "\r\n",
  8732. q->name, pos++, ast_channel_name(qe->chan), ast_channel_uniqueid(qe->chan),
  8733. S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
  8734. S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
  8735. S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
  8736. S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
  8737. (long) (now - qe->start), qe->prio, idText);
  8738. ++q_items;
  8739. }
  8740. }
  8741. ao2_unlock(q);
  8742. queue_t_unref(q, "Done with iterator");
  8743. }
  8744. ao2_iterator_destroy(&queue_iter);
  8745. astman_send_list_complete_start(s, m, "QueueStatusComplete", q_items);
  8746. astman_send_list_complete_end(s);
  8747. return RESULT_SUCCESS;
  8748. }
  8749. static int manager_add_queue_member(struct mansession *s, const struct message *m)
  8750. {
  8751. const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface;
  8752. int paused, penalty = 0;
  8753. queuename = astman_get_header(m, "Queue");
  8754. interface = astman_get_header(m, "Interface");
  8755. penalty_s = astman_get_header(m, "Penalty");
  8756. paused_s = astman_get_header(m, "Paused");
  8757. membername = astman_get_header(m, "MemberName");
  8758. state_interface = astman_get_header(m, "StateInterface");
  8759. if (ast_strlen_zero(queuename)) {
  8760. astman_send_error(s, m, "'Queue' not specified.");
  8761. return 0;
  8762. }
  8763. if (ast_strlen_zero(interface)) {
  8764. astman_send_error(s, m, "'Interface' not specified.");
  8765. return 0;
  8766. }
  8767. if (ast_strlen_zero(penalty_s)) {
  8768. penalty = 0;
  8769. } else if (sscanf(penalty_s, "%30d", &penalty) != 1 || penalty < 0) {
  8770. penalty = 0;
  8771. }
  8772. if (ast_strlen_zero(paused_s)) {
  8773. paused = 0;
  8774. } else {
  8775. paused = abs(ast_true(paused_s));
  8776. }
  8777. switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
  8778. case RES_OKAY:
  8779. if (ast_strlen_zero(membername) || !log_membername_as_agent) {
  8780. ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
  8781. } else {
  8782. ast_queue_log(queuename, "MANAGER", membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
  8783. }
  8784. astman_send_ack(s, m, "Added interface to queue");
  8785. break;
  8786. case RES_EXISTS:
  8787. astman_send_error(s, m, "Unable to add interface: Already there");
  8788. break;
  8789. case RES_NOSUCHQUEUE:
  8790. astman_send_error(s, m, "Unable to add interface to queue: No such queue");
  8791. break;
  8792. case RES_OUTOFMEMORY:
  8793. astman_send_error(s, m, "Out of memory");
  8794. break;
  8795. }
  8796. return 0;
  8797. }
  8798. static int manager_remove_queue_member(struct mansession *s, const struct message *m)
  8799. {
  8800. const char *queuename, *interface;
  8801. struct member *mem = NULL;
  8802. queuename = astman_get_header(m, "Queue");
  8803. interface = astman_get_header(m, "Interface");
  8804. if (ast_strlen_zero(queuename) || ast_strlen_zero(interface)) {
  8805. astman_send_error(s, m, "Need 'Queue' and 'Interface' parameters.");
  8806. return 0;
  8807. }
  8808. if (log_membername_as_agent) {
  8809. mem = find_member_by_queuename_and_interface(queuename, interface);
  8810. }
  8811. switch (remove_from_queue(queuename, interface)) {
  8812. case RES_OKAY:
  8813. if (!mem || ast_strlen_zero(mem->membername)) {
  8814. ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
  8815. } else {
  8816. ast_queue_log(queuename, "MANAGER", mem->membername, "REMOVEMEMBER", "%s", "");
  8817. }
  8818. astman_send_ack(s, m, "Removed interface from queue");
  8819. break;
  8820. case RES_EXISTS:
  8821. astman_send_error(s, m, "Unable to remove interface: Not there");
  8822. break;
  8823. case RES_NOSUCHQUEUE:
  8824. astman_send_error(s, m, "Unable to remove interface from queue: No such queue");
  8825. break;
  8826. case RES_OUTOFMEMORY:
  8827. astman_send_error(s, m, "Out of memory");
  8828. break;
  8829. case RES_NOT_DYNAMIC:
  8830. astman_send_error(s, m, "Member not dynamic");
  8831. break;
  8832. }
  8833. if (mem) {
  8834. ao2_ref(mem, -1);
  8835. }
  8836. return 0;
  8837. }
  8838. static int manager_pause_queue_member(struct mansession *s, const struct message *m)
  8839. {
  8840. const char *queuename, *interface, *paused_s, *reason;
  8841. int paused;
  8842. interface = astman_get_header(m, "Interface");
  8843. paused_s = astman_get_header(m, "Paused");
  8844. queuename = astman_get_header(m, "Queue"); /* Optional - if not supplied, pause the given Interface in all queues */
  8845. reason = astman_get_header(m, "Reason"); /* Optional */
  8846. if (ast_strlen_zero(interface) || ast_strlen_zero(paused_s)) {
  8847. astman_send_error(s, m, "Need 'Interface' and 'Paused' parameters.");
  8848. return 0;
  8849. }
  8850. paused = abs(ast_true(paused_s));
  8851. if (set_member_paused(queuename, interface, reason, paused)) {
  8852. astman_send_error(s, m, "Interface not found");
  8853. } else {
  8854. astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
  8855. }
  8856. return 0;
  8857. }
  8858. static int manager_queue_log_custom(struct mansession *s, const struct message *m)
  8859. {
  8860. const char *queuename, *event, *message, *interface, *uniqueid;
  8861. queuename = astman_get_header(m, "Queue");
  8862. uniqueid = astman_get_header(m, "UniqueId");
  8863. interface = astman_get_header(m, "Interface");
  8864. event = astman_get_header(m, "Event");
  8865. message = astman_get_header(m, "Message");
  8866. if (ast_strlen_zero(queuename) || ast_strlen_zero(event)) {
  8867. astman_send_error(s, m, "Need 'Queue' and 'Event' parameters.");
  8868. return 0;
  8869. }
  8870. ast_queue_log(queuename, S_OR(uniqueid, "NONE"), interface, event, "%s", message);
  8871. astman_send_ack(s, m, "Event added successfully");
  8872. return 0;
  8873. }
  8874. static int manager_queue_reload(struct mansession *s, const struct message *m)
  8875. {
  8876. struct ast_flags mask = {0,};
  8877. const char *queuename = NULL;
  8878. int header_found = 0;
  8879. queuename = astman_get_header(m, "Queue");
  8880. if (!strcasecmp(S_OR(astman_get_header(m, "Members"), ""), "yes")) {
  8881. ast_set_flag(&mask, QUEUE_RELOAD_MEMBER);
  8882. header_found = 1;
  8883. }
  8884. if (!strcasecmp(S_OR(astman_get_header(m, "Rules"), ""), "yes")) {
  8885. ast_set_flag(&mask, QUEUE_RELOAD_RULES);
  8886. header_found = 1;
  8887. }
  8888. if (!strcasecmp(S_OR(astman_get_header(m, "Parameters"), ""), "yes")) {
  8889. ast_set_flag(&mask, QUEUE_RELOAD_PARAMETERS);
  8890. header_found = 1;
  8891. }
  8892. if (!header_found) {
  8893. ast_set_flag(&mask, AST_FLAGS_ALL);
  8894. }
  8895. if (!reload_handler(1, &mask, queuename)) {
  8896. astman_send_ack(s, m, "Queue reloaded successfully");
  8897. } else {
  8898. astman_send_error(s, m, "Error encountered while reloading queue");
  8899. }
  8900. return 0;
  8901. }
  8902. static int manager_queue_reset(struct mansession *s, const struct message *m)
  8903. {
  8904. const char *queuename = NULL;
  8905. struct ast_flags mask = {QUEUE_RESET_STATS,};
  8906. queuename = astman_get_header(m, "Queue");
  8907. if (!reload_handler(1, &mask, queuename)) {
  8908. astman_send_ack(s, m, "Queue stats reset successfully");
  8909. } else {
  8910. astman_send_error(s, m, "Error encountered while resetting queue stats");
  8911. }
  8912. return 0;
  8913. }
  8914. static char *complete_queue_add_member(const char *line, const char *word, int pos, int state)
  8915. {
  8916. /* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
  8917. switch (pos) {
  8918. case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
  8919. return NULL;
  8920. case 4: /* only one possible match, "to" */
  8921. return state == 0 ? ast_strdup("to") : NULL;
  8922. case 5: /* <queue> */
  8923. return complete_queue(line, word, pos, state, 0);
  8924. case 6: /* only one possible match, "penalty" */
  8925. return state == 0 ? ast_strdup("penalty") : NULL;
  8926. case 7:
  8927. if (0 <= state && state < 100) { /* 0-99 */
  8928. char *num;
  8929. if ((num = ast_malloc(3))) {
  8930. sprintf(num, "%d", state);
  8931. }
  8932. return num;
  8933. } else {
  8934. return NULL;
  8935. }
  8936. case 8: /* only one possible match, "as" */
  8937. return state == 0 ? ast_strdup("as") : NULL;
  8938. case 9: /* Don't attempt to complete name of member (infinite possibilities) */
  8939. return NULL;
  8940. default:
  8941. return NULL;
  8942. }
  8943. }
  8944. static int manager_queue_member_ringinuse(struct mansession *s, const struct message *m)
  8945. {
  8946. const char *queuename, *interface, *ringinuse_s;
  8947. int ringinuse;
  8948. interface = astman_get_header(m, "Interface");
  8949. ringinuse_s = astman_get_header(m, "RingInUse");
  8950. /* Optional - if not supplied, set the ringinuse value for the given Interface in all queues */
  8951. queuename = astman_get_header(m, "Queue");
  8952. if (ast_strlen_zero(interface) || ast_strlen_zero(ringinuse_s)) {
  8953. astman_send_error(s, m, "Need 'Interface' and 'RingInUse' parameters.");
  8954. return 0;
  8955. }
  8956. if (ast_true(ringinuse_s)) {
  8957. ringinuse = 1;
  8958. } else if (ast_false(ringinuse_s)) {
  8959. ringinuse = 0;
  8960. } else {
  8961. astman_send_error(s, m, "'RingInUse' parameter must be a truth value (yes/no, on/off, 0/1, etc)");
  8962. return 0;
  8963. }
  8964. if (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
  8965. astman_send_error(s, m, "Invalid interface, queuename, or ringinuse value\n");
  8966. } else {
  8967. astman_send_ack(s, m, "Interface ringinuse set successfully");
  8968. }
  8969. return 0;
  8970. }
  8971. static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
  8972. {
  8973. const char *queuename, *interface, *penalty_s;
  8974. int penalty;
  8975. interface = astman_get_header(m, "Interface");
  8976. penalty_s = astman_get_header(m, "Penalty");
  8977. /* Optional - if not supplied, set the penalty value for the given Interface in all queues */
  8978. queuename = astman_get_header(m, "Queue");
  8979. if (ast_strlen_zero(interface) || ast_strlen_zero(penalty_s)) {
  8980. astman_send_error(s, m, "Need 'Interface' and 'Penalty' parameters.");
  8981. return 0;
  8982. }
  8983. penalty = atoi(penalty_s);
  8984. if (set_member_value((char *)queuename, (char *)interface, MEMBER_PENALTY, penalty)) {
  8985. astman_send_error(s, m, "Invalid interface, queuename or penalty");
  8986. } else {
  8987. astman_send_ack(s, m, "Interface penalty set successfully");
  8988. }
  8989. return 0;
  8990. }
  8991. static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  8992. {
  8993. const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
  8994. int penalty;
  8995. switch ( cmd ) {
  8996. case CLI_INIT:
  8997. e->command = "queue add member";
  8998. e->usage =
  8999. "Usage: queue add member <dial string> to <queue> [[[penalty <penalty>] as <membername>] state_interface <interface>]\n"
  9000. " Add a dial string (Such as a channel,e.g. SIP/6001) to a queue with optionally: a penalty, membername and a state_interface\n";
  9001. return NULL;
  9002. case CLI_GENERATE:
  9003. return complete_queue_add_member(a->line, a->word, a->pos, a->n);
  9004. }
  9005. if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
  9006. return CLI_SHOWUSAGE;
  9007. } else if (strcmp(a->argv[4], "to")) {
  9008. return CLI_SHOWUSAGE;
  9009. } else if ((a->argc >= 8) && strcmp(a->argv[6], "penalty")) {
  9010. return CLI_SHOWUSAGE;
  9011. } else if ((a->argc >= 10) && strcmp(a->argv[8], "as")) {
  9012. return CLI_SHOWUSAGE;
  9013. } else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
  9014. return CLI_SHOWUSAGE;
  9015. }
  9016. queuename = a->argv[5];
  9017. interface = a->argv[3];
  9018. if (a->argc >= 8) {
  9019. if (sscanf(a->argv[7], "%30d", &penalty) == 1) {
  9020. if (penalty < 0) {
  9021. ast_cli(a->fd, "Penalty must be >= 0\n");
  9022. penalty = 0;
  9023. }
  9024. } else {
  9025. ast_cli(a->fd, "Penalty must be an integer >= 0\n");
  9026. penalty = 0;
  9027. }
  9028. } else {
  9029. penalty = 0;
  9030. }
  9031. if (a->argc >= 10) {
  9032. membername = a->argv[9];
  9033. }
  9034. if (a->argc >= 12) {
  9035. state_interface = a->argv[11];
  9036. }
  9037. switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
  9038. case RES_OKAY:
  9039. if (ast_strlen_zero(membername) || !log_membername_as_agent) {
  9040. ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
  9041. } else {
  9042. ast_queue_log(queuename, "CLI", membername, "ADDMEMBER", "%s", "");
  9043. }
  9044. ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
  9045. return CLI_SUCCESS;
  9046. case RES_EXISTS:
  9047. ast_cli(a->fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
  9048. return CLI_FAILURE;
  9049. case RES_NOSUCHQUEUE:
  9050. ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
  9051. return CLI_FAILURE;
  9052. case RES_OUTOFMEMORY:
  9053. ast_cli(a->fd, "Out of memory\n");
  9054. return CLI_FAILURE;
  9055. case RES_NOT_DYNAMIC:
  9056. ast_cli(a->fd, "Member not dynamic\n");
  9057. return CLI_FAILURE;
  9058. default:
  9059. return CLI_FAILURE;
  9060. }
  9061. }
  9062. static char *complete_queue_remove_member(const char *line, const char *word, int pos, int state)
  9063. {
  9064. int which = 0;
  9065. struct call_queue *q;
  9066. struct member *m;
  9067. struct ao2_iterator queue_iter;
  9068. struct ao2_iterator mem_iter;
  9069. int wordlen = strlen(word);
  9070. /* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
  9071. if (pos > 5 || pos < 3) {
  9072. return NULL;
  9073. }
  9074. if (pos == 4) { /* only one possible match, 'from' */
  9075. return (state == 0 ? ast_strdup("from") : NULL);
  9076. }
  9077. if (pos == 5) { /* No need to duplicate code */
  9078. return complete_queue(line, word, pos, state, 0);
  9079. }
  9080. /* here is the case for 3, <member> */
  9081. queue_iter = ao2_iterator_init(queues, 0);
  9082. while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
  9083. ao2_lock(q);
  9084. mem_iter = ao2_iterator_init(q->members, 0);
  9085. while ((m = ao2_iterator_next(&mem_iter))) {
  9086. if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
  9087. char *tmp;
  9088. tmp = ast_strdup(m->interface);
  9089. ao2_ref(m, -1);
  9090. ao2_iterator_destroy(&mem_iter);
  9091. ao2_unlock(q);
  9092. queue_t_unref(q, "Done with iterator, returning interface name");
  9093. ao2_iterator_destroy(&queue_iter);
  9094. return tmp;
  9095. }
  9096. ao2_ref(m, -1);
  9097. }
  9098. ao2_iterator_destroy(&mem_iter);
  9099. ao2_unlock(q);
  9100. queue_t_unref(q, "Done with iterator");
  9101. }
  9102. ao2_iterator_destroy(&queue_iter);
  9103. return NULL;
  9104. }
  9105. static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  9106. {
  9107. const char *queuename, *interface;
  9108. struct member *mem = NULL;
  9109. char *res = CLI_FAILURE;
  9110. switch (cmd) {
  9111. case CLI_INIT:
  9112. e->command = "queue remove member";
  9113. e->usage =
  9114. "Usage: queue remove member <channel> from <queue>\n"
  9115. " Remove a specific channel from a queue.\n";
  9116. return NULL;
  9117. case CLI_GENERATE:
  9118. return complete_queue_remove_member(a->line, a->word, a->pos, a->n);
  9119. }
  9120. if (a->argc != 6) {
  9121. return CLI_SHOWUSAGE;
  9122. } else if (strcmp(a->argv[4], "from")) {
  9123. return CLI_SHOWUSAGE;
  9124. }
  9125. queuename = a->argv[5];
  9126. interface = a->argv[3];
  9127. if (log_membername_as_agent) {
  9128. mem = find_member_by_queuename_and_interface(queuename, interface);
  9129. }
  9130. switch (remove_from_queue(queuename, interface)) {
  9131. case RES_OKAY:
  9132. if (!mem || ast_strlen_zero(mem->membername)) {
  9133. ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
  9134. } else {
  9135. ast_queue_log(queuename, "CLI", mem->membername, "REMOVEMEMBER", "%s", "");
  9136. }
  9137. ast_cli(a->fd, "Removed interface %s from queue '%s'\n", interface, queuename);
  9138. res = CLI_SUCCESS;
  9139. break;
  9140. case RES_EXISTS:
  9141. ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
  9142. break;
  9143. case RES_NOSUCHQUEUE:
  9144. ast_cli(a->fd, "Unable to remove interface from queue '%s': No such queue\n", queuename);
  9145. break;
  9146. case RES_OUTOFMEMORY:
  9147. ast_cli(a->fd, "Out of memory\n");
  9148. break;
  9149. case RES_NOT_DYNAMIC:
  9150. ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Member is not dynamic\n", interface, queuename);
  9151. break;
  9152. }
  9153. if (mem) {
  9154. ao2_ref(mem, -1);
  9155. }
  9156. return res;
  9157. }
  9158. static char *complete_queue_pause_member(const char *line, const char *word, int pos, int state)
  9159. {
  9160. /* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
  9161. switch (pos) {
  9162. case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
  9163. return NULL;
  9164. case 4: /* only one possible match, "queue" */
  9165. return state == 0 ? ast_strdup("queue") : NULL;
  9166. case 5: /* <queue> */
  9167. return complete_queue(line, word, pos, state, 0);
  9168. case 6: /* "reason" */
  9169. return state == 0 ? ast_strdup("reason") : NULL;
  9170. case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
  9171. return NULL;
  9172. default:
  9173. return NULL;
  9174. }
  9175. }
  9176. static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  9177. {
  9178. const char *queuename, *interface, *reason;
  9179. int paused;
  9180. switch (cmd) {
  9181. case CLI_INIT:
  9182. e->command = "queue {pause|unpause} member";
  9183. e->usage =
  9184. "Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
  9185. " Pause or unpause a queue member. Not specifying a particular queue\n"
  9186. " will pause or unpause a member across all queues to which the member\n"
  9187. " belongs.\n";
  9188. return NULL;
  9189. case CLI_GENERATE:
  9190. return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
  9191. }
  9192. if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
  9193. return CLI_SHOWUSAGE;
  9194. } else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
  9195. return CLI_SHOWUSAGE;
  9196. } else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
  9197. return CLI_SHOWUSAGE;
  9198. }
  9199. interface = a->argv[3];
  9200. queuename = a->argc >= 6 ? a->argv[5] : NULL;
  9201. reason = a->argc == 8 ? a->argv[7] : NULL;
  9202. paused = !strcasecmp(a->argv[1], "pause");
  9203. if (set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
  9204. ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
  9205. if (!ast_strlen_zero(queuename)) {
  9206. ast_cli(a->fd, " in queue '%s'", queuename);
  9207. }
  9208. if (!ast_strlen_zero(reason)) {
  9209. ast_cli(a->fd, " for reason '%s'", reason);
  9210. }
  9211. ast_cli(a->fd, "\n");
  9212. return CLI_SUCCESS;
  9213. } else {
  9214. ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
  9215. if (!ast_strlen_zero(queuename)) {
  9216. ast_cli(a->fd, " in queue '%s'", queuename);
  9217. }
  9218. if (!ast_strlen_zero(reason)) {
  9219. ast_cli(a->fd, " for reason '%s'", reason);
  9220. }
  9221. ast_cli(a->fd, "\n");
  9222. return CLI_FAILURE;
  9223. }
  9224. }
  9225. static char *complete_queue_set_member_value(const char *line, const char *word, int pos, int state)
  9226. {
  9227. /* 0 - queue; 1 - set; 2 - penalty/ringinuse; 3 - <value>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
  9228. switch (pos) {
  9229. case 4:
  9230. if (state == 0) {
  9231. return ast_strdup("on");
  9232. } else {
  9233. return NULL;
  9234. }
  9235. case 6:
  9236. if (state == 0) {
  9237. return ast_strdup("in");
  9238. } else {
  9239. return NULL;
  9240. }
  9241. case 7:
  9242. return complete_queue(line, word, pos, state, 0);
  9243. default:
  9244. return NULL;
  9245. }
  9246. }
  9247. static char *handle_queue_set_member_ringinuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  9248. {
  9249. const char *queuename = NULL, *interface;
  9250. int ringinuse;
  9251. switch (cmd) {
  9252. case CLI_INIT:
  9253. e->command = "queue set ringinuse";
  9254. e->usage =
  9255. "Usage: queue set ringinuse <yes/no> on <interface> [in <queue>]\n"
  9256. " Set a member's ringinuse in the queue specified. If no queue is specified\n"
  9257. " then that interface's penalty is set in all queues to which that interface is a member.\n";
  9258. break;
  9259. return NULL;
  9260. case CLI_GENERATE:
  9261. return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
  9262. }
  9263. /* Sensible argument counts */
  9264. if (a->argc != 6 && a->argc != 8) {
  9265. return CLI_SHOWUSAGE;
  9266. }
  9267. /* Uses proper indicational words */
  9268. if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
  9269. return CLI_SHOWUSAGE;
  9270. }
  9271. /* Set the queue name if applicale */
  9272. if (a->argc == 8) {
  9273. queuename = a->argv[7];
  9274. }
  9275. /* Interface being set */
  9276. interface = a->argv[5];
  9277. /* Check and set the ringinuse value */
  9278. if (ast_true(a->argv[3])) {
  9279. ringinuse = 1;
  9280. } else if (ast_false(a->argv[3])) {
  9281. ringinuse = 0;
  9282. } else {
  9283. return CLI_SHOWUSAGE;
  9284. }
  9285. switch (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
  9286. case RESULT_SUCCESS:
  9287. ast_cli(a->fd, "Set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
  9288. return CLI_SUCCESS;
  9289. case RESULT_FAILURE:
  9290. ast_cli(a->fd, "Failed to set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
  9291. return CLI_FAILURE;
  9292. default:
  9293. return CLI_FAILURE;
  9294. }
  9295. }
  9296. static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  9297. {
  9298. const char *queuename = NULL, *interface;
  9299. int penalty = 0;
  9300. switch (cmd) {
  9301. case CLI_INIT:
  9302. e->command = "queue set penalty";
  9303. e->usage =
  9304. "Usage: queue set penalty <penalty> on <interface> [in <queue>]\n"
  9305. " Set a member's penalty in the queue specified. If no queue is specified\n"
  9306. " then that interface's penalty is set in all queues to which that interface is a member\n";
  9307. return NULL;
  9308. case CLI_GENERATE:
  9309. return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
  9310. }
  9311. if (a->argc != 6 && a->argc != 8) {
  9312. return CLI_SHOWUSAGE;
  9313. } else if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
  9314. return CLI_SHOWUSAGE;
  9315. }
  9316. if (a->argc == 8) {
  9317. queuename = a->argv[7];
  9318. }
  9319. interface = a->argv[5];
  9320. penalty = atoi(a->argv[3]);
  9321. switch (set_member_value(queuename, interface, MEMBER_PENALTY, penalty)) {
  9322. case RESULT_SUCCESS:
  9323. ast_cli(a->fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
  9324. return CLI_SUCCESS;
  9325. case RESULT_FAILURE:
  9326. ast_cli(a->fd, "Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename);
  9327. return CLI_FAILURE;
  9328. default:
  9329. return CLI_FAILURE;
  9330. }
  9331. }
  9332. static char *complete_queue_rule_show(const char *line, const char *word, int pos, int state)
  9333. {
  9334. int which = 0;
  9335. struct rule_list *rl_iter;
  9336. int wordlen = strlen(word);
  9337. char *ret = NULL;
  9338. if (pos != 3) /* Wha? */ {
  9339. return NULL;
  9340. }
  9341. AST_LIST_LOCK(&rule_lists);
  9342. AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
  9343. if (!strncasecmp(word, rl_iter->name, wordlen) && ++which > state) {
  9344. ret = ast_strdup(rl_iter->name);
  9345. break;
  9346. }
  9347. }
  9348. AST_LIST_UNLOCK(&rule_lists);
  9349. return ret;
  9350. }
  9351. static char *handle_queue_rule_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  9352. {
  9353. const char *rule;
  9354. struct rule_list *rl_iter;
  9355. struct penalty_rule *pr_iter;
  9356. switch (cmd) {
  9357. case CLI_INIT:
  9358. e->command = "queue show rules";
  9359. e->usage =
  9360. "Usage: queue show rules [rulename]\n"
  9361. " Show the list of rules associated with rulename. If no\n"
  9362. " rulename is specified, list all rules defined in queuerules.conf\n";
  9363. return NULL;
  9364. case CLI_GENERATE:
  9365. return complete_queue_rule_show(a->line, a->word, a->pos, a->n);
  9366. }
  9367. if (a->argc != 3 && a->argc != 4) {
  9368. return CLI_SHOWUSAGE;
  9369. }
  9370. rule = a->argc == 4 ? a->argv[3] : "";
  9371. AST_LIST_LOCK(&rule_lists);
  9372. AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
  9373. if (ast_strlen_zero(rule) || !strcasecmp(rl_iter->name, rule)) {
  9374. ast_cli(a->fd, "Rule: %s\n", rl_iter->name);
  9375. AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
  9376. ast_cli(a->fd, "\tAfter %d seconds, adjust QUEUE_MAX_PENALTY %s %d and adjust QUEUE_MIN_PENALTY %s %d\n", pr_iter->time, pr_iter->max_relative ? "by" : "to", pr_iter->max_value, pr_iter->min_relative ? "by" : "to", pr_iter->min_value);
  9377. }
  9378. }
  9379. }
  9380. AST_LIST_UNLOCK(&rule_lists);
  9381. return CLI_SUCCESS;
  9382. }
  9383. static char *handle_queue_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  9384. {
  9385. struct ast_flags mask = {QUEUE_RESET_STATS,};
  9386. int i;
  9387. switch (cmd) {
  9388. case CLI_INIT:
  9389. e->command = "queue reset stats";
  9390. e->usage =
  9391. "Usage: queue reset stats [<queuenames>]\n"
  9392. "\n"
  9393. "Issuing this command will reset statistics for\n"
  9394. "<queuenames>, or for all queues if no queue is\n"
  9395. "specified.\n";
  9396. return NULL;
  9397. case CLI_GENERATE:
  9398. if (a->pos >= 3) {
  9399. return complete_queue(a->line, a->word, a->pos, a->n, 17);
  9400. } else {
  9401. return NULL;
  9402. }
  9403. }
  9404. if (a->argc < 3) {
  9405. return CLI_SHOWUSAGE;
  9406. }
  9407. if (a->argc == 3) {
  9408. reload_handler(1, &mask, NULL);
  9409. return CLI_SUCCESS;
  9410. }
  9411. for (i = 3; i < a->argc; ++i) {
  9412. reload_handler(1, &mask, a->argv[i]);
  9413. }
  9414. return CLI_SUCCESS;
  9415. }
  9416. static char *handle_queue_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  9417. {
  9418. struct ast_flags mask = {0,};
  9419. int i;
  9420. switch (cmd) {
  9421. case CLI_INIT:
  9422. e->command = "queue reload {parameters|members|rules|all}";
  9423. e->usage =
  9424. "Usage: queue reload {parameters|members|rules|all} [<queuenames>]\n"
  9425. "Reload queues. If <queuenames> are specified, only reload information pertaining\n"
  9426. "to <queuenames>. One of 'parameters,' 'members,' 'rules,' or 'all' must be\n"
  9427. "specified in order to know what information to reload. Below is an explanation\n"
  9428. "of each of these qualifiers.\n"
  9429. "\n"
  9430. "\t'members' - reload queue members from queues.conf\n"
  9431. "\t'parameters' - reload all queue options except for queue members\n"
  9432. "\t'rules' - reload the queuerules.conf file\n"
  9433. "\t'all' - reload queue rules, parameters, and members\n"
  9434. "\n"
  9435. "Note: the 'rules' qualifier here cannot actually be applied to a specific queue.\n"
  9436. "Use of the 'rules' qualifier causes queuerules.conf to be reloaded. Even if only\n"
  9437. "one queue is specified when using this command, reloading queue rules may cause\n"
  9438. "other queues to be affected\n";
  9439. return NULL;
  9440. case CLI_GENERATE:
  9441. if (a->pos >= 3) {
  9442. /* find the point at which the list of queue names starts */
  9443. const char *command_end = a->line + strlen("queue reload ");
  9444. command_end = strchr(command_end, ' ');
  9445. if (!command_end) {
  9446. command_end = a->line + strlen(a->line);
  9447. }
  9448. return complete_queue(a->line, a->word, a->pos, a->n, command_end - a->line);
  9449. } else {
  9450. return NULL;
  9451. }
  9452. }
  9453. if (a->argc < 3)
  9454. return CLI_SHOWUSAGE;
  9455. if (!strcasecmp(a->argv[2], "rules")) {
  9456. ast_set_flag(&mask, QUEUE_RELOAD_RULES);
  9457. } else if (!strcasecmp(a->argv[2], "members")) {
  9458. ast_set_flag(&mask, QUEUE_RELOAD_MEMBER);
  9459. } else if (!strcasecmp(a->argv[2], "parameters")) {
  9460. ast_set_flag(&mask, QUEUE_RELOAD_PARAMETERS);
  9461. } else if (!strcasecmp(a->argv[2], "all")) {
  9462. ast_set_flag(&mask, AST_FLAGS_ALL);
  9463. }
  9464. if (a->argc == 3) {
  9465. reload_handler(1, &mask, NULL);
  9466. return CLI_SUCCESS;
  9467. }
  9468. for (i = 3; i < a->argc; ++i) {
  9469. reload_handler(1, &mask, a->argv[i]);
  9470. }
  9471. return CLI_SUCCESS;
  9472. }
  9473. static struct ast_cli_entry cli_queue[] = {
  9474. AST_CLI_DEFINE(queue_show, "Show status of a specified queue"),
  9475. AST_CLI_DEFINE(handle_queue_rule_show, "Show the rules defined in queuerules.conf"),
  9476. AST_CLI_DEFINE(handle_queue_add_member, "Add a channel to a specified queue"),
  9477. AST_CLI_DEFINE(handle_queue_remove_member, "Removes a channel from a specified queue"),
  9478. AST_CLI_DEFINE(handle_queue_pause_member, "Pause or unpause a queue member"),
  9479. AST_CLI_DEFINE(handle_queue_set_member_penalty, "Set penalty for a channel of a specified queue"),
  9480. AST_CLI_DEFINE(handle_queue_set_member_ringinuse, "Set ringinuse for a channel of a specified queue"),
  9481. AST_CLI_DEFINE(handle_queue_reload, "Reload queues, members, queue rules, or parameters"),
  9482. AST_CLI_DEFINE(handle_queue_reset, "Reset statistics for a queue"),
  9483. };
  9484. /* struct call_queue astdata mapping. */
  9485. #define DATA_EXPORT_CALL_QUEUE(MEMBER) \
  9486. MEMBER(call_queue, name, AST_DATA_STRING) \
  9487. MEMBER(call_queue, moh, AST_DATA_STRING) \
  9488. MEMBER(call_queue, announce, AST_DATA_STRING) \
  9489. MEMBER(call_queue, context, AST_DATA_STRING) \
  9490. MEMBER(call_queue, membermacro, AST_DATA_STRING) \
  9491. MEMBER(call_queue, membergosub, AST_DATA_STRING) \
  9492. MEMBER(call_queue, defaultrule, AST_DATA_STRING) \
  9493. MEMBER(call_queue, sound_next, AST_DATA_STRING) \
  9494. MEMBER(call_queue, sound_thereare, AST_DATA_STRING) \
  9495. MEMBER(call_queue, sound_calls, AST_DATA_STRING) \
  9496. MEMBER(call_queue, queue_quantity1, AST_DATA_STRING) \
  9497. MEMBER(call_queue, queue_quantity2, AST_DATA_STRING) \
  9498. MEMBER(call_queue, sound_holdtime, AST_DATA_STRING) \
  9499. MEMBER(call_queue, sound_minutes, AST_DATA_STRING) \
  9500. MEMBER(call_queue, sound_minute, AST_DATA_STRING) \
  9501. MEMBER(call_queue, sound_seconds, AST_DATA_STRING) \
  9502. MEMBER(call_queue, sound_thanks, AST_DATA_STRING) \
  9503. MEMBER(call_queue, sound_callerannounce, AST_DATA_STRING) \
  9504. MEMBER(call_queue, sound_reporthold, AST_DATA_STRING) \
  9505. MEMBER(call_queue, dead, AST_DATA_BOOLEAN) \
  9506. MEMBER(call_queue, ringinuse, AST_DATA_BOOLEAN) \
  9507. MEMBER(call_queue, announce_to_first_user, AST_DATA_BOOLEAN) \
  9508. MEMBER(call_queue, setinterfacevar, AST_DATA_BOOLEAN) \
  9509. MEMBER(call_queue, setqueuevar, AST_DATA_BOOLEAN) \
  9510. MEMBER(call_queue, setqueueentryvar, AST_DATA_BOOLEAN) \
  9511. MEMBER(call_queue, reportholdtime, AST_DATA_BOOLEAN) \
  9512. MEMBER(call_queue, wrapped, AST_DATA_BOOLEAN) \
  9513. MEMBER(call_queue, timeoutrestart, AST_DATA_BOOLEAN) \
  9514. MEMBER(call_queue, announceholdtime, AST_DATA_INTEGER) \
  9515. MEMBER(call_queue, realtime, AST_DATA_BOOLEAN) \
  9516. MEMBER(call_queue, found, AST_DATA_BOOLEAN) \
  9517. MEMBER(call_queue, announcepositionlimit, AST_DATA_INTEGER) \
  9518. MEMBER(call_queue, announcefrequency, AST_DATA_SECONDS) \
  9519. MEMBER(call_queue, minannouncefrequency, AST_DATA_SECONDS) \
  9520. MEMBER(call_queue, periodicannouncefrequency, AST_DATA_SECONDS) \
  9521. MEMBER(call_queue, numperiodicannounce, AST_DATA_INTEGER) \
  9522. MEMBER(call_queue, randomperiodicannounce, AST_DATA_INTEGER) \
  9523. MEMBER(call_queue, roundingseconds, AST_DATA_SECONDS) \
  9524. MEMBER(call_queue, holdtime, AST_DATA_SECONDS) \
  9525. MEMBER(call_queue, talktime, AST_DATA_SECONDS) \
  9526. MEMBER(call_queue, callscompleted, AST_DATA_INTEGER) \
  9527. MEMBER(call_queue, callsabandoned, AST_DATA_INTEGER) \
  9528. MEMBER(call_queue, servicelevel, AST_DATA_INTEGER) \
  9529. MEMBER(call_queue, callscompletedinsl, AST_DATA_INTEGER) \
  9530. MEMBER(call_queue, monfmt, AST_DATA_STRING) \
  9531. MEMBER(call_queue, montype, AST_DATA_INTEGER) \
  9532. MEMBER(call_queue, count, AST_DATA_INTEGER) \
  9533. MEMBER(call_queue, maxlen, AST_DATA_INTEGER) \
  9534. MEMBER(call_queue, wrapuptime, AST_DATA_SECONDS) \
  9535. MEMBER(call_queue, retry, AST_DATA_SECONDS) \
  9536. MEMBER(call_queue, timeout, AST_DATA_SECONDS) \
  9537. MEMBER(call_queue, weight, AST_DATA_INTEGER) \
  9538. MEMBER(call_queue, autopause, AST_DATA_INTEGER) \
  9539. MEMBER(call_queue, timeoutpriority, AST_DATA_INTEGER) \
  9540. MEMBER(call_queue, rrpos, AST_DATA_INTEGER) \
  9541. MEMBER(call_queue, memberdelay, AST_DATA_INTEGER) \
  9542. MEMBER(call_queue, autofill, AST_DATA_INTEGER) \
  9543. MEMBER(call_queue, members, AST_DATA_CONTAINER)
  9544. AST_DATA_STRUCTURE(call_queue, DATA_EXPORT_CALL_QUEUE);
  9545. /* struct member astdata mapping. */
  9546. #define DATA_EXPORT_MEMBER(MEMBER) \
  9547. MEMBER(member, interface, AST_DATA_STRING) \
  9548. MEMBER(member, state_interface, AST_DATA_STRING) \
  9549. MEMBER(member, membername, AST_DATA_STRING) \
  9550. MEMBER(member, penalty, AST_DATA_INTEGER) \
  9551. MEMBER(member, calls, AST_DATA_INTEGER) \
  9552. MEMBER(member, dynamic, AST_DATA_INTEGER) \
  9553. MEMBER(member, realtime, AST_DATA_INTEGER) \
  9554. MEMBER(member, status, AST_DATA_INTEGER) \
  9555. MEMBER(member, paused, AST_DATA_BOOLEAN) \
  9556. MEMBER(member, rt_uniqueid, AST_DATA_STRING)
  9557. AST_DATA_STRUCTURE(member, DATA_EXPORT_MEMBER);
  9558. #define DATA_EXPORT_QUEUE_ENT(MEMBER) \
  9559. MEMBER(queue_ent, moh, AST_DATA_STRING) \
  9560. MEMBER(queue_ent, announce, AST_DATA_STRING) \
  9561. MEMBER(queue_ent, context, AST_DATA_STRING) \
  9562. MEMBER(queue_ent, digits, AST_DATA_STRING) \
  9563. MEMBER(queue_ent, valid_digits, AST_DATA_INTEGER) \
  9564. MEMBER(queue_ent, pos, AST_DATA_INTEGER) \
  9565. MEMBER(queue_ent, prio, AST_DATA_INTEGER) \
  9566. MEMBER(queue_ent, last_pos_said, AST_DATA_INTEGER) \
  9567. MEMBER(queue_ent, last_periodic_announce_time, AST_DATA_INTEGER) \
  9568. MEMBER(queue_ent, last_periodic_announce_sound, AST_DATA_INTEGER) \
  9569. MEMBER(queue_ent, last_pos, AST_DATA_INTEGER) \
  9570. MEMBER(queue_ent, opos, AST_DATA_INTEGER) \
  9571. MEMBER(queue_ent, handled, AST_DATA_INTEGER) \
  9572. MEMBER(queue_ent, pending, AST_DATA_INTEGER) \
  9573. MEMBER(queue_ent, max_penalty, AST_DATA_INTEGER) \
  9574. MEMBER(queue_ent, min_penalty, AST_DATA_INTEGER) \
  9575. MEMBER(queue_ent, linpos, AST_DATA_INTEGER) \
  9576. MEMBER(queue_ent, linwrapped, AST_DATA_INTEGER) \
  9577. MEMBER(queue_ent, start, AST_DATA_INTEGER) \
  9578. MEMBER(queue_ent, expire, AST_DATA_INTEGER) \
  9579. MEMBER(queue_ent, cancel_answered_elsewhere, AST_DATA_INTEGER)
  9580. AST_DATA_STRUCTURE(queue_ent, DATA_EXPORT_QUEUE_ENT);
  9581. /*!
  9582. * \internal
  9583. * \brief Add a queue to the data_root node.
  9584. * \param[in] search The search tree.
  9585. * \param[in] data_root The main result node.
  9586. * \param[in] queue The queue to add.
  9587. */
  9588. static void queues_data_provider_get_helper(const struct ast_data_search *search,
  9589. struct ast_data *data_root, struct call_queue *queue)
  9590. {
  9591. struct ao2_iterator im;
  9592. struct member *member;
  9593. struct queue_ent *qe;
  9594. struct ast_data *data_queue, *data_members = NULL, *enum_node;
  9595. struct ast_data *data_member, *data_callers = NULL, *data_caller, *data_caller_channel;
  9596. data_queue = ast_data_add_node(data_root, "queue");
  9597. if (!data_queue) {
  9598. return;
  9599. }
  9600. ast_data_add_structure(call_queue, data_queue, queue);
  9601. ast_data_add_str(data_queue, "strategy", int2strat(queue->strategy));
  9602. ast_data_add_int(data_queue, "membercount", ao2_container_count(queue->members));
  9603. /* announce position */
  9604. enum_node = ast_data_add_node(data_queue, "announceposition");
  9605. if (!enum_node) {
  9606. return;
  9607. }
  9608. switch (queue->announceposition) {
  9609. case ANNOUNCEPOSITION_LIMIT:
  9610. ast_data_add_str(enum_node, "text", "limit");
  9611. break;
  9612. case ANNOUNCEPOSITION_MORE_THAN:
  9613. ast_data_add_str(enum_node, "text", "more");
  9614. break;
  9615. case ANNOUNCEPOSITION_YES:
  9616. ast_data_add_str(enum_node, "text", "yes");
  9617. break;
  9618. case ANNOUNCEPOSITION_NO:
  9619. ast_data_add_str(enum_node, "text", "no");
  9620. break;
  9621. default:
  9622. ast_data_add_str(enum_node, "text", "unknown");
  9623. break;
  9624. }
  9625. ast_data_add_int(enum_node, "value", queue->announceposition);
  9626. /* add queue members */
  9627. im = ao2_iterator_init(queue->members, 0);
  9628. while ((member = ao2_iterator_next(&im))) {
  9629. if (!data_members) {
  9630. data_members = ast_data_add_node(data_queue, "members");
  9631. if (!data_members) {
  9632. ao2_ref(member, -1);
  9633. continue;
  9634. }
  9635. }
  9636. data_member = ast_data_add_node(data_members, "member");
  9637. if (!data_member) {
  9638. ao2_ref(member, -1);
  9639. continue;
  9640. }
  9641. ast_data_add_structure(member, data_member, member);
  9642. ao2_ref(member, -1);
  9643. }
  9644. ao2_iterator_destroy(&im);
  9645. /* include the callers inside the result. */
  9646. if (queue->head) {
  9647. for (qe = queue->head; qe; qe = qe->next) {
  9648. if (!data_callers) {
  9649. data_callers = ast_data_add_node(data_queue, "callers");
  9650. if (!data_callers) {
  9651. continue;
  9652. }
  9653. }
  9654. data_caller = ast_data_add_node(data_callers, "caller");
  9655. if (!data_caller) {
  9656. continue;
  9657. }
  9658. ast_data_add_structure(queue_ent, data_caller, qe);
  9659. /* add the caller channel. */
  9660. data_caller_channel = ast_data_add_node(data_caller, "channel");
  9661. if (!data_caller_channel) {
  9662. continue;
  9663. }
  9664. ast_channel_data_add_structure(data_caller_channel, qe->chan, 1);
  9665. }
  9666. }
  9667. /* if this queue doesn't match remove the added queue. */
  9668. if (!ast_data_search_match(search, data_queue)) {
  9669. ast_data_remove_node(data_root, data_queue);
  9670. }
  9671. }
  9672. /*!
  9673. * \internal
  9674. * \brief Callback used to generate the queues tree.
  9675. * \param[in] search The search pattern tree.
  9676. * \retval NULL on error.
  9677. * \retval non-NULL The generated tree.
  9678. */
  9679. static int queues_data_provider_get(const struct ast_data_search *search,
  9680. struct ast_data *data_root)
  9681. {
  9682. struct ao2_iterator i;
  9683. struct call_queue *queue, *queue_realtime = NULL;
  9684. struct ast_config *cfg;
  9685. /* load realtime queues. */
  9686. cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
  9687. if (cfg) {
  9688. char *category = NULL;
  9689. while ((category = ast_category_browse(cfg, category))) {
  9690. const char *queuename = ast_variable_retrieve(cfg, category, "name");
  9691. if ((queue = find_load_queue_rt_friendly(queuename))) {
  9692. queue_unref(queue);
  9693. }
  9694. }
  9695. ast_config_destroy(cfg);
  9696. }
  9697. /* static queues. */
  9698. i = ao2_iterator_init(queues, 0);
  9699. while ((queue = ao2_iterator_next(&i))) {
  9700. ao2_lock(queue);
  9701. if (queue->realtime) {
  9702. queue_realtime = find_load_queue_rt_friendly(queue->name);
  9703. if (!queue_realtime) {
  9704. ao2_unlock(queue);
  9705. queue_unref(queue);
  9706. continue;
  9707. }
  9708. queue_unref(queue_realtime);
  9709. }
  9710. queues_data_provider_get_helper(search, data_root, queue);
  9711. ao2_unlock(queue);
  9712. queue_unref(queue);
  9713. }
  9714. ao2_iterator_destroy(&i);
  9715. return 0;
  9716. }
  9717. static const struct ast_data_handler queues_data_provider = {
  9718. .version = AST_DATA_HANDLER_VERSION,
  9719. .get = queues_data_provider_get
  9720. };
  9721. static const struct ast_data_entry queue_data_providers[] = {
  9722. AST_DATA_ENTRY("asterisk/application/queue/list", &queues_data_provider),
  9723. };
  9724. static struct stasis_message_router *agent_router;
  9725. static struct stasis_forward *topic_forwarder;
  9726. static int unload_module(void)
  9727. {
  9728. stasis_message_router_unsubscribe_and_join(agent_router);
  9729. agent_router = NULL;
  9730. topic_forwarder = stasis_forward_cancel(topic_forwarder);
  9731. STASIS_MESSAGE_TYPE_CLEANUP(queue_caller_join_type);
  9732. STASIS_MESSAGE_TYPE_CLEANUP(queue_caller_leave_type);
  9733. STASIS_MESSAGE_TYPE_CLEANUP(queue_caller_abandon_type);
  9734. STASIS_MESSAGE_TYPE_CLEANUP(queue_member_status_type);
  9735. STASIS_MESSAGE_TYPE_CLEANUP(queue_member_added_type);
  9736. STASIS_MESSAGE_TYPE_CLEANUP(queue_member_removed_type);
  9737. STASIS_MESSAGE_TYPE_CLEANUP(queue_member_pause_type);
  9738. STASIS_MESSAGE_TYPE_CLEANUP(queue_member_penalty_type);
  9739. STASIS_MESSAGE_TYPE_CLEANUP(queue_member_ringinuse_type);
  9740. STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_called_type);
  9741. STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_connect_type);
  9742. STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_complete_type);
  9743. STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_dump_type);
  9744. STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_ringnoanswer_type);
  9745. ast_cli_unregister_multiple(cli_queue, ARRAY_LEN(cli_queue));
  9746. ast_manager_unregister("QueueStatus");
  9747. ast_manager_unregister("Queues");
  9748. ast_manager_unregister("QueueRule");
  9749. ast_manager_unregister("QueueSummary");
  9750. ast_manager_unregister("QueueAdd");
  9751. ast_manager_unregister("QueueRemove");
  9752. ast_manager_unregister("QueuePause");
  9753. ast_manager_unregister("QueueLog");
  9754. ast_manager_unregister("QueuePenalty");
  9755. ast_manager_unregister("QueueReload");
  9756. ast_manager_unregister("QueueReset");
  9757. ast_manager_unregister("QueueMemberRingInUse");
  9758. ast_unregister_application(app_aqm);
  9759. ast_unregister_application(app_rqm);
  9760. ast_unregister_application(app_pqm);
  9761. ast_unregister_application(app_upqm);
  9762. ast_unregister_application(app_ql);
  9763. ast_unregister_application(app);
  9764. ast_custom_function_unregister(&queueexists_function);
  9765. ast_custom_function_unregister(&queuevar_function);
  9766. ast_custom_function_unregister(&queuemembercount_function);
  9767. ast_custom_function_unregister(&queuemembercount_dep);
  9768. ast_custom_function_unregister(&queuememberlist_function);
  9769. ast_custom_function_unregister(&queuewaitingcount_function);
  9770. ast_custom_function_unregister(&queuememberpenalty_function);
  9771. ast_data_unregister(NULL);
  9772. device_state_sub = stasis_unsubscribe_and_join(device_state_sub);
  9773. ast_unload_realtime("queue_members");
  9774. ao2_cleanup(queues);
  9775. ao2_cleanup(pending_members);
  9776. queues = NULL;
  9777. return 0;
  9778. }
  9779. /*!
  9780. * \brief Load the module
  9781. *
  9782. * Module loading including tests for configuration or dependencies.
  9783. * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
  9784. * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
  9785. * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
  9786. * configuration file or other non-critical problem return
  9787. * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
  9788. */
  9789. static int load_module(void)
  9790. {
  9791. int err = 0;
  9792. struct ast_flags mask = {AST_FLAGS_ALL, };
  9793. struct ast_config *member_config;
  9794. struct stasis_topic *queue_topic;
  9795. struct stasis_topic *manager_topic;
  9796. queues = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MAX_QUEUE_BUCKETS,
  9797. queue_hash_cb, NULL, queue_cmp_cb);
  9798. if (!queues) {
  9799. return AST_MODULE_LOAD_DECLINE;
  9800. }
  9801. pending_members = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
  9802. MAX_CALL_ATTEMPT_BUCKETS, pending_members_hash, NULL, pending_members_cmp);
  9803. if (!pending_members) {
  9804. unload_module();
  9805. return AST_MODULE_LOAD_DECLINE;
  9806. }
  9807. use_weight = 0;
  9808. if (reload_handler(0, &mask, NULL)) {
  9809. unload_module();
  9810. return AST_MODULE_LOAD_DECLINE;
  9811. }
  9812. ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
  9813. /*
  9814. * This section is used to determine which name for 'ringinuse' to use in realtime members
  9815. * Necessary for supporting older setups.
  9816. */
  9817. member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name LIKE", "%", SENTINEL);
  9818. if (!member_config) {
  9819. realtime_ringinuse_field = "ringinuse";
  9820. } else {
  9821. const char *config_val;
  9822. if ((config_val = ast_variable_retrieve(member_config, NULL, "ringinuse"))) {
  9823. ast_log(LOG_NOTICE, "ringinuse field entries found in queue_members table. Using 'ringinuse'\n");
  9824. realtime_ringinuse_field = "ringinuse";
  9825. } else if ((config_val = ast_variable_retrieve(member_config, NULL, "ignorebusy"))) {
  9826. ast_log(LOG_NOTICE, "ignorebusy field found in queue_members table with no ringinuse field. Using 'ignorebusy'\n");
  9827. realtime_ringinuse_field = "ignorebusy";
  9828. } else {
  9829. ast_log(LOG_NOTICE, "No entries were found for ringinuse/ignorebusy in queue_members table. Using 'ringinuse'\n");
  9830. realtime_ringinuse_field = "ringinuse";
  9831. }
  9832. }
  9833. ast_config_destroy(member_config);
  9834. if (queue_persistent_members) {
  9835. reload_queue_members();
  9836. }
  9837. ast_data_register_multiple(queue_data_providers, ARRAY_LEN(queue_data_providers));
  9838. err |= ast_cli_register_multiple(cli_queue, ARRAY_LEN(cli_queue));
  9839. err |= ast_register_application_xml(app, queue_exec);
  9840. err |= ast_register_application_xml(app_aqm, aqm_exec);
  9841. err |= ast_register_application_xml(app_rqm, rqm_exec);
  9842. err |= ast_register_application_xml(app_pqm, pqm_exec);
  9843. err |= ast_register_application_xml(app_upqm, upqm_exec);
  9844. err |= ast_register_application_xml(app_ql, ql_exec);
  9845. err |= ast_manager_register_xml("Queues", 0, manager_queues_show);
  9846. err |= ast_manager_register_xml("QueueStatus", 0, manager_queues_status);
  9847. err |= ast_manager_register_xml("QueueSummary", 0, manager_queues_summary);
  9848. err |= ast_manager_register_xml("QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member);
  9849. err |= ast_manager_register_xml("QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member);
  9850. err |= ast_manager_register_xml("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member);
  9851. err |= ast_manager_register_xml("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom);
  9852. err |= ast_manager_register_xml("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty);
  9853. err |= ast_manager_register_xml("QueueMemberRingInUse", EVENT_FLAG_AGENT, manager_queue_member_ringinuse);
  9854. err |= ast_manager_register_xml("QueueRule", 0, manager_queue_rule_show);
  9855. err |= ast_manager_register_xml("QueueReload", 0, manager_queue_reload);
  9856. err |= ast_manager_register_xml("QueueReset", 0, manager_queue_reset);
  9857. err |= ast_custom_function_register(&queuevar_function);
  9858. err |= ast_custom_function_register(&queueexists_function);
  9859. err |= ast_custom_function_register(&queuemembercount_function);
  9860. err |= ast_custom_function_register(&queuemembercount_dep);
  9861. err |= ast_custom_function_register(&queuememberlist_function);
  9862. err |= ast_custom_function_register(&queuewaitingcount_function);
  9863. err |= ast_custom_function_register(&queuememberpenalty_function);
  9864. /* in the following subscribe call, do I use DEVICE_STATE, or DEVICE_STATE_CHANGE? */
  9865. device_state_sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL);
  9866. if (!device_state_sub) {
  9867. err = -1;
  9868. }
  9869. stasis_subscription_accept_message_type(device_state_sub, ast_device_state_message_type());
  9870. stasis_subscription_set_filter(device_state_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
  9871. manager_topic = ast_manager_get_topic();
  9872. queue_topic = ast_queue_topic_all();
  9873. if (!manager_topic || !queue_topic) {
  9874. unload_module();
  9875. return AST_MODULE_LOAD_DECLINE;
  9876. }
  9877. topic_forwarder = stasis_forward_all(queue_topic, manager_topic);
  9878. if (!topic_forwarder) {
  9879. unload_module();
  9880. return AST_MODULE_LOAD_DECLINE;
  9881. }
  9882. if (!ast_channel_agent_login_type()
  9883. || !ast_channel_agent_logoff_type()) {
  9884. unload_module();
  9885. return AST_MODULE_LOAD_DECLINE;
  9886. }
  9887. agent_router = stasis_message_router_create(ast_channel_topic_all());
  9888. if (!agent_router) {
  9889. unload_module();
  9890. return AST_MODULE_LOAD_DECLINE;
  9891. }
  9892. err |= stasis_message_router_add(agent_router,
  9893. ast_channel_agent_login_type(),
  9894. queue_agent_cb,
  9895. NULL);
  9896. err |= stasis_message_router_add(agent_router,
  9897. ast_channel_agent_logoff_type(),
  9898. queue_agent_cb,
  9899. NULL);
  9900. err |= STASIS_MESSAGE_TYPE_INIT(queue_caller_join_type);
  9901. err |= STASIS_MESSAGE_TYPE_INIT(queue_caller_leave_type);
  9902. err |= STASIS_MESSAGE_TYPE_INIT(queue_caller_abandon_type);
  9903. err |= STASIS_MESSAGE_TYPE_INIT(queue_member_status_type);
  9904. err |= STASIS_MESSAGE_TYPE_INIT(queue_member_added_type);
  9905. err |= STASIS_MESSAGE_TYPE_INIT(queue_member_removed_type);
  9906. err |= STASIS_MESSAGE_TYPE_INIT(queue_member_pause_type);
  9907. err |= STASIS_MESSAGE_TYPE_INIT(queue_member_penalty_type);
  9908. err |= STASIS_MESSAGE_TYPE_INIT(queue_member_ringinuse_type);
  9909. err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_called_type);
  9910. err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_connect_type);
  9911. err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_complete_type);
  9912. err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_dump_type);
  9913. err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_ringnoanswer_type);
  9914. if (err) {
  9915. unload_module();
  9916. return AST_MODULE_LOAD_DECLINE;
  9917. }
  9918. return AST_MODULE_LOAD_SUCCESS;
  9919. }
  9920. static int reload(void)
  9921. {
  9922. struct ast_flags mask = {AST_FLAGS_ALL & ~QUEUE_RESET_STATS,};
  9923. ast_unload_realtime("queue_members");
  9924. reload_handler(1, &mask, NULL);
  9925. return 0;
  9926. }
  9927. /* \brief Find a member by looking up queuename and interface.
  9928. * \return Returns a member or NULL if member not found.
  9929. */
  9930. static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface)
  9931. {
  9932. struct member *mem = NULL;
  9933. struct call_queue *q;
  9934. if ((q = find_load_queue_rt_friendly(queuename))) {
  9935. ao2_lock(q);
  9936. mem = ao2_find(q->members, interface, OBJ_KEY);
  9937. ao2_unlock(q);
  9938. queue_t_unref(q, "Expiring temporary reference.");
  9939. }
  9940. return mem;
  9941. }
  9942. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "True Call Queueing",
  9943. .support_level = AST_MODULE_SUPPORT_CORE,
  9944. .load = load_module,
  9945. .unload = unload_module,
  9946. .reload = reload,
  9947. .load_pri = AST_MODPRI_DEVSTATE_CONSUMER,
  9948. );