12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582 |
- /*
- * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2005-2020, Anthony Minessale II <anthm@freeswitch.org>
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- *
- * The Initial Developer of the Original Code is
- * Anthony Minessale II <anthm@freeswitch.org>
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II <anthm@freeswitch.org>
- * Michael Jerris <mike@jerris.com>
- *
- *
- * switch_channel.c -- Media Channel Interface
- *
- */
- #include <switch.h>
- #include <switch_channel.h>
- #include <pcre.h>
- struct switch_cause_table {
- const char *name;
- switch_call_cause_t cause;
- };
- typedef struct switch_device_state_binding_s {
- switch_device_state_function_t function;
- void *user_data;
- struct switch_device_state_binding_s *next;
- } switch_device_state_binding_t;
- static struct {
- switch_memory_pool_t *pool;
- switch_hash_t *device_hash;
- switch_mutex_t *device_mutex;
- switch_device_state_binding_t *device_bindings;
- } globals;
- static struct switch_cause_table CAUSE_CHART[] = {
- {"NONE", SWITCH_CAUSE_NONE},
- {"UNALLOCATED_NUMBER", SWITCH_CAUSE_UNALLOCATED_NUMBER},
- {"NO_ROUTE_TRANSIT_NET", SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET},
- {"NO_ROUTE_DESTINATION", SWITCH_CAUSE_NO_ROUTE_DESTINATION},
- {"CHANNEL_UNACCEPTABLE", SWITCH_CAUSE_CHANNEL_UNACCEPTABLE},
- {"CALL_AWARDED_DELIVERED", SWITCH_CAUSE_CALL_AWARDED_DELIVERED},
- {"NORMAL_CLEARING", SWITCH_CAUSE_NORMAL_CLEARING},
- {"USER_BUSY", SWITCH_CAUSE_USER_BUSY},
- {"NO_USER_RESPONSE", SWITCH_CAUSE_NO_USER_RESPONSE},
- {"NO_ANSWER", SWITCH_CAUSE_NO_ANSWER},
- {"SUBSCRIBER_ABSENT", SWITCH_CAUSE_SUBSCRIBER_ABSENT},
- {"CALL_REJECTED", SWITCH_CAUSE_CALL_REJECTED},
- {"NUMBER_CHANGED", SWITCH_CAUSE_NUMBER_CHANGED},
- {"REDIRECTION_TO_NEW_DESTINATION", SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION},
- {"EXCHANGE_ROUTING_ERROR", SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR},
- {"DESTINATION_OUT_OF_ORDER", SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER},
- {"INVALID_NUMBER_FORMAT", SWITCH_CAUSE_INVALID_NUMBER_FORMAT},
- {"FACILITY_REJECTED", SWITCH_CAUSE_FACILITY_REJECTED},
- {"RESPONSE_TO_STATUS_ENQUIRY", SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY},
- {"NORMAL_UNSPECIFIED", SWITCH_CAUSE_NORMAL_UNSPECIFIED},
- {"NORMAL_CIRCUIT_CONGESTION", SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION},
- {"NETWORK_OUT_OF_ORDER", SWITCH_CAUSE_NETWORK_OUT_OF_ORDER},
- {"NORMAL_TEMPORARY_FAILURE", SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE},
- {"SWITCH_CONGESTION", SWITCH_CAUSE_SWITCH_CONGESTION},
- {"ACCESS_INFO_DISCARDED", SWITCH_CAUSE_ACCESS_INFO_DISCARDED},
- {"REQUESTED_CHAN_UNAVAIL", SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL},
- {"PRE_EMPTED", SWITCH_CAUSE_PRE_EMPTED},
- {"FACILITY_NOT_SUBSCRIBED", SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED},
- {"OUTGOING_CALL_BARRED", SWITCH_CAUSE_OUTGOING_CALL_BARRED},
- {"INCOMING_CALL_BARRED", SWITCH_CAUSE_INCOMING_CALL_BARRED},
- {"BEARERCAPABILITY_NOTAUTH", SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH},
- {"BEARERCAPABILITY_NOTAVAIL", SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL},
- {"SERVICE_UNAVAILABLE", SWITCH_CAUSE_SERVICE_UNAVAILABLE},
- {"BEARERCAPABILITY_NOTIMPL", SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL},
- {"CHAN_NOT_IMPLEMENTED", SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED},
- {"FACILITY_NOT_IMPLEMENTED", SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED},
- {"SERVICE_NOT_IMPLEMENTED", SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED},
- {"INVALID_CALL_REFERENCE", SWITCH_CAUSE_INVALID_CALL_REFERENCE},
- {"INCOMPATIBLE_DESTINATION", SWITCH_CAUSE_INCOMPATIBLE_DESTINATION},
- {"INVALID_MSG_UNSPECIFIED", SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED},
- {"MANDATORY_IE_MISSING", SWITCH_CAUSE_MANDATORY_IE_MISSING},
- {"MESSAGE_TYPE_NONEXIST", SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST},
- {"WRONG_MESSAGE", SWITCH_CAUSE_WRONG_MESSAGE},
- {"IE_NONEXIST", SWITCH_CAUSE_IE_NONEXIST},
- {"INVALID_IE_CONTENTS", SWITCH_CAUSE_INVALID_IE_CONTENTS},
- {"WRONG_CALL_STATE", SWITCH_CAUSE_WRONG_CALL_STATE},
- {"RECOVERY_ON_TIMER_EXPIRE", SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE},
- {"MANDATORY_IE_LENGTH_ERROR", SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR},
- {"PROTOCOL_ERROR", SWITCH_CAUSE_PROTOCOL_ERROR},
- {"INTERWORKING", SWITCH_CAUSE_INTERWORKING},
- {"SUCCESS", SWITCH_CAUSE_SUCCESS},
- {"ORIGINATOR_CANCEL", SWITCH_CAUSE_ORIGINATOR_CANCEL},
- {"CRASH", SWITCH_CAUSE_CRASH},
- {"SYSTEM_SHUTDOWN", SWITCH_CAUSE_SYSTEM_SHUTDOWN},
- {"LOSE_RACE", SWITCH_CAUSE_LOSE_RACE},
- {"MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST},
- {"BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER},
- {"ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER},
- {"ALLOTTED_TIMEOUT", SWITCH_CAUSE_ALLOTTED_TIMEOUT},
- {"USER_CHALLENGE", SWITCH_CAUSE_USER_CHALLENGE},
- {"MEDIA_TIMEOUT", SWITCH_CAUSE_MEDIA_TIMEOUT},
- {"PICKED_OFF", SWITCH_CAUSE_PICKED_OFF},
- {"USER_NOT_REGISTERED", SWITCH_CAUSE_USER_NOT_REGISTERED},
- {"PROGRESS_TIMEOUT", SWITCH_CAUSE_PROGRESS_TIMEOUT},
- {"INVALID_GATEWAY", SWITCH_CAUSE_INVALID_GATEWAY},
- {"GATEWAY_DOWN", SWITCH_CAUSE_GATEWAY_DOWN},
- {"INVALID_URL", SWITCH_CAUSE_INVALID_URL},
- {"INVALID_PROFILE", SWITCH_CAUSE_INVALID_PROFILE},
- {"NO_PICKUP", SWITCH_CAUSE_NO_PICKUP},
- {"SRTP_READ_ERROR", SWITCH_CAUSE_SRTP_READ_ERROR},
- {"BOWOUT", SWITCH_CAUSE_BOWOUT},
- {"BUSY_EVERYWHERE", SWITCH_CAUSE_BUSY_EVERYWHERE},
- {"DECLINE", SWITCH_CAUSE_DECLINE},
- {"DOES_NOT_EXIST_ANYWHERE", SWITCH_CAUSE_DOES_NOT_EXIST_ANYWHERE},
- {"NOT_ACCEPTABLE", SWITCH_CAUSE_NOT_ACCEPTABLE},
- {"UNWANTED", SWITCH_CAUSE_UNWANTED},
- {"NO_IDENTITY", SWITCH_CAUSE_NO_IDENTITY},
- {"BAD_IDENTITY_INFO", SWITCH_CAUSE_BAD_IDENTITY_INFO},
- {"UNSUPPORTED_CERTIFICATE", SWITCH_CAUSE_UNSUPPORTED_CERTIFICATE},
- {"INVALID_IDENTITY", SWITCH_CAUSE_INVALID_IDENTITY},
- {"STALE_DATE", SWITCH_CAUSE_STALE_DATE},
- {"REJECT_ALL", SWITCH_CAUSE_REJECT_ALL},
- {NULL, 0}
- };
- typedef enum {
- OCF_HANGUP = (1 << 0)
- } opaque_channel_flag_t;
- typedef enum {
- LP_NEITHER,
- LP_ORIGINATOR,
- LP_ORIGINATEE
- } switch_originator_type_t;
- struct switch_channel {
- char *name;
- switch_call_direction_t direction;
- switch_call_direction_t logical_direction;
- switch_queue_t *dtmf_queue;
- switch_queue_t *dtmf_log_queue;
- switch_mutex_t*dtmf_mutex;
- switch_mutex_t *flag_mutex;
- switch_mutex_t *state_mutex;
- switch_mutex_t *thread_mutex;
- switch_mutex_t *profile_mutex;
- switch_core_session_t *session;
- switch_channel_state_t state;
- switch_channel_state_t running_state;
- switch_channel_callstate_t callstate;
- uint32_t flags[CF_FLAG_MAX];
- uint32_t caps[CC_FLAG_MAX];
- uint8_t state_flags[CF_FLAG_MAX];
- uint32_t private_flags;
- switch_caller_profile_t *caller_profile;
- const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];
- int state_handler_index;
- switch_event_t *variables;
- switch_event_t *scope_variables;
- switch_hash_t *private_hash;
- switch_hash_t *app_flag_hash;
- switch_call_cause_t hangup_cause;
- int vi;
- int event_count;
- int profile_index;
- opaque_channel_flag_t opaque_flags;
- switch_originator_type_t last_profile_type;
- switch_caller_extension_t *queued_extension;
- switch_event_t *app_list;
- switch_event_t *api_list;
- switch_event_t *var_list;
- switch_hold_record_t *hold_record;
- switch_device_node_t *device_node;
- char *device_id;
- switch_event_t *log_tags;
- };
- static void process_device_hup(switch_channel_t *channel);
- static void switch_channel_check_device_state(switch_channel_t *channel, switch_channel_callstate_t callstate);
- SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel)
- {
- return channel->hold_record;
- }
- SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause)
- {
- uint8_t x;
- const char *str = "UNKNOWN";
- for (x = 0; x < (sizeof(CAUSE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
- if (CAUSE_CHART[x].cause == cause) {
- str = CAUSE_CHART[x].name;
- break;
- }
- }
- return str;
- }
- SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2cause(const char *str)
- {
- uint8_t x;
- switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
- if (!zstr(str)) {
- if (*str > 47 && *str < 58) {
- cause = atoi(str);
- } else {
- for (x = 0; x < (sizeof(CAUSE_CHART) / sizeof(struct switch_cause_table)) - 1 && CAUSE_CHART[x].name; x++) {
- if (!strcasecmp(CAUSE_CHART[x].name, str)) {
- cause = CAUSE_CHART[x].cause;
- break;
- }
- }
- }
- }
- return cause;
- }
- SWITCH_DECLARE(switch_call_cause_t) switch_channel_get_cause(switch_channel_t *channel)
- {
- return channel->hangup_cause;
- }
- SWITCH_DECLARE(switch_call_cause_t *) switch_channel_get_cause_ptr(switch_channel_t *channel)
- {
- return &channel->hangup_cause;
- }
- struct switch_callstate_table {
- const char *name;
- switch_channel_callstate_t callstate;
- };
- static struct switch_callstate_table CALLSTATE_CHART[] = {
- {"DOWN", CCS_DOWN},
- {"DIALING", CCS_DIALING},
- {"RINGING", CCS_RINGING},
- {"EARLY", CCS_EARLY},
- {"ACTIVE", CCS_ACTIVE},
- {"HELD", CCS_HELD},
- {"RING_WAIT", CCS_RING_WAIT},
- {"HANGUP", CCS_HANGUP},
- {"UNHELD", CCS_UNHELD},
- {NULL, 0}
- };
- struct switch_device_state_table {
- const char *name;
- switch_device_state_t device_state;
- };
- static struct switch_device_state_table DEVICE_STATE_CHART[] = {
- {"DOWN", SDS_DOWN},
- {"RINGING", SDS_RINGING},
- {"ACTIVE", SDS_ACTIVE},
- {"ACTIVE_MULTI", SDS_ACTIVE_MULTI},
- {"HELD", SDS_HELD},
- {"UNHELD", SDS_UNHELD},
- {"HANGUP", SDS_HANGUP},
- {NULL, 0}
- };
- SWITCH_DECLARE(void) switch_channel_perform_set_callstate(switch_channel_t *channel, switch_channel_callstate_t callstate,
- const char *file, const char *func, int line)
- {
- switch_event_t *event;
- switch_channel_callstate_t o_callstate = channel->callstate;
- if (o_callstate == callstate || o_callstate == CCS_HANGUP) return;
- channel->callstate = callstate;
- if (channel->device_node) {
- channel->device_node->callstate = callstate;
- }
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG,
- "(%s) Callstate Change %s -> %s\n", channel->name,
- switch_channel_callstate2str(o_callstate), switch_channel_callstate2str(callstate));
- switch_channel_check_device_state(channel, channel->callstate);
- if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CALLSTATE) == SWITCH_STATUS_SUCCESS) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Original-Channel-Call-State", switch_channel_callstate2str(o_callstate));
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Call-State-Number", "%d", callstate);
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- }
- SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_get_callstate(switch_channel_t *channel)
- {
- return channel->callstate;
- }
- SWITCH_DECLARE(const char *) switch_channel_callstate2str(switch_channel_callstate_t callstate)
- {
- uint8_t x;
- const char *str = "UNKNOWN";
- for (x = 0; x < (sizeof(CALLSTATE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
- if (CALLSTATE_CHART[x].callstate == callstate) {
- str = CALLSTATE_CHART[x].name;
- break;
- }
- }
- return str;
- }
- SWITCH_DECLARE(const char *) switch_channel_device_state2str(switch_device_state_t device_state)
- {
- uint8_t x;
- const char *str = "UNKNOWN";
- for (x = 0; x < (sizeof(DEVICE_STATE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
- if (DEVICE_STATE_CHART[x].device_state == device_state) {
- str = DEVICE_STATE_CHART[x].name;
- break;
- }
- }
- return str;
- }
- SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_str2callstate(const char *str)
- {
- uint8_t x;
- switch_channel_callstate_t callstate = (switch_channel_callstate_t) SWITCH_CAUSE_NONE;
- if (*str > 47 && *str < 58) {
- callstate = atoi(str);
- } else {
- for (x = 0; x < (sizeof(CALLSTATE_CHART) / sizeof(struct switch_callstate_table)) - 1 && CALLSTATE_CHART[x].name; x++) {
- if (!strcasecmp(CALLSTATE_CHART[x].name, str)) {
- callstate = CALLSTATE_CHART[x].callstate;
- break;
- }
- }
- }
- return callstate;
- }
- SWITCH_DECLARE(void) switch_channel_perform_audio_sync(switch_channel_t *channel, const char *file, const char *func, int line)
- {
- if (switch_channel_media_up(channel)) {
- switch_core_session_message_t *msg = NULL;
- msg = switch_core_session_alloc(channel->session, sizeof(*msg));
- MESSAGE_STAMP_FFL(msg);
- msg->message_id = SWITCH_MESSAGE_INDICATE_AUDIO_SYNC;
- msg->from = channel->name;
- msg->_file = file;
- msg->_func = func;
- msg->_line = line;
- switch_core_session_queue_message(channel->session, msg);
- }
- }
- SWITCH_DECLARE(void) switch_channel_perform_video_sync(switch_channel_t *channel, const char *file, const char *func, int line)
- {
- if (switch_channel_media_up(channel)) {
- switch_core_session_message_t *msg = NULL;
- msg = switch_core_session_alloc(channel->session, sizeof(*msg));
- MESSAGE_STAMP_FFL(msg);
- msg->message_id = SWITCH_MESSAGE_INDICATE_VIDEO_SYNC;
- msg->from = channel->name;
- msg->_file = file;
- msg->_func = func;
- msg->_line = line;
- switch_core_session_request_video_refresh(channel->session);
- switch_core_session_queue_message(channel->session, msg);
- }
- }
- SWITCH_DECLARE(switch_call_cause_t) switch_channel_cause_q850(switch_call_cause_t cause)
- {
- if (cause <= SWITCH_CAUSE_INTERWORKING) {
- return cause;
- } else {
- return SWITCH_CAUSE_NORMAL_CLEARING;
- }
- }
- SWITCH_DECLARE(switch_call_cause_t) switch_channel_get_cause_q850(switch_channel_t *channel)
- {
- return switch_channel_cause_q850(channel->hangup_cause);
- }
- SWITCH_DECLARE(switch_channel_timetable_t *) switch_channel_get_timetable(switch_channel_t *channel)
- {
- switch_channel_timetable_t *times = NULL;
- if (channel->caller_profile) {
- switch_mutex_lock(channel->profile_mutex);
- times = channel->caller_profile->times;
- switch_mutex_unlock(channel->profile_mutex);
- }
- return times;
- }
- SWITCH_DECLARE(void) switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction)
- {
- if (!switch_core_session_in_thread(channel->session)) {
- channel->direction = channel->logical_direction = direction;
- switch_channel_set_variable(channel, "direction", switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
- }
- }
- SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel)
- {
- return channel->direction;
- }
- SWITCH_DECLARE(switch_call_direction_t) switch_channel_logical_direction(switch_channel_t *channel)
- {
- return channel->logical_direction;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_call_direction_t direction, switch_memory_pool_t *pool)
- {
- switch_assert(pool != NULL);
- if (((*channel) = switch_core_alloc(pool, sizeof(switch_channel_t))) == 0) {
- return SWITCH_STATUS_MEMERR;
- }
- switch_event_create_plain(&(*channel)->variables, SWITCH_EVENT_CHANNEL_DATA);
- switch_core_hash_init(&(*channel)->private_hash);
- switch_queue_create(&(*channel)->dtmf_queue, SWITCH_DTMF_LOG_LEN, pool);
- switch_queue_create(&(*channel)->dtmf_log_queue, SWITCH_DTMF_LOG_LEN, pool);
- switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->thread_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);
- (*channel)->hangup_cause = SWITCH_CAUSE_NONE;
- (*channel)->name = "";
- (*channel)->direction = (*channel)->logical_direction = direction;
- switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_dtmf_lock(switch_channel_t *channel)
- {
- return switch_mutex_lock(channel->dtmf_mutex);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_try_dtmf_lock(switch_channel_t *channel)
- {
- return switch_mutex_trylock(channel->dtmf_mutex);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_dtmf_unlock(switch_channel_t *channel)
- {
- return switch_mutex_unlock(channel->dtmf_mutex);
- }
- SWITCH_DECLARE(switch_size_t) switch_channel_has_dtmf(switch_channel_t *channel)
- {
- switch_size_t has;
- switch_mutex_lock(channel->dtmf_mutex);
- has = switch_queue_size(channel->dtmf_queue);
- switch_mutex_unlock(channel->dtmf_mutex);
- return has;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const switch_dtmf_t *dtmf)
- {
- switch_status_t status;
- void *pop;
- switch_dtmf_t new_dtmf = { 0 };
- switch_bool_t sensitive = switch_true(switch_channel_get_variable_dup(channel, SWITCH_SENSITIVE_DTMF_VARIABLE, SWITCH_FALSE, -1));
- switch_assert(dtmf);
- switch_mutex_lock(channel->dtmf_mutex);
- new_dtmf = *dtmf;
- if (sensitive) {
- switch_set_flag((&new_dtmf), DTMF_FLAG_SENSITIVE);
- }
- if ((status = switch_core_session_recv_dtmf(channel->session, dtmf) != SWITCH_STATUS_SUCCESS)) {
- goto done;
- }
- if (is_dtmf(new_dtmf.digit)) {
- switch_dtmf_t *dt;
- int x = 0;
- if (!sensitive) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_INFO, "RECV DTMF %c:%d\n", new_dtmf.digit, new_dtmf.duration);
- }
- if (new_dtmf.digit != 'w' && new_dtmf.digit != 'W') {
- if (new_dtmf.duration > switch_core_max_dtmf_duration(0)) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s EXCESSIVE DTMF DIGIT LEN [%d]\n",
- switch_channel_get_name(channel), new_dtmf.duration);
- new_dtmf.duration = switch_core_max_dtmf_duration(0);
- } else if (new_dtmf.duration < switch_core_min_dtmf_duration(0)) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s SHORT DTMF DIGIT LEN [%d]\n",
- switch_channel_get_name(channel), new_dtmf.duration);
- new_dtmf.duration = switch_core_min_dtmf_duration(0);
- }
- }
- if (!new_dtmf.duration) {
- new_dtmf.duration = switch_core_default_dtmf_duration(0);
- }
- switch_zmalloc(dt, sizeof(*dt));
- *dt = new_dtmf;
- while (switch_queue_trypush(channel->dtmf_queue, dt) != SWITCH_STATUS_SUCCESS) {
- if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
- free(pop);
- }
- if (++x > 100) {
- status = SWITCH_STATUS_FALSE;
- free(dt);
- goto done;
- }
- }
- }
- status = SWITCH_STATUS_SUCCESS;
- done:
- switch_mutex_unlock(channel->dtmf_mutex);
- switch_core_media_break(channel->session, SWITCH_MEDIA_TYPE_AUDIO);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_t *channel, const char *dtmf_string)
- {
- char *p;
- switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0), 0, SWITCH_DTMF_APP };
- int sent = 0, dur, bad_input = 0;
- char *string;
- int i, argc;
- char *argv[256];
- if (zstr(dtmf_string)) {
- return SWITCH_STATUS_GENERR;
- }
- dtmf.flags = DTMF_FLAG_SKIP_PROCESS;
- if (*dtmf_string == '~') {
- dtmf_string++;
- dtmf.flags = 0;
- }
- string = switch_core_session_strdup(channel->session, dtmf_string);
- argc = switch_separate_string(string, '+', argv, (sizeof(argv) / sizeof(argv[0])));
- for (i = 0; i < argc; i++) {
- dtmf.duration = switch_core_default_dtmf_duration(0);
- dur = switch_core_default_dtmf_duration(0) / 8;
- if ((p = strchr(argv[i], '@'))) {
- *p++ = '\0';
- if ((dur = atoi(p)) > (int)switch_core_min_dtmf_duration(0) / 8) {
- dtmf.duration = dur * 8;
- }
- }
- for (p = argv[i]; p && *p; p++) {
- if (is_dtmf(*p)) {
- dtmf.digit = *p;
- if (dtmf.duration > switch_core_max_dtmf_duration(0)) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "EXCESSIVE DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration);
- dtmf.duration = switch_core_max_dtmf_duration(0);
- } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "SHORT DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration);
- dtmf.duration = switch_core_min_dtmf_duration(0);
- } else if (!dtmf.duration) {
- dtmf.duration = switch_core_default_dtmf_duration(0);
- }
- if (switch_channel_queue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s Queue dtmf\ndigit=%c ms=%u samples=%u\n",
- switch_channel_get_name(channel), dtmf.digit, dur, dtmf.duration);
- sent++;
- }
- } else {
- bad_input++;
- }
- }
- }
- if (sent) {
- return SWITCH_STATUS_SUCCESS;
- }
- return bad_input ? SWITCH_STATUS_GENERR : SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, switch_dtmf_t *dtmf)
- {
- switch_event_t *event;
- void *pop;
- switch_dtmf_t *dt;
- switch_status_t status = SWITCH_STATUS_FALSE;
- int sensitive = 0;
- switch_mutex_lock(channel->dtmf_mutex);
- if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
- dt = (switch_dtmf_t *) pop;
- *dtmf = *dt;
- sensitive = switch_test_flag(dtmf, DTMF_FLAG_SENSITIVE);
- if (!sensitive && switch_queue_trypush(channel->dtmf_log_queue, dt) != SWITCH_STATUS_SUCCESS) {
- free(dt);
- }
- dt = NULL;
- if (dtmf->duration > switch_core_max_dtmf_duration(0)) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n",
- switch_channel_get_name(channel), sensitive ? 'S' : dtmf->digit, dtmf->duration);
- dtmf->duration = switch_core_max_dtmf_duration(0);
- } else if (dtmf->duration < switch_core_min_dtmf_duration(0)) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n",
- switch_channel_get_name(channel), sensitive ? 'S' : dtmf->digit, dtmf->duration);
- dtmf->duration = switch_core_min_dtmf_duration(0);
- } else if (!dtmf->duration) {
- dtmf->duration = switch_core_default_dtmf_duration(0);
- }
- status = SWITCH_STATUS_SUCCESS;
- }
- switch_mutex_unlock(channel->dtmf_mutex);
- if (!sensitive && status == SWITCH_STATUS_SUCCESS && switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
- const char *dtmf_source_str = NULL;
- switch_channel_event_set_data(channel, event);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Digit", "%c", dtmf->digit);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Duration", "%u", dtmf->duration);
- switch(dtmf->source) {
- case SWITCH_DTMF_INBAND_AUDIO: /* From audio */
- dtmf_source_str = "INBAND_AUDIO";
- break;
- case SWITCH_DTMF_RTP: /* From RTP as a telephone event */
- dtmf_source_str = "RTP";
- break;
- case SWITCH_DTMF_ENDPOINT: /* From endpoint signaling */
- dtmf_source_str = "ENDPOINT";
- break;
- case SWITCH_DTMF_APP: /* Injected by application */
- dtmf_source_str = "APP";
- break;
- case SWITCH_DTMF_UNKNOWN: /* Unknown source */
- default:
- dtmf_source_str = "UNKNOWN";
- break;
- }
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Source", "%s", dtmf_source_str);
- if (switch_channel_test_flag(channel, CF_DIVERT_EVENTS)) {
- switch_core_session_queue_event(channel->session, &event);
- } else {
- switch_event_fire(&event);
- }
- }
- return status;
- }
- SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf_string(switch_channel_t *channel, char *dtmf_str, switch_size_t len)
- {
- switch_size_t x = 0;
- switch_dtmf_t dtmf = { 0 };
- memset(dtmf_str, 0, len);
- while (x < len - 1 && switch_channel_dequeue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
- dtmf_str[x++] = dtmf.digit;
- }
- return x;
- }
- SWITCH_DECLARE(void) switch_channel_flush_dtmf(switch_channel_t *channel)
- {
- void *pop;
- switch_mutex_lock(channel->dtmf_mutex);
- while (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_dtmf_t *dt = (switch_dtmf_t *) pop;
- if (channel->state >= CS_HANGUP || switch_queue_trypush(channel->dtmf_log_queue, dt) != SWITCH_STATUS_SUCCESS) {
- free(dt);
- }
- }
- switch_mutex_unlock(channel->dtmf_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel)
- {
- void *pop;
- switch_channel_flush_dtmf(channel);
- while (switch_queue_trypop(channel->dtmf_log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_safe_free(pop);
- }
- if (channel->private_hash) {
- switch_core_hash_destroy(&channel->private_hash);
- }
- if (channel->app_flag_hash) {
- switch_core_hash_destroy(&channel->app_flag_hash);
- }
- switch_mutex_lock(channel->profile_mutex);
- switch_event_destroy(&channel->variables);
- switch_event_destroy(&channel->api_list);
- switch_event_destroy(&channel->var_list);
- switch_event_destroy(&channel->app_list);
- if (channel->log_tags) {
- switch_event_destroy(&channel->log_tags);
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_init(switch_channel_t *channel, switch_core_session_t *session, switch_channel_state_t state,
- switch_channel_flag_t flag)
- {
- switch_assert(channel != NULL);
- channel->state = state;
- switch_channel_set_flag(channel, flag);
- channel->session = session;
- channel->running_state = CS_NONE;
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(void) switch_channel_perform_presence(switch_channel_t *channel, const char *rpid, const char *status, const char *id,
- const char *file, const char *func, int line)
- {
- switch_event_t *event;
- switch_event_types_t type = SWITCH_EVENT_PRESENCE_IN;
- const char *call_info = NULL;
- char *call_info_state = "active";
- if (switch_channel_test_flag(channel, CF_NO_PRESENCE)) {
- return;
- }
- if (!status) {
- type = SWITCH_EVENT_PRESENCE_OUT;
- status = "idle";
- }
- if (!id) {
- id = switch_channel_get_variable(channel, "presence_id");
- }
- if (!id) {
- return;
- }
- call_info = switch_channel_get_variable(channel, "presence_call_info");
- if (switch_event_create(&event, type) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(channel, event);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "any");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", __FILE__);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", id);
- if (type == SWITCH_EVENT_PRESENCE_IN) {
- if (!rpid) {
- rpid = "unknown";
- }
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status);
- }
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
- if (!strcasecmp(status, "idle") || !switch_channel_up_nosig(channel)) {
- call_info_state = "idle";
- } else if (!strcasecmp(status, "hold-private")) {
- call_info_state = "held-private";
- } else if (!strcasecmp(status, "hold")) {
- call_info_state = "held";
- } else if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
- if (channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
- call_info_state = "progressing";
- } else {
- if (switch_channel_test_flag(channel, CF_SLA_INTERCEPT)) {
- call_info_state = "idle";
- } else {
- call_info_state = "alerting";
- }
- }
- }
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-info-state", call_info_state);
- if (call_info) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-info", call_info);
- }
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction",
- channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", channel->event_count++);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Calling-File", file);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Calling-Function", func);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Presence-Calling-Line", "%d", line);
- if (switch_true(switch_channel_get_variable(channel, "presence_privacy"))) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Privacy", "true");
- }
- switch_event_fire(&event);
- }
- }
- SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_bool_t on)
- {
- switch_event_t *event;
- if (!!on == !!switch_channel_test_flag(channel, CF_LEG_HOLDING)) {
- goto end;
- }
- if (on) {
- switch_channel_set_flag(channel, CF_LEG_HOLDING);
- } else {
- switch_channel_clear_flag(channel, CF_LEG_HOLDING);
- }
- if (switch_event_create(&event, on ? SWITCH_EVENT_CHANNEL_HOLD : SWITCH_EVENT_CHANNEL_UNHOLD) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- end:
- if (on) {
- if (switch_true(switch_channel_get_variable(channel, "flip_record_on_hold"))) {
- switch_core_session_t *other_session;
- if (switch_core_session_get_partner(channel->session, &other_session) == SWITCH_STATUS_SUCCESS) {
- switch_ivr_transfer_recordings(channel->session, other_session);
- switch_core_session_rwunlock(other_session);
- }
- }
- }
- }
- SWITCH_DECLARE(const char *) switch_channel_get_hold_music(switch_channel_t *channel)
- {
- const char *var;
- if (!(var = switch_channel_get_variable(channel, SWITCH_TEMP_HOLD_MUSIC_VARIABLE))) {
- var = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE);
- }
- if (!zstr(var)) {
- char *expanded = switch_channel_expand_variables(channel, var);
- if (expanded != var) {
- var = switch_core_session_strdup(channel->session, expanded);
- free(expanded);
- }
- }
- return var;
- }
- SWITCH_DECLARE(const char *) switch_channel_get_hold_music_partner(switch_channel_t *channel)
- {
- switch_core_session_t *session;
- const char *r = NULL;
- if (switch_core_session_get_partner(channel->session, &session) == SWITCH_STATUS_SUCCESS) {
- r = switch_channel_get_hold_music(switch_core_session_get_channel(session));
- switch_core_session_rwunlock(session);
- }
- return r;
- }
- SWITCH_DECLARE(void) switch_channel_set_scope_variables(switch_channel_t *channel, switch_event_t **event)
- {
- switch_mutex_lock(channel->profile_mutex);
- if (event && *event) { /* push */
- (*event)->next = channel->scope_variables;
- channel->scope_variables = *event;
- *event = NULL;
- } else if (channel->scope_variables) { /* pop */
- switch_event_t *top_event = channel->scope_variables;
- channel->scope_variables = channel->scope_variables->next;
- switch_event_destroy(&top_event);
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_get_scope_variables(switch_channel_t *channel, switch_event_t **event)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_event_t *new_event;
- switch_mutex_lock(channel->profile_mutex);
- if (channel->scope_variables) {
- switch_event_t *ep;
- switch_event_header_t *hp;
- switch_event_create_plain(&new_event, SWITCH_EVENT_CHANNEL_DATA);
- status = SWITCH_STATUS_SUCCESS;
- *event = new_event;
- for (ep = channel->scope_variables; ep; ep = ep->next) {
- for (hp = ep->headers; hp; hp = hp->next) {
- if (!switch_event_get_header(new_event, hp->value)) {
- switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
- }
- }
- }
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
- {
- const char *v = NULL, *r = NULL, *vdup = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (!zstr(varname)) {
- if (channel->scope_variables) {
- switch_event_t *ep;
- for (ep = channel->scope_variables; ep; ep = ep->next) {
- if ((v = switch_event_get_header_idx(ep, varname, idx))) {
- break;
- }
- }
- }
- if (!v && (!channel->variables || !(v = switch_event_get_header_idx(channel->variables, varname, idx)))) {
- switch_caller_profile_t *cp = switch_channel_get_caller_profile(channel);
- if (cp) {
- if (!strncmp(varname, "aleg_", 5)) {
- cp = cp->originator_caller_profile;
- varname += 5;
- } else if (!strncmp(varname, "bleg_", 5)) {
- cp = cp->originatee_caller_profile;
- varname += 5;
- }
- }
- if (!cp || !(v = switch_caller_get_field_by_name(cp, varname))) {
- if ((vdup = switch_core_get_variable_pdup(varname, switch_core_session_get_pool(channel->session)))) {
- v = vdup;
- }
- }
- }
- }
- if (dup && v != vdup) {
- if (v) {
- r = switch_core_session_strdup(channel->session, v);
- }
- } else {
- r = v;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return r;
- }
- SWITCH_DECLARE(const char *) switch_channel_get_variable_strdup(switch_channel_t *channel, const char *varname)
- {
- const char *value = switch_channel_get_variable_dup(channel, varname, SWITCH_FALSE, -1);
- return value ? (const char *)strdup(value) : NULL;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_get_variable_buf(switch_channel_t *channel, const char *varname, char *buf, switch_size_t buflen)
- {
- const char *value = switch_channel_get_variable_dup(channel, varname, SWITCH_FALSE, -1);
- if (value && buf && buflen && switch_copy_string(buf, value, buflen)) {
- return SWITCH_STATUS_SUCCESS;
- }
- return SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(const char *) switch_channel_get_variable_partner(switch_channel_t *channel, const char *varname)
- {
- const char *uuid;
- const char *val = NULL, *r = NULL;
- switch_assert(channel != NULL);
- if (!zstr(varname)) {
- if ((uuid = switch_channel_get_partner_uuid(channel))) {
- switch_core_session_t *session;
- if ((session = switch_core_session_locate(uuid))) {
- switch_channel_t *tchannel = switch_core_session_get_channel(session);
- val = switch_channel_get_variable(tchannel, varname);
- switch_core_session_rwunlock(session);
- }
- }
- }
- if (val)
- r = switch_core_session_strdup(channel->session, val);
- return r;
- }
- SWITCH_DECLARE(void) switch_channel_variable_last(switch_channel_t *channel)
- {
- switch_assert(channel != NULL);
- if (!channel->vi) {
- return;
- }
- channel->vi = 0;
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(switch_event_header_t *) switch_channel_variable_first(switch_channel_t *channel)
- {
- switch_event_header_t *hi = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->variables && (hi = channel->variables->headers)) {
- channel->vi = 1;
- } else {
- switch_mutex_unlock(channel->profile_mutex);
- }
- return hi;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
- {
- switch_assert(channel != NULL);
- switch_core_hash_insert_locked(channel->private_hash, key, private_info, channel->profile_mutex);
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(void *) switch_channel_get_private(switch_channel_t *channel, const char *key)
- {
- void *val;
- switch_assert(channel != NULL);
- val = switch_core_hash_find_locked(channel->private_hash, key, channel->profile_mutex);
- return val;
- }
- SWITCH_DECLARE(void *) switch_channel_get_private_partner(switch_channel_t *channel, const char *key)
- {
- const char *uuid;
- void *val = NULL;
- switch_assert(channel != NULL);
- if ((uuid = switch_channel_get_partner_uuid(channel))) {
- switch_core_session_t *session;
- if ((session = switch_core_session_locate(uuid))) {
- val = switch_core_hash_find_locked(channel->private_hash, key, channel->profile_mutex);
- switch_core_session_rwunlock(session);
- }
- }
- return val;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_name(switch_channel_t *channel, const char *name)
- {
- const char *old = NULL;
- switch_assert(channel != NULL);
- if (!zstr(channel->name)) {
- old = channel->name;
- }
- channel->name = NULL;
- if (name) {
- char *uuid = switch_core_session_get_uuid(channel->session);
- channel->name = switch_core_session_strdup(channel->session, name);
- switch_channel_set_variable(channel, SWITCH_CHANNEL_NAME_VARIABLE, name);
- if (old) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Rename Channel %s->%s [%s]\n", old, name, uuid);
- } else {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "New Channel %s [%s]\n", name, uuid);
- }
- }
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(char *) switch_channel_get_name(switch_channel_t *channel)
- {
- switch_assert(channel != NULL);
- return (!zstr(channel->name)) ? channel->name : "N/A";
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_profile_var(switch_channel_t *channel, const char *name, const char *val)
- {
- char *v;
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_mutex_lock(channel->profile_mutex);
- if (!strcasecmp(name, "device_id") && !zstr(val)) {
- const char *device_id;
- if (!(device_id = switch_channel_set_device_id(channel, val))) {
- /* one time setting */
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- val = device_id;
- }
- if (!zstr(val)) {
- v = switch_core_strdup(channel->caller_profile->pool, val);
- } else {
- v = SWITCH_BLANK_STRING;
- }
- if (!strcasecmp(name, "dialplan")) {
- channel->caller_profile->dialplan = v;
- } else if (!strcasecmp(name, "username")) {
- channel->caller_profile->username = v;
- } else if (!strcasecmp(name, "caller_id_name")) {
- channel->caller_profile->caller_id_name = v;
- } else if (!strcasecmp(name, "caller_id_number")) {
- channel->caller_profile->caller_id_number = v;
- } else if (!strcasecmp(name, "callee_id_name")) {
- channel->caller_profile->callee_id_name = v;
- } else if (!strcasecmp(name, "callee_id_number")) {
- channel->caller_profile->callee_id_number = v;
- } else if (val && !strcasecmp(name, "caller_ton")) {
- channel->caller_profile->caller_ton = (uint8_t) atoi(v);
- } else if (val && !strcasecmp(name, "caller_numplan")) {
- channel->caller_profile->caller_numplan = (uint8_t) atoi(v);
- } else if (val && !strcasecmp(name, "destination_number_ton")) {
- channel->caller_profile->destination_number_ton = (uint8_t) atoi(v);
- } else if (val && !strcasecmp(name, "destination_number_numplan")) {
- channel->caller_profile->destination_number_numplan = (uint8_t) atoi(v);
- } else if (!strcasecmp(name, "ani")) {
- channel->caller_profile->ani = v;
- } else if (!strcasecmp(name, "aniii")) {
- channel->caller_profile->aniii = v;
- } else if (!strcasecmp(name, "network_addr")) {
- channel->caller_profile->network_addr = v;
- } else if (!strcasecmp(name, "rdnis")) {
- channel->caller_profile->rdnis = v;
- } else if (!strcasecmp(name, "destination_number")) {
- channel->caller_profile->destination_number = v;
- } else if (!strcasecmp(name, "uuid")) {
- channel->caller_profile->uuid = v;
- } else if (!strcasecmp(name, "source")) {
- channel->caller_profile->source = v;
- } else if (!strcasecmp(name, "context")) {
- channel->caller_profile->context = v;
- } else if (!strcasecmp(name, "chan_name")) {
- channel->caller_profile->chan_name = v;
- } else {
- profile_node_t *pn, *n = switch_core_alloc(channel->caller_profile->pool, sizeof(*n));
- int var_found;
- n->var = switch_core_strdup(channel->caller_profile->pool, name);
- n->val = v;
- if (!channel->caller_profile->soft) {
- channel->caller_profile->soft = n;
- } else {
- var_found = 0;
- for(pn = channel->caller_profile->soft; pn ; pn = pn->next) {
- if (!strcasecmp(pn->var,n->var)) {
- pn->val = n->val;
- var_found = 1;
- break;
- }
- if(!pn->next) {
- break;
- }
- }
- if (pn && !pn->next && !var_found) {
- pn->next = n;
- }
- }
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(void) switch_channel_process_export(switch_channel_t *channel, switch_channel_t *peer_channel,
- switch_event_t *var_event, const char *export_varname)
- {
- const char *export_vars = switch_channel_get_variable(channel, export_varname);
- char *cptmp = switch_core_session_strdup(channel->session, export_vars);
- int argc;
- char *argv[256];
- if (zstr(export_vars)) return;
- if (var_event) {
- switch_event_del_header(var_event, export_varname);
- switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, export_varname, export_vars);
- }
- if (peer_channel) {
- switch_channel_set_variable(peer_channel, export_varname, export_vars);
- }
- if ((argc = switch_separate_string(cptmp, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
- int x;
- for (x = 0; x < argc; x++) {
- const char *vval;
- if ((vval = switch_channel_get_variable(channel, argv[x]))) {
- char *vvar = argv[x];
- if (!strncasecmp(vvar, "nolocal:", 8)) { /* remove this later ? */
- vvar += 8;
- } else if (!strncasecmp(vvar, "_nolocal_", 9)) {
- vvar += 9;
- }
- if (var_event) {
- switch_event_del_header(var_event, vvar);
- switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, vvar, vval);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_DEBUG,
- "%s EXPORTING[%s] [%s]=[%s] to event\n",
- switch_channel_get_name(channel),
- export_varname,
- vvar, vval);
- }
- if (peer_channel) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_DEBUG,
- "%s EXPORTING[%s] [%s]=[%s] to %s\n",
- switch_channel_get_name(channel),
- export_varname,
- vvar, vval, switch_channel_get_name(peer_channel));
- switch_channel_set_variable(peer_channel, vvar, vval);
- }
- }
- }
- }
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_var_check(switch_channel_t *channel,
- const char *varname, const char *val,
- const char *export_varname, switch_bool_t var_check)
- {
- char *var_name = NULL;
- const char *exports;
- char *var, *new_exports, *new_exports_d = NULL;
- int local = 1;
- exports = switch_channel_get_variable(channel, export_varname);
- var = switch_core_session_strdup(channel->session, varname);
- if (var) {
- if (!strncasecmp(var, "nolocal:", 8)) { /* remove this later ? */
- var_name = var + 8;
- local = 0;
- } else if (!strncasecmp(var, "_nolocal_", 9)) {
- var_name = var + 9;
- local = 0;
- } else {
- var_name = var;
- }
- }
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_DEBUG, "EXPORT (%s) %s[%s]=[%s]\n",
- export_varname, local ? "" : "(REMOTE ONLY) ",
- var_name ? var_name : "", val ? val : "UNDEF");
- switch_channel_set_variable_var_check(channel, var, val, var_check);
- if (var && val) {
- if (exports) {
- new_exports_d = switch_mprintf("%s,%s", exports, var);
- new_exports = new_exports_d;
- } else {
- new_exports = var;
- }
- switch_channel_set_variable(channel, export_varname, new_exports);
- switch_safe_free(new_exports_d);
- }
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_printf(switch_channel_t *channel, const char *varname,
- const char *export_varname, const char *fmt, ...)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- char *data = NULL;
- va_list ap;
- int ret;
- switch_assert(channel != NULL);
- va_start(ap, fmt);
- ret = switch_vasprintf(&data, fmt, ap);
- va_end(ap);
- if (ret == -1) {
- return SWITCH_STATUS_FALSE;
- }
- status = switch_channel_export_variable(channel, varname, data, export_varname);
- free(data);
- return status;
- }
- SWITCH_DECLARE(uint32_t) switch_channel_del_variable_prefix(switch_channel_t *channel, const char *prefix)
- {
- switch_event_t *event;
- switch_event_header_t *hp;
- uint32_t r = 0;
- switch_channel_get_variables(channel, &event);
- if (event) {
- for (hp = event->headers; hp; hp = hp->next) {
- if (zstr(prefix) || !strncasecmp(hp->name, prefix, strlen(prefix))) {
- switch_channel_set_variable(channel, hp->name, NULL);
- }
- }
- }
- switch_event_destroy(&event);
- return r;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_transfer_variable_prefix(switch_channel_t *orig_channel, switch_channel_t *new_channel, const char *prefix)
- {
- switch_event_header_t *hi = NULL;
- int x = 0;
- if ((hi = switch_channel_variable_first(orig_channel))) {
- for (; hi; hi = hi->next) {
- char *var = hi->name;
- char *val = hi->value;
- if (zstr(prefix) || !strncasecmp(var, prefix, strlen(prefix))) {
- x++;
- switch_channel_set_variable(new_channel, var, val);
- }
- }
- switch_channel_variable_last(orig_channel);
- }
- return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(void) switch_channel_set_presence_data_vals(switch_channel_t *channel, const char *presence_data_cols)
- {
- char *cols[128] = { 0 };
- char header_name[128] = "";
- int col_count = 0, i = 0;
- char *data_copy = NULL;
- if (zstr(presence_data_cols)) {
- presence_data_cols = switch_channel_get_variable_dup(channel, "presence_data_cols", SWITCH_FALSE, -1);
- if (zstr(presence_data_cols)) {
- return;
- }
- }
- data_copy = strdup(presence_data_cols);
- col_count = switch_split(data_copy, ':', cols);
- for (i = 0; i < col_count; i++) {
- const char *val = NULL;
- switch_snprintf(header_name, sizeof(header_name), "PD-%s", cols[i]);
- val = switch_channel_get_variable(channel, cols[i]);
- switch_channel_set_profile_var(channel, header_name, val);
- }
- switch_safe_free(data_copy);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_log_tag(switch_channel_t *channel, const char *tagname, const char *tagvalue)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (!zstr(tagname)) {
- if (!channel->log_tags) {
- switch_event_create_plain(&channel->log_tags, SWITCH_EVENT_CHANNEL_DATA);
- }
- if (zstr(tagvalue)) {
- switch_event_del_header(channel->log_tags, tagname);
- } else {
- switch_event_add_header_string(channel->log_tags, SWITCH_STACK_BOTTOM, tagname, tagvalue);
- }
- status = SWITCH_STATUS_SUCCESS;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_get_log_tags(switch_channel_t *channel, switch_event_t **log_tags)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_assert(channel != NULL);
- if (!channel->log_tags) {
- return status;
- }
- switch_mutex_lock(channel->profile_mutex);
- if (channel->log_tags && log_tags) {
- status = switch_event_dup(log_tags, channel->log_tags);
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_channel_t *channel,
- const char *varname, const char *value, switch_bool_t var_check)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->variables && !zstr(varname)) {
- if (zstr(value)) {
- switch_event_del_header(channel->variables, varname);
- } else {
- int ok = 1;
- if (var_check) {
- ok = !switch_string_var_check_const(value);
- }
- if (ok) {
- switch_event_add_header_string(channel->variables, SWITCH_STACK_BOTTOM, varname, value);
- } else {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Invalid data (${%s} contains a variable)\n", varname);
- }
- }
- status = SWITCH_STATUS_SUCCESS;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_strip_quotes_var_check(switch_channel_t *channel,
- const char *varname, const char *value, switch_bool_t var_check)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->variables && !zstr(varname)) {
- if (zstr(value)) {
- switch_event_del_header(channel->variables, varname);
- } else {
- int ok = 1;
- char *t = (char *)value;
- char *r = (char *)value;
- char *tmp = NULL;
- if (t && *t == '"') {
- t++;
- if (end_of(t) == '"') {
- r = tmp = strdup(t);
- switch_assert(r);
- end_of(r) = '\0';
- }
- }
- if (var_check) {
- ok = !switch_string_var_check_const(r);
- }
- if (ok) {
- switch_event_add_header_string(channel->variables, SWITCH_STACK_BOTTOM, varname, r);
- } else {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Invalid data (${%s} contains a variable)\n", varname);
- }
- switch_safe_free(tmp);
- }
- status = SWITCH_STATUS_SUCCESS;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_add_variable_var_check(switch_channel_t *channel,
- const char *varname, const char *value, switch_bool_t var_check, switch_stack_t stack)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->variables && !zstr(varname)) {
- if (zstr(value)) {
- switch_event_del_header(channel->variables, varname);
- } else {
- int ok = 1;
- if (var_check) {
- ok = !switch_string_var_check_const(value);
- }
- if (ok) {
- switch_event_add_header_string(channel->variables, stack, varname, value);
- } else {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Invalid data (${%s} contains a variable)\n", varname);
- }
- }
- status = SWITCH_STATUS_SUCCESS;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data);
- SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt, ...)
- {
- int ret = 0;
- char *data;
- va_list ap;
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->variables && !zstr(varname)) {
- switch_event_del_header(channel->variables, varname);
- va_start(ap, fmt);
- ret = switch_vasprintf(&data, fmt, ap);
- va_end(ap);
- if (ret == -1) {
- switch_mutex_unlock(channel->profile_mutex);
- return SWITCH_STATUS_MEMERR;
- }
- status = switch_channel_set_variable(channel, varname, data);
- free(data);
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt, ...)
- {
- int ret = 0;
- char *varname;
- va_list ap;
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- va_start(ap, fmt);
- ret = switch_vasprintf(&varname, fmt, ap);
- va_end(ap);
- if (ret == -1) {
- switch_mutex_unlock(channel->profile_mutex);
- return SWITCH_STATUS_MEMERR;
- }
- status = switch_channel_set_variable(channel, varname, val);
- free(varname);
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_partner_var_check(switch_channel_t *channel,
- const char *varname, const char *value, switch_bool_t var_check)
- {
- const char *uuid;
- switch_assert(channel != NULL);
- if (!zstr(varname)) {
- if ((uuid = switch_channel_get_partner_uuid(channel))) {
- switch_core_session_t *session;
- if ((session = switch_core_session_locate(uuid))) {
- switch_channel_t *tchannel = switch_core_session_get_channel(session);
- switch_channel_set_variable_var_check(tchannel, varname, value, var_check);
- switch_core_session_rwunlock(session);
- }
- return SWITCH_STATUS_SUCCESS;
- }
- }
- return SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(uint32_t) switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- uint32_t r = 0;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- r = channel->flags[flag];
- switch_mutex_unlock(channel->flag_mutex);
- return r;
- }
- SWITCH_DECLARE(switch_bool_t) switch_channel_set_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- const char *uuid;
- switch_assert(channel != NULL);
- if ((uuid = switch_channel_get_partner_uuid(channel))) {
- switch_core_session_t *session;
- if ((session = switch_core_session_locate(uuid))) {
- switch_channel_set_flag(switch_core_session_get_channel(session), flag);
- switch_core_session_rwunlock(session);
- return SWITCH_TRUE;
- }
- }
- return SWITCH_FALSE;
- }
- SWITCH_DECLARE(uint32_t) switch_channel_test_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- const char *uuid;
- int r = 0;
- switch_assert(channel != NULL);
- if ((uuid = switch_channel_get_partner_uuid(channel))) {
- switch_core_session_t *session;
- if ((session = switch_core_session_locate(uuid))) {
- r = switch_channel_test_flag(switch_core_session_get_channel(session), flag);
- switch_core_session_rwunlock(session);
- }
- }
- return r;
- }
- SWITCH_DECLARE(switch_bool_t) switch_channel_clear_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- const char *uuid;
- switch_assert(channel != NULL);
- if ((uuid = switch_channel_get_partner_uuid(channel))) {
- switch_core_session_t *session;
- if ((session = switch_core_session_locate(uuid))) {
- switch_channel_clear_flag(switch_core_session_get_channel(session), flag);
- switch_core_session_rwunlock(session);
- return SWITCH_TRUE;
- }
- }
- return SWITCH_FALSE;
- }
- SWITCH_DECLARE(void) switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
- {
- switch_assert(channel);
- for (;;) {
- if ((channel->state < CS_HANGUP && channel->state == channel->running_state && channel->running_state == want_state) ||
- (other_channel && switch_channel_down_nosig(other_channel)) || switch_channel_down(channel)) {
- break;
- }
- switch_cond_next();
- }
- }
- SWITCH_DECLARE(void) switch_channel_wait_for_state_timeout(switch_channel_t *channel, switch_channel_state_t want_state, uint32_t timeout)
- {
- uint32_t count = 0;
- for (;;) {
- if ((channel->state == channel->running_state && channel->running_state == want_state) || channel->state >= CS_HANGUP) {
- break;
- }
- switch_channel_check_signal(channel, SWITCH_TRUE);
- switch_cond_next();
- if (++count >= timeout) {
- break;
- }
- }
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_wait_for_flag(switch_channel_t *channel,
- switch_channel_flag_t want_flag,
- switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
- {
- if (to) {
- to++;
- }
- for (;;) {
- if (pres) {
- if (switch_channel_test_flag(channel, want_flag)) {
- break;
- }
- } else {
- if (!switch_channel_test_flag(channel, want_flag)) {
- break;
- }
- }
- switch_cond_next();
- if (super_channel && !switch_channel_ready(super_channel)) {
- return SWITCH_STATUS_FALSE;
- }
- if (switch_channel_down(channel)) {
- return SWITCH_STATUS_FALSE;
- }
- if (to && !--to) {
- return SWITCH_STATUS_TIMEOUT;
- }
- }
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_wait_for_app_flag(switch_channel_t *channel,
- uint32_t app_flag,
- const char *key, switch_bool_t pres, uint32_t to)
- {
- int r = 0;
-
- if (to) {
- to++;
- }
- for (;;) {
- if (pres) {
- if ((r = switch_channel_test_app_flag_key(key, channel, app_flag))) {
- break;
- }
- } else {
- if (!(r = switch_channel_test_app_flag_key(key, channel, app_flag))) {
- break;
- }
- }
- switch_cond_next();
- if (switch_channel_down(channel)) {
- return r;
- }
- if (to && !--to) {
- return r;
- }
- }
- return r;
- }
- SWITCH_DECLARE(void) switch_channel_set_cap_value(switch_channel_t *channel, switch_channel_cap_t cap, uint32_t value)
- {
- switch_assert(channel);
- switch_assert(channel->flag_mutex);
- switch_mutex_lock(channel->flag_mutex);
- channel->caps[cap] = value;
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_clear_cap(switch_channel_t *channel, switch_channel_cap_t cap)
- {
- switch_assert(channel != NULL);
- switch_assert(channel->flag_mutex);
- switch_mutex_lock(channel->flag_mutex);
- channel->caps[cap] = 0;
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap)
- {
- switch_assert(channel != NULL);
- return channel->caps[cap] ? 1 : 0;
- }
- SWITCH_DECLARE(uint32_t) switch_channel_test_cap_partner(switch_channel_t *channel, switch_channel_cap_t cap)
- {
- const char *uuid;
- int r = 0;
- switch_assert(channel != NULL);
- if ((uuid = switch_channel_get_partner_uuid(channel))) {
- switch_core_session_t *session;
- if ((session = switch_core_session_locate(uuid))) {
- r = switch_channel_test_cap(switch_core_session_get_channel(session), cap);
- switch_core_session_rwunlock(session);
- }
- }
- return r;
- }
- SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel)
- {
- switch_stream_handle_t stream = { 0 };
- char *r;
- int i = 0;
- SWITCH_STANDARD_STREAM(stream);
- switch_mutex_lock(channel->flag_mutex);
- for (i = 0; i < CF_FLAG_MAX; i++) {
- if (channel->flags[i]) {
- stream.write_function(&stream, "%d=%d;", i, channel->flags[i]);
- }
- }
- switch_mutex_unlock(channel->flag_mutex);
- r = (char *) stream.data;
- if (end_of(r) == ';') {
- end_of(r) = '\0';
- }
- return r;
- }
- SWITCH_DECLARE(char *) switch_channel_get_cap_string(switch_channel_t *channel)
- {
- switch_stream_handle_t stream = { 0 };
- char *r;
- int i = 0;
- SWITCH_STANDARD_STREAM(stream);
- switch_mutex_lock(channel->flag_mutex);
- for (i = 0; i < CC_FLAG_MAX; i++) {
- if (channel->caps[i]) {
- stream.write_function(&stream, "%d=%d;", i, channel->caps[i]);
- }
- }
- switch_mutex_unlock(channel->flag_mutex);
- r = (char *) stream.data;
- if (end_of(r) == ';') {
- end_of(r) = '\0';
- }
- return r;
- }
- SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, switch_channel_flag_t flag, uint32_t value)
- {
- int HELD = 0;
- int just_set = 0;
- switch_assert(channel);
- switch_assert(channel->flag_mutex);
- switch_mutex_lock(channel->flag_mutex);
- if (flag == CF_LEG_HOLDING && !channel->flags[flag] && channel->flags[CF_ANSWERED]) {
- HELD = 1;
- }
- if (channel->flags[flag] != value) {
- just_set = 1;
- channel->flags[flag] = value;
- }
- switch_mutex_unlock(channel->flag_mutex);
- if (flag == CF_VIDEO_READY && just_set) {
- switch_core_session_request_video_refresh(channel->session);
- }
- if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)) {
- switch_channel_set_callstate(channel, CCS_RING_WAIT);
- }
- if (flag == CF_DIALPLAN) {
- if (channel->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND;
- if (channel->device_node) {
- channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND;
- }
- } else {
- channel->logical_direction = SWITCH_CALL_DIRECTION_INBOUND;
- if (channel->device_node) {
- channel->device_node->direction = SWITCH_CALL_DIRECTION_OUTBOUND;
- }
- }
- }
- if (HELD) {
- switch_hold_record_t *hr;
- const char *brto = switch_channel_get_partner_uuid(channel);
- switch_channel_set_callstate(channel, CCS_HELD);
- switch_mutex_lock(channel->profile_mutex);
- channel->caller_profile->times->last_hold = switch_time_now();
- hr = switch_core_session_alloc(channel->session, sizeof(*hr));
- hr->on = switch_time_now();
- if (brto) {
- hr->uuid = switch_core_session_strdup(channel->session, brto);
- }
- if (channel->hold_record) {
- hr->next = channel->hold_record;
- }
- channel->hold_record = hr;
- switch_mutex_unlock(channel->profile_mutex);
- }
- if (flag == CF_OUTBOUND) {
- switch_channel_set_variable(channel, "is_outbound", "true");
- }
- if (flag == CF_RECOVERED) {
- switch_channel_set_variable(channel, "recovered", "true");
- }
- if (flag == CF_VIDEO_ECHO || flag == CF_VIDEO_BLANK || flag == CF_VIDEO_DECODED_READ || flag == CF_VIDEO_PASSIVE) {
- switch_core_session_start_video_thread(channel->session);
- }
- if (flag == CF_VIDEO_DECODED_READ && channel->flags[CF_VIDEO]) {
- switch_core_session_request_video_refresh(channel->session);
- }
- }
- SWITCH_DECLARE(void) switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- switch_assert(channel);
- switch_assert(channel->flag_mutex);
- switch_mutex_lock(channel->flag_mutex);
- channel->flags[flag]++;
- switch_mutex_unlock(channel->flag_mutex);
- if (flag == CF_OUTBOUND) {
- switch_channel_set_variable(channel, "is_outbound", "true");
- }
- if (flag == CF_RECOVERED) {
- switch_channel_set_variable(channel, "recovered", "true");
- }
- }
- SWITCH_DECLARE(void) switch_channel_set_private_flag(switch_channel_t *channel, uint32_t flags)
- {
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- channel->private_flags |= flags;
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_clear_private_flag(switch_channel_t *channel, uint32_t flags)
- {
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- channel->private_flags &= ~flags;
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(int) switch_channel_test_private_flag(switch_channel_t *channel, uint32_t flags)
- {
- switch_assert(channel != NULL);
- return (channel->private_flags & flags);
- }
- SWITCH_DECLARE(void) switch_channel_set_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
- {
- uint32_t *flagp = NULL;
- switch_byte_t new = 0;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- if (!channel->app_flag_hash) {
- switch_core_hash_init(&channel->app_flag_hash);
- new++;
- }
- if (new || !(flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
- flagp = switch_core_session_alloc(channel->session, sizeof(uint32_t));
- switch_core_hash_insert(channel->app_flag_hash, key, flagp);
- }
- switch_assert(flagp);
- *flagp |= flags;
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_clear_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
- {
- uint32_t *flagp = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- if (channel->app_flag_hash && (flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
- if (!flags) {
- *flagp = 0;
- } else {
- *flagp &= ~flags;
- }
- }
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(int) switch_channel_test_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
- {
- int r = 0;
- uint32_t *flagp = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- if (channel->app_flag_hash && (flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
- r = (*flagp & flags);
- }
- switch_mutex_unlock(channel->flag_mutex);
- return r;
- }
- SWITCH_DECLARE(void) switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- channel->state_flags[0] = 1;
- channel->state_flags[flag] = 1;
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_clear_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->flag_mutex);
- channel->state_flags[flag] = 0;
- switch_mutex_unlock(channel->flag_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- int ACTIVE = 0;
- int CLEAR = 0;
- switch_assert(channel != NULL);
- switch_assert(channel->flag_mutex);
- switch_mutex_lock(channel->flag_mutex);
- if (flag == CF_LEG_HOLDING && channel->flags[flag] && channel->flags[CF_ANSWERED]) {
- ACTIVE = 1;
- }
- if (flag == CF_VIDEO_PASSIVE && channel->flags[CF_VIDEO]) {
- channel->flags[CF_VIDEO_READY] = 1;
- if (channel->flags[flag]) {
- CLEAR = 1;
- }
- }
- channel->flags[flag] = 0;
- switch_mutex_unlock(channel->flag_mutex);
- if (flag == CF_DIALPLAN) {
- if (channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
- channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND;
- if (channel->device_node) {
- channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND;
- }
- }
- }
- if (ACTIVE) {
- switch_channel_set_callstate(channel, CCS_UNHELD);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile->times->last_hold) {
- channel->caller_profile->times->hold_accum += (switch_time_now() - channel->caller_profile->times->last_hold);
- }
- if (channel->hold_record) {
- channel->hold_record->off = switch_time_now();
- }
- if (switch_channel_test_flag(channel, CF_PROXY_MODE) && switch_channel_test_flag(channel, CF_BRIDGED)) {
- switch_channel_set_callstate(channel, CCS_ACTIVE);
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)) {
- switch_channel_set_callstate(channel, CCS_ACTIVE);
- }
- if (flag == CF_OUTBOUND) {
- switch_channel_set_variable(channel, "is_outbound", NULL);
- }
- if (flag == CF_RECOVERED) {
- switch_channel_set_variable(channel, "recovered", NULL);
- }
- if (flag == CF_VIDEO_PASSIVE && CLEAR) {
- switch_core_session_wake_video_thread(channel->session);
- }
- if (flag == CF_RECOVERING && !channel->hangup_cause && !switch_channel_test_flag(channel, CF_NO_RECOVER)) {
- switch_core_recovery_track(channel->session);
- }
- }
- SWITCH_DECLARE(void) switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
- {
- switch_assert(channel != NULL);
- switch_assert(channel->flag_mutex);
- switch_mutex_lock(channel->flag_mutex);
- if (channel->flags[flag]) {
- channel->flags[flag]--;
- }
- switch_mutex_unlock(channel->flag_mutex);
- if (flag == CF_OUTBOUND) {
- switch_channel_set_variable(channel, "is_outbound", NULL);
- }
- }
- SWITCH_DECLARE(switch_channel_state_t) switch_channel_get_state(switch_channel_t *channel)
- {
- switch_channel_state_t state;
- switch_assert(channel != NULL);
- state = channel->state;
- return state;
- }
- SWITCH_DECLARE(switch_channel_state_t) switch_channel_get_running_state(switch_channel_t *channel)
- {
- switch_channel_state_t state;
- switch_assert(channel != NULL);
- state = channel->running_state;
- return state;
- }
- SWITCH_DECLARE(int) switch_channel_state_change_pending(switch_channel_t *channel)
- {
- if (switch_channel_down_nosig(channel) || !switch_core_session_in_thread(channel->session)) {
- return 0;
- }
- return channel->running_state != channel->state;
- }
- SWITCH_DECLARE(int) switch_channel_check_signal(switch_channel_t *channel, switch_bool_t in_thread_only)
- {
- switch_ivr_parse_signal_data(channel->session, SWITCH_FALSE, in_thread_only);
- return 0;
- }
- SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_bool_t check_ready, switch_bool_t check_media)
- {
- int ret = 0;
- switch_assert(channel != NULL);
- switch_channel_check_signal(channel, SWITCH_TRUE);
- if (check_media) {
- ret = ((switch_channel_test_flag(channel, CF_ANSWERED) ||
- switch_channel_test_flag(channel, CF_EARLY_MEDIA)) && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
- switch_core_session_get_read_codec(channel->session) && switch_core_session_get_write_codec(channel->session));
- if (!ret)
- return ret;
- }
- if (!check_ready)
- return ret;
- ret = 0;
- if (!channel->hangup_cause && channel->state > CS_ROUTING && channel->state < CS_HANGUP && channel->state != CS_RESET &&
- !switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_NOT_READY) &&
- !switch_channel_state_change_pending(channel)) {
- ret++;
- }
- return ret;
- }
- static const char *state_names[] = {
- "CS_NEW",
- "CS_INIT",
- "CS_ROUTING",
- "CS_SOFT_EXECUTE",
- "CS_EXECUTE",
- "CS_EXCHANGE_MEDIA",
- "CS_PARK",
- "CS_CONSUME_MEDIA",
- "CS_HIBERNATE",
- "CS_RESET",
- "CS_HANGUP",
- "CS_REPORTING",
- "CS_DESTROY",
- "CS_NONE",
- NULL
- };
- SWITCH_DECLARE(const char *) switch_channel_state_name(switch_channel_state_t state)
- {
- return state_names[state];
- }
- SWITCH_DECLARE(switch_channel_state_t) switch_channel_name_state(const char *name)
- {
- uint32_t x = 0;
- for (x = 0; state_names[x]; x++) {
- if (!strcasecmp(state_names[x], name)) {
- return (switch_channel_state_t) x;
- }
- }
- return CS_DESTROY;
- }
- static inline void careful_set(switch_channel_t *channel, switch_channel_state_t *state, switch_channel_state_t val) {
- if (switch_mutex_trylock(channel->thread_mutex) == SWITCH_STATUS_SUCCESS) {
- *state = val;
- switch_mutex_unlock(channel->thread_mutex);
- } else {
- switch_mutex_t *mutex = switch_core_session_get_mutex(channel->session);
- int x = 0;
- for (x = 0; x < 100; x++) {
- if (switch_mutex_trylock(mutex) == SWITCH_STATUS_SUCCESS) {
- *state = val;
- switch_mutex_unlock(mutex);
- break;
- } else {
- switch_cond_next();
- }
- }
- if (x == 100) {
- *state = val;
- }
- }
- }
- SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state(switch_channel_t *channel, switch_channel_state_t state,
- const char *file, const char *func, int line)
- {
- int x;
- switch_mutex_lock(channel->flag_mutex);
- if (channel->state_flags[0]) {
- for (x = 1; x < CF_FLAG_MAX; x++) {
- if (channel->state_flags[x]) {
- channel->flags[x] = 1;
- channel->state_flags[x] = 0;
- }
- }
- channel->state_flags[0] = 0;
- }
- switch_mutex_unlock(channel->flag_mutex);
- switch_channel_clear_flag(channel, CF_TAGGED);
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) Running State Change %s (Cur %d Tot %" SWITCH_SIZE_T_FMT ")\n",
- channel->name, state_names[state], switch_core_session_count(), switch_core_session_id() - 1);
- switch_mutex_lock(channel->state_mutex);
- careful_set(channel, &channel->running_state, state);
- if (state <= CS_DESTROY) {
- switch_event_t *event;
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
- if (state < CS_HANGUP) {
- if (state == CS_ROUTING) {
- switch_channel_set_callstate(channel, CCS_RINGING);
- } else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
- switch_channel_set_callstate(channel, CCS_ACTIVE);
- } else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
- switch_channel_set_callstate(channel, CCS_EARLY);
- }
- }
- }
- if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- }
- switch_mutex_unlock(channel->state_mutex);
- return (switch_channel_state_t) SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_channel_t *channel,
- const char *file, const char *func, int line, switch_channel_state_t state)
- {
- switch_channel_state_t last_state;
- int ok = 0;
- switch_assert(channel != NULL);
- switch_assert(state <= CS_DESTROY);
- switch_mutex_lock(channel->state_mutex);
- last_state = channel->state;
- switch_assert(last_state <= CS_DESTROY);
- if (last_state == state) {
- goto done;
- }
- if (last_state >= CS_HANGUP && state < last_state) {
- goto done;
- }
- /* STUB for more dev
- case CS_INIT:
- switch(state) {
- case CS_NEW:
- case CS_INIT:
- case CS_EXCHANGE_MEDIA:
- case CS_SOFT_EXECUTE:
- case CS_ROUTING:
- case CS_EXECUTE:
- case CS_HANGUP:
- case CS_DESTROY:
- default:
- break;
- }
- break;
- */
- switch (last_state) {
- case CS_NEW:
- case CS_RESET:
- switch (state) {
- default:
- ok++;
- break;
- }
- break;
- case CS_INIT:
- switch (state) {
- case CS_EXCHANGE_MEDIA:
- case CS_SOFT_EXECUTE:
- case CS_ROUTING:
- case CS_EXECUTE:
- case CS_PARK:
- case CS_CONSUME_MEDIA:
- case CS_HIBERNATE:
- case CS_RESET:
- ok++;
- default:
- break;
- }
- break;
- case CS_EXCHANGE_MEDIA:
- switch (state) {
- case CS_SOFT_EXECUTE:
- case CS_ROUTING:
- case CS_EXECUTE:
- case CS_PARK:
- case CS_CONSUME_MEDIA:
- case CS_HIBERNATE:
- case CS_RESET:
- ok++;
- default:
- break;
- }
- break;
- case CS_SOFT_EXECUTE:
- switch (state) {
- case CS_EXCHANGE_MEDIA:
- case CS_ROUTING:
- case CS_EXECUTE:
- case CS_PARK:
- case CS_CONSUME_MEDIA:
- case CS_HIBERNATE:
- case CS_RESET:
- ok++;
- default:
- break;
- }
- break;
- case CS_PARK:
- switch (state) {
- case CS_EXCHANGE_MEDIA:
- case CS_ROUTING:
- case CS_EXECUTE:
- case CS_SOFT_EXECUTE:
- case CS_HIBERNATE:
- case CS_RESET:
- case CS_CONSUME_MEDIA:
- ok++;
- default:
- break;
- }
- break;
- case CS_CONSUME_MEDIA:
- switch (state) {
- case CS_EXCHANGE_MEDIA:
- case CS_ROUTING:
- case CS_EXECUTE:
- case CS_SOFT_EXECUTE:
- case CS_HIBERNATE:
- case CS_RESET:
- case CS_PARK:
- ok++;
- default:
- break;
- }
- break;
- case CS_HIBERNATE:
- switch (state) {
- case CS_EXCHANGE_MEDIA:
- case CS_INIT:
- case CS_ROUTING:
- case CS_EXECUTE:
- case CS_SOFT_EXECUTE:
- case CS_PARK:
- case CS_CONSUME_MEDIA:
- case CS_RESET:
- ok++;
- default:
- break;
- }
- break;
- case CS_ROUTING:
- switch (state) {
- case CS_EXCHANGE_MEDIA:
- case CS_EXECUTE:
- case CS_SOFT_EXECUTE:
- case CS_PARK:
- case CS_CONSUME_MEDIA:
- case CS_HIBERNATE:
- case CS_RESET:
- ok++;
- default:
- break;
- }
- break;
- case CS_EXECUTE:
- switch (state) {
- case CS_EXCHANGE_MEDIA:
- case CS_SOFT_EXECUTE:
- case CS_ROUTING:
- case CS_PARK:
- case CS_CONSUME_MEDIA:
- case CS_HIBERNATE:
- case CS_RESET:
- ok++;
- default:
- break;
- }
- break;
- case CS_HANGUP:
- switch (state) {
- case CS_REPORTING:
- case CS_DESTROY:
- ok++;
- default:
- break;
- }
- break;
- case CS_REPORTING:
- switch (state) {
- case CS_DESTROY:
- ok++;
- default:
- break;
- }
- break;
- default:
- break;
- }
- if (ok) {
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) State Change %s -> %s\n",
- channel->name, state_names[last_state], state_names[state]);
- careful_set(channel, &channel->state, state);
- if (state == CS_HANGUP && !channel->hangup_cause) {
- channel->hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING;
- }
- if (state <= CS_DESTROY) {
- switch_core_session_signal_state_change(channel->session);
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_WARNING,
- "(%s) Invalid State Change %s -> %s\n", channel->name, state_names[last_state], state_names[state]);
- /* we won't tolerate an invalid state change so we can make sure we are as robust as a nice cup of dark coffee! */
- /* not cool lets crash this bad boy and figure out wtf is going on */
- switch_assert(channel->state >= CS_HANGUP);
- }
- done:
- switch_mutex_unlock(channel->state_mutex);
- return channel->state;
- }
- SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel)
- {
- switch_mutex_lock(channel->thread_mutex);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_state_thread_trylock(switch_channel_t *channel)
- {
- return switch_mutex_trylock(channel->thread_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel)
- {
- switch_mutex_unlock(channel->thread_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *channel, switch_event_t *event)
- {
- switch_caller_profile_t *caller_profile, *originator_caller_profile = NULL, *originatee_caller_profile = NULL;
- switch_codec_implementation_t impl = { 0 };
- char state_num[25];
- const char *v;
- switch_mutex_lock(channel->profile_mutex);
- if ((caller_profile = channel->caller_profile)) {
- originator_caller_profile = caller_profile->originator_caller_profile;
- originatee_caller_profile = caller_profile->originatee_caller_profile;
- }
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(channel->running_state));
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate));
- switch_snprintf(state_num, sizeof(state_num), "%d", channel->state);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", state_num);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Name", switch_channel_get_name(channel));
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(channel->session));
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Session-External-ID", switch_core_session_get_external_id(channel->session));
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Direction",
- channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Call-Direction",
- channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-HIT-Dialplan",
- switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND ||
- switch_channel_test_flag(channel, CF_DIALPLAN) ? "true" : "false");
- if ((v = switch_channel_get_variable_dup(channel, "presence_id", SWITCH_FALSE, -1))) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-ID", v);
- }
- if ((v = switch_channel_get_variable_dup(channel, "presence_data", SWITCH_FALSE, -1))) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-Data", v);
- }
- if ((v = switch_channel_get_variable_dup(channel, "presence_data_cols", SWITCH_FALSE, -1))) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Data-Cols", v);
- switch_event_add_presence_data_cols(channel, event, "PD-");
- }
- if ((v = switch_channel_get_variable_dup(channel, "call_uuid", SWITCH_FALSE, -1))) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", v);
- } else {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", switch_core_session_get_uuid(channel->session));
- }
- if (switch_channel_down_nosig(channel)) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "hangup");
- } else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered");
- } else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "early");
- } else {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing");
- }
- if (channel->hangup_cause) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(channel->hangup_cause));
- }
- switch_core_session_get_read_impl(channel->session, &impl);
- if (impl.iananame) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Name", impl.iananame);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Rate", "%u", impl.actual_samples_per_second);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Bit-Rate", "%d", impl.bits_per_second);
- }
- switch_core_session_get_write_impl(channel->session, &impl);
- if (impl.iananame) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", impl.iananame);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%u", impl.actual_samples_per_second);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Bit-Rate", "%d", impl.bits_per_second);
- }
- /* Index Caller's Profile */
- if (caller_profile) {
- switch_caller_profile_event_set_data(caller_profile, "Caller", event);
- }
- /* Index Originator/ee's Profile */
- if (originator_caller_profile && channel->last_profile_type == LP_ORIGINATOR) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originator");
- switch_caller_profile_event_set_data(originator_caller_profile, "Other-Leg", event);
- } else if (originatee_caller_profile && channel->last_profile_type == LP_ORIGINATEE) { /* Index Originatee's Profile */
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originatee");
- switch_caller_profile_event_set_data(originatee_caller_profile, "Other-Leg", event);
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_event_set_extended_data(switch_channel_t *channel, switch_event_t *event)
- {
- switch_event_header_t *hi;
- int global_verbose_events = -1;
- switch_mutex_lock(channel->profile_mutex);
- switch_core_session_ctl(SCSC_VERBOSE_EVENTS, &global_verbose_events);
- if (global_verbose_events ||
- switch_channel_test_flag(channel, CF_VERBOSE_EVENTS) ||
- switch_event_get_header(event, "presence-data-cols") ||
- event->event_id == SWITCH_EVENT_CHANNEL_CREATE ||
- event->event_id == SWITCH_EVENT_CHANNEL_ORIGINATE ||
- event->event_id == SWITCH_EVENT_CHANNEL_UUID ||
- event->event_id == SWITCH_EVENT_CHANNEL_ANSWER ||
- event->event_id == SWITCH_EVENT_CHANNEL_PARK ||
- event->event_id == SWITCH_EVENT_CHANNEL_UNPARK ||
- event->event_id == SWITCH_EVENT_CHANNEL_BRIDGE ||
- event->event_id == SWITCH_EVENT_CHANNEL_UNBRIDGE ||
- event->event_id == SWITCH_EVENT_CHANNEL_PROGRESS ||
- event->event_id == SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA ||
- event->event_id == SWITCH_EVENT_CHANNEL_HANGUP ||
- event->event_id == SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE ||
- event->event_id == SWITCH_EVENT_REQUEST_PARAMS ||
- event->event_id == SWITCH_EVENT_CHANNEL_DATA ||
- event->event_id == SWITCH_EVENT_CHANNEL_EXECUTE ||
- event->event_id == SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE ||
- event->event_id == SWITCH_EVENT_CHANNEL_DESTROY ||
- event->event_id == SWITCH_EVENT_SESSION_HEARTBEAT ||
- event->event_id == SWITCH_EVENT_API ||
- event->event_id == SWITCH_EVENT_RECORD_START ||
- event->event_id == SWITCH_EVENT_RECORD_STOP ||
- event->event_id == SWITCH_EVENT_PLAYBACK_START ||
- event->event_id == SWITCH_EVENT_PLAYBACK_STOP ||
- event->event_id == SWITCH_EVENT_CALL_UPDATE ||
- event->event_id == SWITCH_EVENT_MEDIA_BUG_START ||
- event->event_id == SWITCH_EVENT_MEDIA_BUG_STOP ||
- event->event_id == SWITCH_EVENT_CHANNEL_HOLD ||
- event->event_id == SWITCH_EVENT_CHANNEL_UNHOLD ||
- event->event_id == SWITCH_EVENT_TEXT ||
- event->event_id == SWITCH_EVENT_CUSTOM) {
- /* Index Variables */
- if (channel->scope_variables) {
- switch_event_t *ep;
- for (ep = channel->scope_variables; ep; ep = ep->next) {
- for (hi = ep->headers; hi; hi = hi->next) {
- char buf[1024];
- char *vvar = NULL, *vval = NULL;
- vvar = (char *) hi->name;
- vval = (char *) hi->value;
- switch_assert(vvar && vval);
- switch_snprintf(buf, sizeof(buf), "scope_variable_%s", vvar);
- if (!switch_event_get_header(event, buf)) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, buf, vval);
- }
- }
- }
- }
- if (channel->variables) {
- for (hi = channel->variables->headers; hi; hi = hi->next) {
- char buf[1024];
- char *vvar = NULL, *vval = NULL;
- vvar = (char *) hi->name;
- vval = (char *) hi->value;
- switch_assert(vvar && vval);
- switch_snprintf(buf, sizeof(buf), "variable_%s", vvar);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, buf, vval);
- }
- }
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_event_set_data(switch_channel_t *channel, switch_event_t *event)
- {
- switch_mutex_lock(channel->profile_mutex);
- switch_channel_event_set_basic_data(channel, event);
- switch_channel_event_set_extended_data(channel, event);
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_step_caller_profile(switch_channel_t *channel)
- {
- switch_caller_profile_t *cp;
- switch_mutex_lock(channel->profile_mutex);
- cp = switch_caller_profile_clone(channel->session, channel->caller_profile);
- switch_mutex_unlock(channel->profile_mutex);
- switch_channel_set_caller_profile(channel, cp);
- }
- SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
- {
- char *uuid = NULL;
- switch_assert(channel != NULL);
- switch_assert(channel->session != NULL);
- switch_mutex_lock(channel->profile_mutex);
- switch_assert(caller_profile != NULL);
- caller_profile->direction = channel->direction;
- caller_profile->logical_direction = channel->logical_direction;
- uuid = switch_core_session_get_uuid(channel->session);
- if (!caller_profile->uuid || strcasecmp(caller_profile->uuid, uuid)) {
- caller_profile->uuid = switch_core_session_strdup(channel->session, uuid);
- }
- if (!caller_profile->chan_name || strcasecmp(caller_profile->chan_name, channel->name)) {
- caller_profile->chan_name = switch_core_session_strdup(channel->session, channel->name);
- }
- if (!caller_profile->context) {
- caller_profile->context = switch_core_session_strdup(channel->session, "default");
- }
- if (!caller_profile->times) {
- caller_profile->times = (switch_channel_timetable_t *) switch_core_session_alloc(channel->session, sizeof(*caller_profile->times));
- caller_profile->times->profile_created = switch_micro_time_now();
- }
- if (channel->caller_profile && channel->caller_profile->times) {
- channel->caller_profile->times->transferred = caller_profile->times->profile_created;
- caller_profile->times->answered = channel->caller_profile->times->answered;
- caller_profile->times->progress = channel->caller_profile->times->progress;
- caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
- caller_profile->times->created = channel->caller_profile->times->created;
- caller_profile->times->hungup = channel->caller_profile->times->hungup;
- if (channel->caller_profile->caller_extension) {
- switch_caller_extension_clone(&caller_profile->caller_extension, channel->caller_profile->caller_extension, caller_profile->pool);
- }
- } else {
- caller_profile->times->created = switch_micro_time_now();
- }
- caller_profile->next = channel->caller_profile;
- channel->caller_profile = caller_profile;
- caller_profile->profile_index = switch_core_sprintf(caller_profile->pool, "%d", ++channel->profile_index);
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_caller_profile(switch_channel_t *channel)
- {
- switch_caller_profile_t *profile;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if ((profile = channel->caller_profile) && profile->hunt_caller_profile) {
- profile = profile->hunt_caller_profile;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return profile;
- }
- SWITCH_DECLARE(void) switch_channel_set_originator_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
- {
- switch_assert(channel != NULL);
- switch_assert(channel->caller_profile != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (!caller_profile->times) {
- caller_profile->times = (switch_channel_timetable_t *) switch_core_alloc(caller_profile->pool, sizeof(*caller_profile->times));
- }
- if (channel->caller_profile) {
- caller_profile->next = channel->caller_profile->originator_caller_profile;
- channel->caller_profile->originator_caller_profile = caller_profile;
- channel->last_profile_type = LP_ORIGINATOR;
- }
- switch_assert(channel->caller_profile->originator_caller_profile->next != channel->caller_profile->originator_caller_profile);
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
- {
- switch_assert(channel != NULL);
- switch_assert(channel->caller_profile != NULL);
- switch_mutex_lock(channel->profile_mutex);
- channel->caller_profile->hunt_caller_profile = NULL;
- if (channel->caller_profile && caller_profile) {
- caller_profile->direction = channel->direction;
- caller_profile->logical_direction = channel->logical_direction;
- channel->caller_profile->hunt_caller_profile = caller_profile;
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_set_origination_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
- {
- switch_assert(channel != NULL);
- switch_assert(channel->caller_profile != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile) {
- caller_profile->next = channel->caller_profile->origination_caller_profile;
- channel->caller_profile->origination_caller_profile = caller_profile;
- }
- switch_assert(channel->caller_profile->origination_caller_profile->next != channel->caller_profile->origination_caller_profile);
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_origination_caller_profile(switch_channel_t *channel)
- {
- switch_caller_profile_t *profile = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile) {
- profile = channel->caller_profile->origination_caller_profile;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return profile;
- }
- SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
- {
- switch_assert(channel != NULL);
- switch_assert(channel->caller_profile != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile) {
- caller_profile->next = channel->caller_profile->originatee_caller_profile;
- channel->caller_profile->originatee_caller_profile = caller_profile;
- channel->last_profile_type = LP_ORIGINATEE;
- }
- switch_assert(channel->caller_profile->originatee_caller_profile->next != channel->caller_profile->originatee_caller_profile);
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_profile(switch_channel_t *channel)
- {
- switch_caller_profile_t *profile = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile) {
- profile = channel->caller_profile->originator_caller_profile;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return profile;
- }
- SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel)
- {
- switch_caller_profile_t *profile = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile) {
- profile = channel->caller_profile->originatee_caller_profile;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return profile;
- }
- SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel)
- {
- switch_assert(channel != NULL);
- switch_assert(channel->session != NULL);
- return switch_core_session_get_uuid(channel->session);
- }
- SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
- {
- int x, index;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->state_mutex);
- for (x = 0; x < SWITCH_MAX_STATE_HANDLERS; x++) {
- if (channel->state_handlers[x] == state_handler) {
- index = x;
- goto end;
- }
- }
- index = channel->state_handler_index++;
- if (channel->state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
- index = -1;
- goto end;
- }
- channel->state_handlers[index] = state_handler;
- end:
- switch_mutex_unlock(channel->state_mutex);
- return index;
- }
- SWITCH_DECLARE(const switch_state_handler_table_t *) switch_channel_get_state_handler(switch_channel_t *channel, int index)
- {
- const switch_state_handler_table_t *h = NULL;
- switch_assert(channel != NULL);
- if (index >= SWITCH_MAX_STATE_HANDLERS || index > channel->state_handler_index) {
- return NULL;
- }
- switch_mutex_lock(channel->state_mutex);
- h = channel->state_handlers[index];
- switch_mutex_unlock(channel->state_mutex);
- return h;
- }
- SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
- {
- int index, i = channel->state_handler_index;
- const switch_state_handler_table_t *new_handlers[SWITCH_MAX_STATE_HANDLERS] = { 0 };
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->state_mutex);
- channel->state_handler_index = 0;
- if (state_handler) {
- for (index = 0; index < i; index++) {
- if (channel->state_handlers[index] != state_handler) {
- new_handlers[channel->state_handler_index++] = channel->state_handlers[index];
- }
- }
- } else {
- for (index = 0; index < i; index++) {
- if (channel->state_handlers[index] && switch_test_flag(channel->state_handlers[index], SSH_FLAG_STICKY)) {
- new_handlers[channel->state_handler_index++] = channel->state_handlers[index];
- }
- }
- }
- for (index = 0; index < SWITCH_MAX_STATE_HANDLERS; index++) {
- channel->state_handlers[index] = NULL;
- }
- if (channel->state_handler_index > 0) {
- for (index = 0; index < channel->state_handler_index; index++) {
- channel->state_handlers[index] = new_handlers[index];
- }
- }
- switch_mutex_unlock(channel->state_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_restart(switch_channel_t *channel)
- {
- switch_channel_set_state(channel, CS_RESET);
- switch_channel_wait_for_state_timeout(channel, CS_RESET, 5000);
- switch_channel_set_state(channel, CS_EXECUTE);
- }
- /* XXX This is a somewhat simple operation. Were essentially taking the extension that one channel
- was executing and generating a new extension for another channel that starts out where the
- original one left off with an optional forward offset. Since all we are really doing is
- copying a few basic pool-allocated structures from one channel to another there really is
- not much to worry about here in terms of threading since we use read-write locks.
- While the features are nice, they only really are needed in one specific crazy attended
- transfer scenario where one channel was in the middle of calling a particular extension
- when it was rudely cut off by a transfer key press. XXX */
- SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switch_channel_t *orig_channel, switch_channel_t *new_channel, uint32_t offset)
- {
- switch_caller_profile_t *caller_profile;
- switch_caller_extension_t *extension = NULL, *orig_extension = NULL;
- switch_caller_application_t *ap;
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_event_header_t *hi = NULL;
- const char *no_copy = switch_channel_get_variable(orig_channel, "attended_transfer_no_copy");
- char *dup;
- int i, argc = 0;
- char *argv[128];
- if (no_copy) {
- dup = switch_core_session_strdup(new_channel->session, no_copy);
- argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
- }
- switch_mutex_lock(orig_channel->profile_mutex);
- switch_mutex_lock(new_channel->profile_mutex);
- caller_profile = switch_caller_profile_clone(new_channel->session, new_channel->caller_profile);
- switch_assert(caller_profile);
- extension = switch_caller_extension_new(new_channel->session, caller_profile->destination_number, caller_profile->destination_number);
- orig_extension = switch_channel_get_caller_extension(orig_channel);
- if (extension && orig_extension) {
- for (ap = orig_extension->current_application; ap && offset > 0; offset--) {
- ap = ap->next;
- }
- for (; ap; ap = ap->next) {
- switch_caller_extension_add_application(new_channel->session, extension, ap->application_name, ap->application_data);
- }
- caller_profile->destination_number = switch_core_strdup(caller_profile->pool, orig_channel->caller_profile->destination_number);
- switch_channel_set_caller_profile(new_channel, caller_profile);
- switch_channel_set_caller_extension(new_channel, extension);
- for (hi = orig_channel->variables->headers; hi; hi = hi->next) {
- int ok = 1;
- for (i = 0; i < argc; i++) {
- if (!strcasecmp(argv[i], hi->name)) {
- ok = 0;
- break;
- }
- }
- if (!ok)
- continue;
- switch_channel_set_variable(new_channel, hi->name, hi->value);
- }
- status = SWITCH_STATUS_SUCCESS;
- }
- switch_mutex_unlock(new_channel->profile_mutex);
- switch_mutex_unlock(orig_channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(void) switch_channel_invert_cid(switch_channel_t *channel)
- {
- const char *tname, *tnum;
- switch_caller_profile_t *cp;
- cp = switch_channel_get_caller_profile(channel);
- tname = cp->caller_id_name;
- tnum = cp->caller_id_number;
- #ifdef DEEP_DEBUG_CID
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SWAP [%s][%s] [%s][%s]\n", cp->caller_id_name, cp->caller_id_number, cp->callee_id_name, cp->callee_id_number);
- #endif
- cp->caller_id_name = cp->callee_id_name;
- cp->caller_id_number = cp->callee_id_number;
- cp->callee_id_name = tname;
- cp->callee_id_number = tnum;
- if (zstr(cp->caller_id_name)) {
- cp->caller_id_name = "Unknown";
- }
- if (zstr(cp->caller_id_number)) {
- cp->caller_id_number = "Unknown";
- }
- }
- SWITCH_DECLARE(void) switch_channel_flip_cid(switch_channel_t *channel)
- {
- switch_event_t *event;
- const char *tmp = NULL;
- switch_mutex_lock(channel->profile_mutex);
- if (switch_channel_test_flag(channel, CF_RECOVERING) && switch_true(switch_channel_get_variable(channel, "channel_cid_flipped"))) {
- switch_mutex_unlock(channel->profile_mutex);
- return;
- }
- if (channel->caller_profile->callee_id_name) {
- tmp = channel->caller_profile->caller_id_name;
- switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name);
- channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name);
- }
- if (switch_channel_test_flag(channel, CF_BRIDGED)) {
- channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
- } else if (tmp) {
- channel->caller_profile->callee_id_name = tmp;
- }
- if (channel->caller_profile->callee_id_number) {
- tmp = channel->caller_profile->caller_id_number;
- switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number);
- channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number);
- }
- if (switch_channel_test_flag(channel, CF_BRIDGED)) {
- channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
- } else if (tmp) {
- channel->caller_profile->callee_id_number = tmp;
- }
- switch_channel_set_variable(channel, "channel_cid_flipped", "yes");
- switch_mutex_unlock(channel->profile_mutex);
- if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
- const char *uuid = switch_channel_get_partner_uuid(channel);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "RECV");
- if (uuid) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
- }
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO, "%s Flipping CID from \"%s\" <%s> to \"%s\" <%s>\n",
- switch_channel_get_name(channel),
- switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_name")),
- switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_number")),
- channel->caller_profile->caller_id_name,
- channel->caller_profile->caller_id_number
- );
- }
- SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel)
- {
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && switch_channel_test_flag(channel, CF_BLEG)) {
- switch_channel_flip_cid(channel);
- switch_channel_clear_flag(channel, CF_BLEG);
- } else if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(channel, CF_DIALPLAN)) {
- switch_channel_set_flag(channel, CF_DIALPLAN);
- switch_channel_flip_cid(channel);
- }
- }
- SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(switch_channel_t *channel)
- {
- switch_caller_extension_t *caller_extension;
- switch_mutex_lock(channel->profile_mutex);
- caller_extension = channel->queued_extension;
- channel->queued_extension = NULL;
- switch_mutex_unlock(channel->profile_mutex);
- return caller_extension;
- }
- SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
- {
- switch_mutex_lock(channel->profile_mutex);
- channel->queued_extension = caller_extension;
- switch_mutex_unlock(channel->profile_mutex);
- switch_channel_set_flag(channel, CF_TRANSFER);
- switch_channel_set_state(channel, CS_ROUTING);
- }
- SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
- {
- switch_assert(channel != NULL);
- switch_channel_sort_cid(channel);
- switch_mutex_lock(channel->profile_mutex);
- caller_extension->next = channel->caller_profile->caller_extension;
- channel->caller_profile->caller_extension = caller_extension;
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_caller_extension(switch_channel_t *channel)
- {
- switch_caller_extension_t *extension = NULL;
- switch_assert(channel != NULL);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile) {
- extension = channel->caller_profile->caller_extension;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return extension;
- }
- SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel)
- {
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile && channel->caller_profile->times) {
- channel->caller_profile->times->bridged = switch_micro_time_now();
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel)
- {
- if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->hungup) {
- switch_mutex_lock(channel->profile_mutex);
- channel->caller_profile->times->hungup = switch_micro_time_now();
- switch_mutex_unlock(channel->profile_mutex);
- }
- }
- SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_channel_t *channel,
- const char *file, const char *func, int line, switch_call_cause_t hangup_cause)
- {
- int ok = 0;
- switch_assert(channel != NULL);
- /* one per customer */
- switch_mutex_lock(channel->state_mutex);
- if (!(channel->opaque_flags & OCF_HANGUP)) {
- channel->opaque_flags |= OCF_HANGUP;
- ok = 1;
- }
- switch_mutex_unlock(channel->state_mutex);
- if (switch_channel_test_flag(channel, CF_LEG_HOLDING)) {
- switch_channel_mark_hold(channel, SWITCH_FALSE);
- switch_channel_set_flag(channel, CF_HANGUP_HELD);
- }
- if (!ok) {
- return channel->state;
- }
- switch_channel_clear_flag(channel, CF_BLOCK_STATE);
- if (channel->state < CS_HANGUP) {
- switch_channel_state_t last_state;
- switch_event_t *event;
- const char *var;
- switch_mutex_lock(channel->profile_mutex);
- if (channel->hold_record && !channel->hold_record->off) {
- channel->hold_record->off = switch_time_now();
- }
- switch_mutex_unlock(channel->profile_mutex);
- switch_mutex_lock(channel->state_mutex);
- last_state = channel->state;
- channel->state = CS_HANGUP;
- switch_mutex_unlock(channel->state_mutex);
- channel->hangup_cause = hangup_cause;
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
- channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
- switch_channel_set_variable_partner(channel, "last_bridge_hangup_cause", switch_channel_cause2str(hangup_cause));
- if ((var = switch_channel_get_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE))) {
- switch_channel_set_variable_partner(channel, "last_bridge_" SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, var);
- }
- if (switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
- switch_channel_set_variable(channel, "last_bridge_role", "originator");
- } else if (switch_channel_test_flag(channel, CF_BRIDGED)) {
- switch_channel_set_variable(channel, "last_bridge_role", "originatee");
- }
- if (!switch_core_session_running(channel->session) && !switch_core_session_started(channel->session)) {
- switch_core_session_thread_launch(channel->session);
- }
- if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
- switch_core_session_signal_state_change(channel->session);
- switch_core_session_hangup_state(channel->session, SWITCH_FALSE);
- }
- return channel->state;
- }
- static switch_status_t send_ind(switch_channel_t *channel, switch_core_session_message_types_t msg_id, const char *file, const char *func, int line)
- {
- switch_core_session_message_t msg = { 0 };
- msg.message_id = msg_id;
- msg.from = channel->name;
- return switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_perform_acknowledge_call(switch_channel_t *channel,
- const char *file, const char *func, int line)
- {
- send_ind(channel, SWITCH_MESSAGE_INDICATE_ACKNOWLEDGE_CALL, file, func, line);
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(switch_channel_t *channel,
- switch_ring_ready_t rv,
- const char *file, const char *func, int line)
- {
- switch_event_t *event;
- if (!switch_channel_test_flag(channel, CF_RING_READY) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring-Ready %s!\n", channel->name);
- switch_channel_set_flag_value(channel, CF_RING_READY, rv);
- switch_mutex_lock(channel->profile_mutex);
- if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->progress) {
- channel->caller_profile->times->progress = switch_micro_time_now();
- if (channel->caller_profile->originator_caller_profile) {
- switch_core_session_t *other_session;
- if ((other_session = switch_core_session_locate(channel->caller_profile->originator_caller_profile->uuid))) {
- switch_channel_t *other_channel;
- other_channel = switch_core_session_get_channel(other_session);
- switch_mutex_lock(other_channel->profile_mutex);
- if (other_channel->caller_profile && !other_channel->caller_profile->times->progress) {
- other_channel->caller_profile->times->progress = channel->caller_profile->times->progress;
- }
- switch_mutex_unlock(other_channel->profile_mutex);
- switch_core_session_rwunlock(other_session);
- }
- channel->caller_profile->originator_caller_profile->times->progress = channel->caller_profile->times->progress;
- }
- }
- switch_mutex_unlock(channel->profile_mutex);
- if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE);
- switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_RING_VARIABLE);
- switch_channel_set_callstate(channel, CCS_RINGING);
- send_ind(channel, SWITCH_MESSAGE_RING_EVENT, file, func, line);
- return SWITCH_STATUS_SUCCESS;
- }
- return SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_channel_t *channel, const char *file, const char *func, int line)
- {
- switch_event_t *event;
- if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
- const char *uuid;
- switch_core_session_t *other_session;
- switch_core_media_check_dtls(channel->session, SWITCH_MEDIA_TYPE_AUDIO);
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Pre-Answer %s!\n", channel->name);
- switch_channel_set_flag(channel, CF_EARLY_MEDIA);
- switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
- if (switch_true(switch_channel_get_variable(channel, "video_mirror_input"))) {
- switch_channel_set_flag(channel, CF_VIDEO_MIRROR_INPUT);
- }
- if (channel->caller_profile && channel->caller_profile->times) {
- switch_mutex_lock(channel->profile_mutex);
- channel->caller_profile->times->progress_media = switch_micro_time_now();
- if (channel->caller_profile->originator_caller_profile) {
- switch_core_session_t *osession;
- if ((osession = switch_core_session_locate(channel->caller_profile->originator_caller_profile->uuid))) {
- switch_channel_t *other_channel;
- other_channel = switch_core_session_get_channel(osession);
- if (other_channel->caller_profile) {
- other_channel->caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
- }
- switch_core_session_rwunlock(osession);
- }
- channel->caller_profile->originator_caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
- }
- switch_mutex_unlock(channel->profile_mutex);
- }
- if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE);
- switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE);
- switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_PRE_ANSWER_VARIABLE);
- switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE);
- if (switch_true(switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE))) {
- switch_channel_set_flag(channel, CF_PASSTHRU_PTIME_MISMATCH);
- }
- /* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
- a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
- */
- if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE))
- && (other_session = switch_core_session_locate(uuid))) {
- switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
- switch_core_session_rwunlock(other_session);
- }
- switch_channel_set_callstate(channel, CCS_EARLY);
- send_ind(channel, SWITCH_MESSAGE_PROGRESS_EVENT, file, func, line);
- switch_core_media_check_autoadj(channel->session);
- return SWITCH_STATUS_SUCCESS;
- }
- return SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_perform_pre_answer(switch_channel_t *channel, const char *file, const char *func, int line)
- {
- switch_core_session_message_t msg = { 0 };
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_assert(channel != NULL);
- if (channel->hangup_cause || channel->state >= CS_HANGUP) {
- return SWITCH_STATUS_FALSE;
- }
- if (switch_channel_test_flag(channel, CF_ANSWERED)) {
- return SWITCH_STATUS_SUCCESS;
- }
- if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
- return SWITCH_STATUS_SUCCESS;
- }
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
- msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
- msg.from = channel->name;
- status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
- }
- if (status == SWITCH_STATUS_SUCCESS) {
- switch_channel_perform_mark_pre_answered(channel, file, func, line);
- switch_channel_audio_sync(channel);
- } else {
- switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
- }
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_channel_t *channel, switch_ring_ready_t rv,
- const char *file, const char *func, int line)
- {
- switch_core_session_message_t msg = { 0 };
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_assert(channel != NULL);
- if (channel->hangup_cause || channel->state >= CS_HANGUP) {
- return SWITCH_STATUS_FALSE;
- }
- if (switch_channel_test_flag(channel, CF_ANSWERED)) {
- return SWITCH_STATUS_SUCCESS;
- }
- if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
- return SWITCH_STATUS_SUCCESS;
- }
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
- msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
- msg.from = channel->name;
- msg.numeric_arg = rv;
- status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
- }
- if (status == SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring Ready %s!\n", channel->name);
- switch_channel_perform_mark_ring_ready_value(channel, rv, file, func, line);
- } else {
- switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
- }
- return status;
- }
- static void do_api_on(switch_channel_t *channel, const char *variable)
- {
- char *app;
- char *arg = NULL;
- char *expanded = NULL;
- switch_stream_handle_t stream = { 0 };
- app = switch_core_session_strdup(channel->session, variable);
- if ((arg = strchr(app, ' '))) {
- *arg++ = '\0';
- }
- if (zstr(arg)) {
- expanded = arg;
- } else {
- expanded = switch_channel_expand_variables(channel, arg);
- }
-
- SWITCH_STANDARD_STREAM(stream);
- switch_api_execute(app, expanded, NULL, &stream);
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s process %s: %s(%s)\n%s\n",
- channel->name, variable, app, switch_str_nil(expanded), (char *) stream.data);
- if (expanded && expanded != arg) {
- free(expanded);
- }
- free(stream.data);
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix)
- {
- switch_event_header_t *hp;
- switch_event_t *event;
- int x = 0;
- switch_channel_get_variables(channel, &event);
- for (hp = event->headers; hp; hp = hp->next) {
- char *var = hp->name;
- char *val = hp->value;
- if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) {
- if (hp->idx) {
- int i;
- for (i = 0; i < hp->idx; i++) {
- x++;
- do_api_on(channel, hp->array[i]);
- }
- } else {
- x++;
- do_api_on(channel, val);
- }
- }
- }
- switch_event_destroy(&event);
- return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_execute_on_value(switch_channel_t *channel, const char *variable_value)
- {
- switch_status_t status;
- char *arg = NULL;
- char *p;
- int bg = 0;
- char *app;
- char *expanded = NULL;
-
- app = switch_core_session_strdup(channel->session, variable_value);
- for(p = app; p && *p; p++) {
- if (*p == ' ' || (*p == ':' && (*(p+1) != ':'))) {
- *p++ = '\0';
- arg = p;
- break;
- } else if (*p == ':' && (*(p+1) == ':')) {
- bg++;
- break;
- }
- }
- switch_assert(app != NULL);
- if (!strncasecmp(app, "perl", 4)) {
- bg++;
- }
- if (zstr(arg)) {
- expanded = arg;
- } else {
- expanded = switch_channel_expand_variables(channel, arg);
- }
-
- if (bg) {
- status = switch_core_session_execute_application_async(channel->session, app, arg);
- } else {
- status = switch_core_session_execute_application(channel->session, app, arg);
- }
- if (expanded && expanded != arg) {
- free(expanded);
- }
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
- {
- switch_event_header_t *hp;
- switch_event_t *event, *cevent;
- int x = 0;
- switch_core_get_variables(&event);
- switch_channel_get_variables(channel, &cevent);
- switch_event_merge(event, cevent);
- for (hp = event->headers; hp; hp = hp->next) {
- char *var = hp->name;
- char *val = hp->value;
- if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) {
- if (hp->idx) {
- int i;
- for (i = 0; i < hp->idx; i++) {
- x++;
- switch_channel_execute_on_value(channel, hp->array[i]);
- }
- } else {
- x++;
- switch_channel_execute_on_value(channel, val);
- }
- }
- }
- switch_event_destroy(&event);
- switch_event_destroy(&cevent);
- return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_channel_t *channel, const char *file, const char *func, int line)
- {
- switch_event_t *event;
- const char *uuid;
- switch_core_session_t *other_session;
- const char *var;
- switch_assert(channel != NULL);
- if (channel->hangup_cause || channel->state >= CS_HANGUP) {
- return SWITCH_STATUS_FALSE;
- }
- if (switch_channel_test_flag(channel, CF_ANSWERED)) {
- return SWITCH_STATUS_SUCCESS;
- }
- switch_core_media_check_dtls(channel->session, SWITCH_MEDIA_TYPE_AUDIO);
- if (channel->caller_profile && channel->caller_profile->times) {
- switch_mutex_lock(channel->profile_mutex);
- channel->caller_profile->times->answered = switch_micro_time_now();
- switch_mutex_unlock(channel->profile_mutex);
- }
- switch_channel_set_flag(channel, CF_ANSWERED);
- if (switch_true(switch_channel_get_variable(channel, "video_mirror_input"))) {
- switch_channel_set_flag(channel, CF_VIDEO_MIRROR_INPUT);
- //switch_channel_set_flag(channel, CF_VIDEO_DECODED_READ);
- }
- if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ANSWER) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(channel, event);
- switch_event_fire(&event);
- }
- /* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
- a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
- */
- if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE))
- && (other_session = switch_core_session_locate(uuid))) {
- switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
- switch_core_session_rwunlock(other_session);
- }
- if (switch_true(switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE))) {
- switch_channel_set_flag(channel, CF_PASSTHRU_PTIME_MISMATCH);
- }
- if ((var = switch_channel_get_variable(channel, SWITCH_ENABLE_HEARTBEAT_EVENTS_VARIABLE))) {
- uint32_t seconds = 60;
- int tmp;
- if (switch_is_number(var)) {
- tmp = atoi(var);
- if (tmp > 0) {
- seconds = tmp;
- }
- } else if (!switch_true(var)) {
- seconds = 0;
- }
- if (seconds) {
- switch_core_session_enable_heartbeat(channel->session, seconds);
- }
- }
- switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ANSWER");
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Channel [%s] has been answered\n",
- channel->name);
- if (switch_channel_get_variable(channel, "absolute_codec_string")) {
- /* inherit_codec == true will implicitly clear the absolute_codec_string
- variable if used since it was the reason it was set in the first place and is no longer needed */
- if (switch_true(switch_channel_get_variable(channel, "inherit_codec"))) {
- switch_channel_set_variable(channel, "absolute_codec_string", NULL);
- }
- }
- switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE);
- if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
- switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE);
- switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE);
- }
- switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE);
- switch_channel_presence(channel, "unknown", "answered", NULL);
- //switch_channel_audio_sync(channel);
-
- if (!switch_channel_test_flag(channel, CF_NO_RECOVER)) {
- switch_core_recovery_track(channel->session);
- }
-
- switch_channel_set_callstate(channel, CCS_ACTIVE);
- send_ind(channel, SWITCH_MESSAGE_ANSWER_EVENT, file, func, line);
- switch_core_media_check_autoadj(channel->session);
- if (switch_channel_test_flag(channel, CF_RTT)) {
- switch_channel_set_flag_partner(channel, CF_RTT);
- }
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *channel, const char *file, const char *func, int line)
- {
- switch_core_session_message_t msg = { 0 };
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_assert(channel != NULL);
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
- return SWITCH_STATUS_SUCCESS;
- }
- if (channel->hangup_cause || channel->state >= CS_HANGUP) {
- return SWITCH_STATUS_FALSE;
- }
- if (switch_channel_test_flag(channel, CF_ANSWERED)) {
- return SWITCH_STATUS_SUCCESS;
- }
- msg.message_id = SWITCH_MESSAGE_INDICATE_ANSWER;
- msg.from = channel->name;
- status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
- if (status == SWITCH_STATUS_SUCCESS) {
- switch_channel_perform_mark_answered(channel, file, func, line);
- if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
- switch_channel_audio_sync(channel);
- }
- } else {
- switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
- }
- if (switch_core_session_in_thread(channel->session) && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
- !switch_channel_test_flag(channel, CF_HAS_TEXT)) {
- const char *delay;
- if ((delay = switch_channel_get_variable(channel, "answer_delay"))) {
- uint32_t msec = atoi(delay);
- if (msec) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_DEBUG, "Answer delay for %u msec\n", msec);
- switch_ivr_sleep(channel->session, msec, SWITCH_TRUE, NULL);
- }
- }
- }
- return status;
- }
- #define resize(l) {\
- char *dp;\
- olen += (len + l + block);\
- cpos = c - data;\
- if ((dp = realloc(data, olen))) {\
- data = dp;\
- c = data + cpos;\
- memset(c, 0, olen - cpos);\
- }} \
- SWITCH_DECLARE(char *) switch_channel_expand_variables_check(switch_channel_t *channel, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur)
- {
- char *p, *c = NULL;
- char *data, *indup, *endof_indup;
- size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
- char *cloned_sub_val = NULL, *sub_val = NULL, *expanded_sub_val = NULL;
- char *func_val = NULL, *sb = NULL;
- int nv = 0;
- if (recur > 100) {
- return (char *) in;
- }
- if (zstr(in)) {
- return (char *) in;
- }
- nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
- if (!nv) {
- return (char *) in;
- }
- nv = 0;
- olen = strlen(in) + 1;
- indup = strdup(in);
- endof_indup = end_of_p(indup) + 1;
- if ((data = malloc(olen))) {
- memset(data, 0, olen);
- c = data;
- for (p = indup; p && p < endof_indup && *p; p++) {
- int global = 0;
- vtype = 0;
- if (*p == '\\') {
- if (*(p + 1) == '$') {
- nv = 1;
- p++;
- if (*(p + 1) == '$') {
- p++;
- }
- } else if (*(p + 1) == '\'') {
- p++;
- continue;
- } else if (*(p + 1) == '\\') {
- if (len + 1 >= olen) {
- resize(1);
- }
- *c++ = *p++;
- len++;
- continue;
- }
- }
- if (*p == '$' && !nv) {
- if (*(p + 1) == '$') {
- p++;
- global++;
- }
- if (*(p + 1)) {
- if (*(p + 1) == '{') {
- vtype = global ? 3 : 1;
- } else {
- nv = 1;
- }
- } else {
- nv = 1;
- }
- }
- if (nv) {
- if (len + 1 >= olen) {
- resize(1);
- }
- *c++ = *p;
- len++;
- nv = 0;
- continue;
- }
- if (vtype) {
- char *s = p, *e, *vname, *vval = NULL;
- size_t nlen;
- s++;
- if ((vtype == 1 || vtype == 3) && *s == '{') {
- br = 1;
- s++;
- }
- e = s;
- vname = s;
- while (*e) {
- if (br == 1 && *e == '}') {
- br = 0;
- *e++ = '\0';
- break;
- }
- if (br > 0) {
- if (e != s && *e == '{') {
- br++;
- } else if (br > 1 && *e == '}') {
- br--;
- }
- }
- e++;
- }
- p = e > endof_indup ? endof_indup : e;
- vval = NULL;
- for(sb = vname; sb && *sb; sb++) {
- if (*sb == ' ') {
- vval = sb;
- break;
- } else if (*sb == '(') {
- vval = sb;
- br = 1;
- break;
- }
- }
- if (vval) {
- e = vval - 1;
- *vval++ = '\0';
- while (*e == ' ') {
- *e-- = '\0';
- }
- e = vval;
- while (e && *e) {
- if (*e == '(') {
- br++;
- } else if (br > 1 && *e == ')') {
- br--;
- } else if (br == 1 && *e == ')') {
- *e = '\0';
- break;
- }
- e++;
- }
- vtype = 2;
- }
- if (vtype == 1 || vtype == 3) {
- char *expanded = NULL;
- int offset = 0;
- int ooffset = 0;
- char *ptr;
- int idx = -1;
- if ((expanded = switch_channel_expand_variables_check(channel, (char *) vname, var_list, api_list, recur+1)) == vname) {
- expanded = NULL;
- } else {
- vname = expanded;
- }
- if ((ptr = strchr(vname, ':'))) {
- *ptr++ = '\0';
- offset = atoi(ptr);
- if ((ptr = strchr(ptr, ':'))) {
- ptr++;
- ooffset = atoi(ptr);
- }
- }
- if ((ptr = strchr(vname, '[')) && strchr(ptr, ']')) {
- *ptr++ = '\0';
- idx = atoi(ptr);
- }
- if ((sub_val = (char *) switch_channel_get_variable_dup(channel, vname, SWITCH_TRUE, idx))) {
- if (var_list && !switch_event_check_permission_list(var_list, vname)) {
- sub_val = "<Variable Expansion Permission Denied>";
- }
- if ((expanded_sub_val = switch_channel_expand_variables_check(channel, sub_val, var_list, api_list, recur+1)) == sub_val) {
- expanded_sub_val = NULL;
- } else {
- sub_val = expanded_sub_val;
- }
- if (offset || ooffset) {
- cloned_sub_val = strdup(sub_val);
- switch_assert(cloned_sub_val);
- sub_val = cloned_sub_val;
- }
- if (offset >= 0) {
- if ((size_t) offset > strlen(sub_val)) {
- *sub_val = '\0';
- } else {
- sub_val += offset;
- }
- } else if ((size_t) abs(offset) <= strlen(sub_val)) {
- sub_val = cloned_sub_val + (strlen(cloned_sub_val) + offset);
- }
- if (ooffset > 0 && (size_t) ooffset < strlen(sub_val)) {
- if ((ptr = (char *) sub_val + ooffset)) {
- *ptr = '\0';
- }
- }
- }
- switch_safe_free(expanded);
- } else {
- switch_stream_handle_t stream = { 0 };
- char *expanded = NULL;
- SWITCH_STANDARD_STREAM(stream);
- if (stream.data) {
- char *expanded_vname = NULL;
- if ((expanded_vname = switch_channel_expand_variables_check(channel, (char *) vname, var_list, api_list, recur+1)) == vname) {
- expanded_vname = NULL;
- } else {
- vname = expanded_vname;
- }
- if ((expanded = switch_channel_expand_variables_check(channel, vval, var_list, api_list, recur+1)) == vval) {
- expanded = NULL;
- } else {
- vval = expanded;
- }
- if (!switch_core_test_flag(SCF_API_EXPANSION) || (api_list && !switch_event_check_permission_list(api_list, vname))) {
- func_val = NULL;
- sub_val = "<API Execute Permission Denied>";
- free(stream.data);
- } else {
- if (switch_api_execute(vname, vval, channel->session, &stream) == SWITCH_STATUS_SUCCESS) {
- func_val = stream.data;
- sub_val = func_val;
- } else {
- free(stream.data);
- }
- }
- switch_safe_free(expanded);
- switch_safe_free(expanded_vname);
- } else {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Memory Error!\n");
- free(data);
- free(indup);
- return (char *) in;
- }
- }
- if ((nlen = sub_val ? strlen(sub_val) : 0)) {
- if (len + nlen >= olen) {
- resize(nlen);
- }
- len += nlen;
- strcat(c, sub_val);
- c += nlen;
- }
- switch_safe_free(func_val);
- switch_safe_free(cloned_sub_val);
- switch_safe_free(expanded_sub_val);
- sub_val = NULL;
- vname = NULL;
- br = 0;
- }
- if (sp) {
- if (len + 1 >= olen) {
- resize(1);
- }
- *c++ = ' ';
- sp = 0;
- len++;
- }
- if (*p == '$') {
- p--;
- } else {
- if (len + 1 >= olen) {
- resize(1);
- }
- *c++ = *p;
- len++;
- }
- }
- }
- free(indup);
- return data;
- }
- SWITCH_DECLARE(char *) switch_channel_build_param_string(switch_channel_t *channel, switch_caller_profile_t *caller_profile, const char *prefix)
- {
- switch_stream_handle_t stream = { 0 };
- switch_size_t encode_len = 1024, new_len = 0;
- char *encode_buf = NULL;
- const char *prof[13] = { 0 }, *prof_names[13] = {
- 0};
- char *e = NULL;
- switch_event_header_t *hi;
- uint32_t x = 0;
- SWITCH_STANDARD_STREAM(stream);
- if (prefix) {
- stream.write_function(&stream, "%s&", prefix);
- }
- encode_buf = malloc(encode_len);
- switch_assert(encode_buf);
- if (!caller_profile) {
- caller_profile = switch_channel_get_caller_profile(channel);
- }
- switch_assert(caller_profile != NULL);
- prof[0] = caller_profile->context;
- prof[1] = caller_profile->destination_number;
- prof[2] = caller_profile->caller_id_name;
- prof[3] = caller_profile->caller_id_number;
- prof[4] = caller_profile->network_addr;
- prof[5] = caller_profile->ani;
- prof[6] = caller_profile->aniii;
- prof[7] = caller_profile->rdnis;
- prof[8] = caller_profile->source;
- prof[9] = caller_profile->chan_name;
- prof[10] = caller_profile->uuid;
- prof[11] = caller_profile->transfer_source;
- prof_names[0] = "context";
- prof_names[1] = "destination_number";
- prof_names[2] = "caller_id_name";
- prof_names[3] = "caller_id_number";
- prof_names[4] = "network_addr";
- prof_names[5] = "ani";
- prof_names[6] = "aniii";
- prof_names[7] = "rdnis";
- prof_names[8] = "source";
- prof_names[9] = "chan_name";
- prof_names[10] = "uuid";
- prof_names[11] = "transfer_source";
- for (x = 0; prof[x]; x++) {
- if (zstr(prof[x])) {
- continue;
- }
- new_len = (strlen(prof[x]) * 3) + 1;
- if (encode_len < new_len) {
- char *tmp;
- encode_len = new_len;
- if (!(tmp = realloc(encode_buf, encode_len))) {
- abort();
- }
- encode_buf = tmp;
- }
- switch_url_encode(prof[x], encode_buf, encode_len);
- stream.write_function(&stream, "%s=%s&", prof_names[x], encode_buf);
- }
- if (channel->caller_profile->soft) {
- profile_node_t *pn;
- for(pn = channel->caller_profile->soft; pn; pn = pn->next) {
- char *var = pn->var;
- char *val = pn->val;
- new_len = (strlen((char *) var) * 3) + 1;
- if (encode_len < new_len) {
- char *tmp;
- encode_len = new_len;
- tmp = realloc(encode_buf, encode_len);
- switch_assert(tmp);
- encode_buf = tmp;
- }
- switch_url_encode((char *) val, encode_buf, encode_len);
- stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
- }
- }
- if ((hi = switch_channel_variable_first(channel))) {
- for (; hi; hi = hi->next) {
- char *var = hi->name;
- char *val = hi->value;
- new_len = (strlen((char *) var) * 3) + 1;
- if (encode_len < new_len) {
- char *tmp;
- encode_len = new_len;
- tmp = realloc(encode_buf, encode_len);
- switch_assert(tmp);
- encode_buf = tmp;
- }
- switch_url_encode((char *) val, encode_buf, encode_len);
- stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
- }
- switch_channel_variable_last(channel);
- }
- e = (char *) stream.data + (strlen((char *) stream.data) - 1);
- if (e && *e == '&') {
- *e = '\0';
- }
- switch_safe_free(encode_buf);
- return stream.data;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel)
- {
- int x = 0;
- switch_assert(channel);
- switch_assert(other_channel);
- switch_mutex_lock(channel->profile_mutex);
- switch_mutex_lock(other_channel->profile_mutex);
- if (!zstr(channel->caller_profile->callee_id_name)) {
- other_channel->caller_profile->callee_id_name = switch_core_strdup(other_channel->caller_profile->pool, channel->caller_profile->callee_id_name);
- x++;
- }
- if (!zstr(channel->caller_profile->callee_id_number)) {
- other_channel->caller_profile->callee_id_number = switch_core_strdup(other_channel->caller_profile->pool, channel->caller_profile->callee_id_number);
- x++;
- }
- switch_mutex_unlock(other_channel->profile_mutex);
- switch_mutex_unlock(channel->profile_mutex);
- return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_get_variables(switch_channel_t *channel, switch_event_t **event)
- {
- switch_status_t status;
- switch_mutex_lock(channel->profile_mutex);
- if (channel->variables) {
- status = switch_event_dup(event, channel->variables);
- } else {
- status = switch_event_create(event, SWITCH_EVENT_CHANNEL_DATA);
- }
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_get_variables_prefix(switch_channel_t *channel, const char *prefix, switch_event_t **event)
- {
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_event_t *vars;
-
- switch_event_create(&vars, SWITCH_EVENT_CHANNEL_DATA);
-
- switch_mutex_lock(channel->profile_mutex);
- if (channel->variables) {
- switch_event_header_t *hi;
- for (hi = channel->variables->headers; hi; hi = hi->next) {
- if (!strncmp(hi->name, prefix, strlen(prefix))) {
- switch_event_add_header_string(vars, SWITCH_STACK_BOTTOM, hi->name, hi->value);
- }
- }
- }
- switch_mutex_unlock(channel->profile_mutex);
- *event = vars;
- return status;
- }
- SWITCH_DECLARE(switch_core_session_t *) switch_channel_get_session(switch_channel_t *channel)
- {
- switch_assert(channel);
- return channel->session;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *channel)
- {
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- const char *cid_buf = NULL;
- switch_caller_profile_t *caller_profile;
- switch_app_log_t *app_log, *ap;
- char *last_app = NULL, *last_arg = NULL;
- char start[80] = "", resurrect[80] = "", answer[80] = "", hold[80],
- bridge[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "",
- profile_start[80] = "";
- int32_t duration = 0, legbillsec = 0, billsec = 0, mduration = 0, billmsec = 0, legbillmsec = 0, progressmsec = 0, progress_mediamsec = 0;
- int32_t answersec = 0, answermsec = 0, waitsec = 0, waitmsec = 0;
- switch_time_t answerusec = 0;
- switch_time_t uduration = 0, legbillusec = 0, billusec = 0, progresssec = 0, progressusec = 0, progress_mediasec = 0, progress_mediausec = 0, waitusec = 0;
- time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0, tt_bridged, tt_last_hold, tt_hold_accum,
- tt_progress = 0, tt_progress_media = 0, tt_hungup = 0, mtt_created = 0, mtt_answered = 0, mtt_bridged = 0,
- mtt_hungup = 0, tt_prof_created, mtt_progress = 0, mtt_progress_media = 0;
- void *pop;
- char dtstr[SWITCH_DTMF_LOG_LEN + 1] = "";
- int x = 0;
- switch_mutex_lock(channel->profile_mutex);
- if (switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
- switch_mutex_unlock(channel->profile_mutex);
- return SWITCH_STATUS_FALSE;
- }
- if (!(caller_profile = channel->caller_profile) || !channel->variables) {
- switch_mutex_unlock(channel->profile_mutex);
- return SWITCH_STATUS_FALSE;
- }
- switch_channel_set_flag(channel, CF_TIMESTAMP_SET);
- if ((app_log = switch_core_session_get_app_log(channel->session))) {
- for (ap = app_log; ap && ap->next; ap = ap->next);
- last_app = ap->app;
- last_arg = ap->arg;
- }
- if (!zstr(caller_profile->caller_id_name)) {
- cid_buf = switch_core_session_sprintf(channel->session, "\"%s\" <%s>", caller_profile->caller_id_name,
- switch_str_nil(caller_profile->caller_id_number));
- } else {
- cid_buf = caller_profile->caller_id_number;
- }
- while (x < SWITCH_DTMF_LOG_LEN && switch_queue_trypop(channel->dtmf_log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_dtmf_t *dt = (switch_dtmf_t *) pop;
- if (dt) {
- dtstr[x++] = dt->digit;
- free(dt);
- dt = NULL;
- }
- }
- if (x) {
- const char *var = switch_channel_get_variable(channel, "digits_dialed_filter");
- char *digit_string = dtstr;
- char *X = NULL;
- switch_regex_t *re = NULL;
- char *substituted = NULL;
- if (!zstr(var)) {
- int proceed = 0;
- int ovector[30];
- if ((proceed = switch_regex_perform(dtstr, var, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
- int len = (strlen(dtstr) + strlen(var) + 10) * proceed;
- int i = 0;
- const char *replace = NULL;
- X = malloc(len);
- for (i = 0; i < proceed; i++) {
- if (pcre_get_substring(dtstr, ovector, proceed, i, &replace) >= 0) {
- if (replace) {
- switch_size_t plen = strlen(replace);
- memset(X, 'X', plen);
- *(X+plen) = '\0';
-
- switch_safe_free(substituted);
- substituted = switch_string_replace(substituted ? substituted : dtstr, replace, X);
-
- pcre_free_substring(replace);
- }
- }
- }
- if (!zstr(substituted)) {
- digit_string = substituted;
- }
- }
- }
- switch_channel_set_variable(channel, "digits_dialed", digit_string);
- switch_regex_safe_free(re);
- switch_safe_free(substituted);
- switch_safe_free(X);
- } else {
- switch_channel_set_variable(channel, "digits_dialed", "none");
- }
- if (caller_profile->times) {
- switch_time_exp_t tm;
- switch_size_t retsize;
- const char *fmt = "%Y-%m-%d %T";
- switch_time_exp_lt(&tm, caller_profile->times->created);
- switch_strftime_nocheck(start, &retsize, sizeof(start), fmt, &tm);
- switch_channel_set_variable(channel, "start_stamp", start);
- switch_time_exp_lt(&tm, caller_profile->times->profile_created);
- switch_strftime_nocheck(profile_start, &retsize, sizeof(profile_start), fmt, &tm);
- switch_channel_set_variable(channel, "profile_start_stamp", profile_start);
- if (caller_profile->times->answered) {
- switch_time_exp_lt(&tm, caller_profile->times->answered);
- switch_strftime_nocheck(answer, &retsize, sizeof(answer), fmt, &tm);
- switch_channel_set_variable(channel, "answer_stamp", answer);
- }
- if (caller_profile->times->bridged) {
- switch_time_exp_lt(&tm, caller_profile->times->bridged);
- switch_strftime_nocheck(bridge, &retsize, sizeof(bridge), fmt, &tm);
- switch_channel_set_variable(channel, "bridge_stamp", bridge);
- }
- if (caller_profile->times->last_hold) {
- switch_time_exp_lt(&tm, caller_profile->times->last_hold);
- switch_strftime_nocheck(hold, &retsize, sizeof(hold), fmt, &tm);
- switch_channel_set_variable(channel, "hold_stamp", hold);
- }
- if (caller_profile->times->resurrected) {
- switch_time_exp_lt(&tm, caller_profile->times->resurrected);
- switch_strftime_nocheck(resurrect, &retsize, sizeof(resurrect), fmt, &tm);
- switch_channel_set_variable(channel, "resurrect_stamp", resurrect);
- }
- if (caller_profile->times->progress) {
- switch_time_exp_lt(&tm, caller_profile->times->progress);
- switch_strftime_nocheck(progress, &retsize, sizeof(progress), fmt, &tm);
- switch_channel_set_variable(channel, "progress_stamp", progress);
- }
- if (caller_profile->times->progress_media) {
- switch_time_exp_lt(&tm, caller_profile->times->progress_media);
- switch_strftime_nocheck(progress_media, &retsize, sizeof(progress_media), fmt, &tm);
- switch_channel_set_variable(channel, "progress_media_stamp", progress_media);
- }
- if (channel->hold_record) {
- switch_hold_record_t *hr;
- switch_stream_handle_t stream = { 0 };
- SWITCH_STANDARD_STREAM(stream);
- stream.write_function(&stream, "{", SWITCH_VA_NONE);
- for (hr = channel->hold_record; hr; hr = hr->next) {
- stream.write_function(&stream, "{%"SWITCH_TIME_T_FMT",%"SWITCH_TIME_T_FMT"},", hr->on, hr->off);
- }
- end_of((char *)stream.data) = '}';
- switch_channel_set_variable(channel, "hold_events", (char *)stream.data);
- free(stream.data);
- }
- switch_time_exp_lt(&tm, caller_profile->times->hungup);
- switch_strftime_nocheck(end, &retsize, sizeof(end), fmt, &tm);
- switch_channel_set_variable(channel, "end_stamp", end);
- tt_created = (time_t) (caller_profile->times->created / 1000000);
- mtt_created = (time_t) (caller_profile->times->created / 1000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_created);
- switch_channel_set_variable(channel, "start_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
- switch_channel_set_variable(channel, "start_uepoch", tmp);
- tt_prof_created = (time_t) (caller_profile->times->profile_created / 1000000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_prof_created);
- switch_channel_set_variable(channel, "profile_start_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
- switch_channel_set_variable(channel, "profile_start_uepoch", tmp);
- tt_answered = (time_t) (caller_profile->times->answered / 1000000);
- mtt_answered = (time_t) (caller_profile->times->answered / 1000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_answered);
- switch_channel_set_variable(channel, "answer_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
- switch_channel_set_variable(channel, "answer_uepoch", tmp);
- tt_bridged = (time_t) (caller_profile->times->bridged / 1000000);
- mtt_bridged = (time_t) (caller_profile->times->bridged / 1000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_bridged);
- switch_channel_set_variable(channel, "bridge_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
- switch_channel_set_variable(channel, "bridge_uepoch", tmp);
- tt_last_hold = (time_t) (caller_profile->times->last_hold / 1000000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_last_hold);
- switch_channel_set_variable(channel, "last_hold_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold);
- switch_channel_set_variable(channel, "last_hold_uepoch", tmp);
- tt_hold_accum = (time_t) (caller_profile->times->hold_accum / 1000000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_hold_accum);
- switch_channel_set_variable(channel, "hold_accum_seconds", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum);
- switch_channel_set_variable(channel, "hold_accum_usec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum / 1000);
- switch_channel_set_variable(channel, "hold_accum_ms", tmp);
- tt_resurrected = (time_t) (caller_profile->times->resurrected / 1000000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_resurrected);
- switch_channel_set_variable(channel, "resurrect_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
- switch_channel_set_variable(channel, "resurrect_uepoch", tmp);
- tt_progress = (time_t) (caller_profile->times->progress / 1000000);
- mtt_progress = (time_t) (caller_profile->times->progress / 1000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_progress);
- switch_channel_set_variable(channel, "progress_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
- switch_channel_set_variable(channel, "progress_uepoch", tmp);
- tt_progress_media = (time_t) (caller_profile->times->progress_media / 1000000);
- mtt_progress_media = (time_t) (caller_profile->times->progress_media / 1000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_progress_media);
- switch_channel_set_variable(channel, "progress_media_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
- switch_channel_set_variable(channel, "progress_media_uepoch", tmp);
- tt_hungup = (time_t) (caller_profile->times->hungup / 1000000);
- mtt_hungup = (time_t) (caller_profile->times->hungup / 1000);
- switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_hungup);
- switch_channel_set_variable(channel, "end_epoch", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
- switch_channel_set_variable(channel, "end_uepoch", tmp);
- duration = (int32_t) (tt_hungup - tt_created);
- mduration = (int32_t) (mtt_hungup - mtt_created);
- uduration = caller_profile->times->hungup - caller_profile->times->created;
- if (caller_profile->times->bridged > caller_profile->times->created) {
- waitsec = (int32_t) (tt_bridged - tt_created);
- waitmsec = (int32_t) (mtt_bridged - mtt_created);
- waitusec = caller_profile->times->bridged - caller_profile->times->created;
- } else {
- waitsec = 0;
- waitmsec = 0;
- waitusec = 0;
- }
- if (caller_profile->times->answered) {
- billsec = (int32_t) (tt_hungup - tt_answered);
- billmsec = (int32_t) (mtt_hungup - mtt_answered);
- billusec = caller_profile->times->hungup - caller_profile->times->answered;
- legbillsec = (int32_t) (tt_hungup - tt_created);
- legbillmsec = (int32_t) (mtt_hungup - mtt_created);
- legbillusec = caller_profile->times->hungup - caller_profile->times->created;
- answersec = (int32_t) (tt_answered - tt_created);
- answermsec = (int32_t) (mtt_answered - mtt_created);
- answerusec = caller_profile->times->answered - caller_profile->times->created;
- }
- if (caller_profile->times->progress) {
- progresssec = (int32_t) (tt_progress - tt_created);
- progressmsec = (int32_t) (mtt_progress - mtt_created);
- progressusec = caller_profile->times->progress - caller_profile->times->created;
- }
- if (caller_profile->times->progress_media) {
- progress_mediasec = (int32_t) (tt_progress_media - tt_created);
- progress_mediamsec = (int32_t) (mtt_progress_media - mtt_created);
- progress_mediausec = caller_profile->times->progress_media - caller_profile->times->created;
- }
- }
- switch_channel_set_variable(channel, "last_app", last_app);
- switch_channel_set_variable(channel, "last_arg", last_arg);
- switch_channel_set_variable(channel, "caller_id", cid_buf);
- switch_snprintf(tmp, sizeof(tmp), "%d", duration);
- switch_channel_set_variable(channel, "duration", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", billsec);
- switch_channel_set_variable(channel, "billsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%"SWITCH_TIME_T_FMT, progresssec);
- switch_channel_set_variable(channel, "progresssec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", answersec);
- switch_channel_set_variable(channel, "answersec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", waitsec);
- switch_channel_set_variable(channel, "waitsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%"SWITCH_TIME_T_FMT, progress_mediasec);
- switch_channel_set_variable(channel, "progress_mediasec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", legbillsec);
- switch_channel_set_variable(channel, "flow_billsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", mduration);
- switch_channel_set_variable(channel, "mduration", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", billmsec);
- switch_channel_set_variable(channel, "billmsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", progressmsec);
- switch_channel_set_variable(channel, "progressmsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", answermsec);
- switch_channel_set_variable(channel, "answermsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", waitmsec);
- switch_channel_set_variable(channel, "waitmsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediamsec);
- switch_channel_set_variable(channel, "progress_mediamsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%d", legbillmsec);
- switch_channel_set_variable(channel, "flow_billmsec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, uduration);
- switch_channel_set_variable(channel, "uduration", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, billusec);
- switch_channel_set_variable(channel, "billusec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, progressusec);
- switch_channel_set_variable(channel, "progressusec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, answerusec);
- switch_channel_set_variable(channel, "answerusec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, waitusec);
- switch_channel_set_variable(channel, "waitusec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, progress_mediausec);
- switch_channel_set_variable(channel, "progress_mediausec", tmp);
- switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, legbillusec);
- switch_channel_set_variable(channel, "flow_billusec", tmp);
- switch_mutex_unlock(channel->profile_mutex);
- return status;
- }
- SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid_copy(switch_channel_t *channel, char *buf, switch_size_t blen)
- {
- const char *uuid = NULL;
- switch_mutex_lock(channel->profile_mutex);
- if (!(uuid = switch_channel_get_variable_dup(channel, SWITCH_SIGNAL_BOND_VARIABLE, SWITCH_TRUE, -1))) {
- uuid = switch_channel_get_variable_dup(channel, SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE, SWITCH_TRUE, -1);
- }
- if (uuid) {
- strncpy(buf, uuid, blen);
- uuid = (const char *) buf;
- }
- switch_mutex_unlock(channel->profile_mutex);
- return uuid;
- }
- SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *channel)
- {
- const char *uuid = NULL;
- if (!(uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
- uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE);
- }
- return uuid;
- }
- SWITCH_DECLARE(void) switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause)
- {
- switch_core_session_t *session = channel->session;
- const char *transfer_on_fail = NULL;
- char *tof_data = NULL;
- char *tof_array[4] = { 0 };
- //int tof_arrayc = 0;
- if (!switch_channel_up_nosig(channel)) {
- return;
- }
- transfer_on_fail = switch_channel_get_variable(channel, "transfer_on_fail");
- tof_data = switch_core_session_strdup(session, transfer_on_fail);
- switch_split(tof_data, ' ', tof_array);
- transfer_on_fail = tof_array[0];
- /*
- if the variable continue_on_fail is set it can be:
- 'true' to continue on all failures.
- 'false' to not continue.
- A list of codes either names or numbers eg "user_busy,normal_temporary_failure,603"
- failure_causes acts as the opposite version
- EXCEPTION... ATTENDED_TRANSFER never is a reason to continue.......
- */
- if (cause != SWITCH_CAUSE_ATTENDED_TRANSFER) {
- const char *continue_on_fail = NULL, *failure_causes = NULL;
- continue_on_fail = switch_channel_get_variable(channel, "continue_on_fail");
- failure_causes = switch_channel_get_variable(channel, "failure_causes");
- if (continue_on_fail || failure_causes) {
- const char *cause_str;
- char cause_num[35] = "";
- cause_str = switch_channel_cause2str(cause);
- switch_snprintf(cause_num, sizeof(cause_num), "%u", cause);
- if (failure_causes) {
- char *lbuf = switch_core_session_strdup(session, failure_causes);
- char *argv[256] = { 0 };
- int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
- int i, x = 0;
- for (i = 0; i < argc; i++) {
- if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
- x++;
- break;
- }
- }
- if (!x) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
- "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str);
- return;
- }
- }
- if (continue_on_fail) {
- if (switch_true(continue_on_fail)) {
- return;
- } else {
- char *lbuf = switch_core_session_strdup(session, continue_on_fail);
- char *argv[256] = { 0 };
- int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
- int i;
- for (i = 0; i < argc; i++) {
- if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
- "Continue on fail [%s]: Cause: %s\n", continue_on_fail, cause_str);
- return;
- }
- }
- }
- }
- } else {
- /* no answer is *always* a reason to continue */
- if (cause == SWITCH_CAUSE_NO_ANSWER || cause == SWITCH_CAUSE_NO_USER_RESPONSE || cause == SWITCH_CAUSE_ORIGINATOR_CANCEL) {
- return;
- }
- }
- if (transfer_on_fail || failure_causes) {
- const char *cause_str;
- char cause_num[35] = "";
- cause_str = switch_channel_cause2str(cause);
- switch_snprintf(cause_num, sizeof(cause_num), "%u", cause);
- if ((tof_array[1] == NULL ) || (!strcasecmp(tof_array[1], "auto_cause"))){
- tof_array[1] = (char *) cause_str;
- }
- if (failure_causes) {
- char *lbuf = switch_core_session_strdup(session, failure_causes);
- char *argv[256] = { 0 };
- int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
- int i, x = 0;
- for (i = 0; i < argc; i++) {
- if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
- x++;
- break;
- }
- }
- if (!x) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
- "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str);
- switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
- }
- }
- if (transfer_on_fail) {
- if (switch_true(transfer_on_fail)) {
- return;
- } else {
- char *lbuf = switch_core_session_strdup(session, transfer_on_fail);
- char *argv[256] = { 0 };
- int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
- int i;
- for (i = 0; i < argc; i++) {
- if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
- "Transfer on fail [%s]: Cause: %s\n", transfer_on_fail, cause_str);
- switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
- }
- }
- }
- }
- }
- }
- if (!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_CONFIRM_BLIND_TRANSFER) &&
- switch_channel_get_state(channel) != CS_ROUTING) {
- switch_channel_hangup(channel, cause);
- }
- }
- SWITCH_DECLARE(void) switch_channel_global_init(switch_memory_pool_t *pool)
- {
- memset(&globals, 0, sizeof(globals));
- globals.pool = pool;
- switch_mutex_init(&globals.device_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_core_hash_init(&globals.device_hash);
- }
- SWITCH_DECLARE(void) switch_channel_global_uninit(void)
- {
- switch_core_hash_destroy(&globals.device_hash);
- }
- static void fetch_device_stats(switch_device_record_t *drec)
- {
- switch_device_node_t *np;
- memset(&drec->stats, 0, sizeof(switch_device_stats_t));
- switch_mutex_lock(drec->mutex);
- for(np = drec->uuid_list; np; np = np->next) {
- drec->stats.total++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.total_in++;
- } else {
- drec->stats.total_out++;
- }
- if (!np->hup_profile) {
- drec->stats.offhook++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.offhook_in++;
- } else {
- drec->stats.offhook_out++;
- }
- if (np->callstate == CCS_HELD) {
- drec->stats.held++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.held_in++;
- } else {
- drec->stats.held_out++;
- }
- } else if (np->callstate == CCS_UNHELD) {
- drec->stats.unheld++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.unheld_in++;
- } else {
- drec->stats.unheld_out++;
- }
- } else {
- if (np->callstate == CCS_EARLY) {
- drec->stats.early++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.early_in++;
- } else {
- drec->stats.early_out++;
- }
- } else if (np->callstate == CCS_RINGING) {
- drec->stats.ringing++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.ringing_in++;
- } else {
- drec->stats.ringing_out++;
- }
- } else if (np->callstate == CCS_RING_WAIT) {
- drec->stats.ring_wait++;
- } else if (np->callstate == CCS_HANGUP) {
- drec->stats.hup++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.hup_in++;
- } else {
- drec->stats.hup_out++;
- }
- } else if (np->callstate != CCS_DOWN) {
- drec->stats.active++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.active_in++;
- } else {
- drec->stats.active_out++;
- }
- }
- }
- } else {
- drec->stats.hup++;
- if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
- drec->stats.hup_in++;
- } else {
- drec->stats.hup_out++;
- }
- }
- }
- switch_mutex_unlock(drec->mutex);
- }
- SWITCH_DECLARE(void) switch_channel_clear_device_record(switch_channel_t *channel)
- {
- switch_memory_pool_t *pool;
- int sanity = 100;
- switch_device_node_t *np;
- switch_event_t *event;
- if (!channel->device_node || !switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG)) {
- return;
- }
- while(--sanity && channel->device_node->parent->refs) {
- switch_yield(100000);
- }
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Destroying device cdr %s on device [%s]\n",
- channel->device_node->parent->uuid,
- channel->device_node->parent->device_id);
- if (switch_event_create(&event, SWITCH_EVENT_CALL_DETAIL) == SWITCH_STATUS_SUCCESS) {
- int x = 0;
- char prefix[80] = "";
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Type", "device");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-ID", channel->device_node->parent->device_id);
- switch_mutex_lock(channel->device_node->parent->mutex);
- for(np = channel->device_node->parent->uuid_list; np; np = np->next) {
- switch_snprintf(prefix, sizeof(prefix), "Call-%d", ++x);
- switch_caller_profile_event_set_data(np->hup_profile, prefix, event);
- }
- switch_mutex_unlock(channel->device_node->parent->mutex);
- switch_event_fire(&event);
- }
- switch_mutex_lock(channel->device_node->parent->mutex);
- for(np = channel->device_node->parent->uuid_list; np; np = np->next) {
- if (np->xml_cdr) {
- switch_xml_free(np->xml_cdr);
- }
- if (np->event) {
- switch_event_destroy(&np->event);
- }
- }
- switch_mutex_unlock(channel->device_node->parent->mutex);
- pool = channel->device_node->parent->pool;
- switch_mutex_lock(globals.device_mutex);
- switch_core_destroy_memory_pool(&pool);
- switch_mutex_unlock(globals.device_mutex);
- }
- SWITCH_DECLARE(void) switch_channel_process_device_hangup(switch_channel_t *channel)
- {
- switch_channel_check_device_state(channel, channel->callstate);
- process_device_hup(channel);
- }
- static void process_device_hup(switch_channel_t *channel)
- {
- switch_hold_record_t *hr, *newhr, *last = NULL;
- switch_device_record_t *drec = NULL;
- switch_device_node_t *node;
- if (!channel->device_node) {
- return;
- }
- switch_mutex_lock(globals.device_mutex);
- node = channel->device_node;
- drec = channel->device_node->parent;
- node->hup_profile = switch_caller_profile_dup(drec->pool, channel->caller_profile);
- fetch_device_stats(drec);
- switch_ivr_generate_xml_cdr(channel->session, &node->xml_cdr);
- if (switch_event_create(&node->event, SWITCH_EVENT_CALL_DETAIL) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_extended_data(channel, node->event);
- }
- for (hr = channel->hold_record; hr; hr = hr->next) {
- newhr = switch_core_alloc(drec->pool, sizeof(*newhr));
- newhr->on = hr->on;
- newhr->off = hr->off;
- if (hr->uuid) {
- newhr->uuid = switch_core_strdup(drec->pool, hr->uuid);
- }
- if (!node->hold_record) {
- node->hold_record = newhr;
- } else if (last) {
- last->next = newhr;
- }
- last = newhr;
- }
- if (!drec->stats.offhook) { /* this is final call */
- switch_core_hash_delete(globals.device_hash, drec->device_id);
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Processing last call from device [%s]\n",
- drec->device_id);
- switch_channel_set_flag(channel, CF_FINAL_DEVICE_LEG);
- } else {
- channel->device_node = NULL;
- }
- drec->refs--;
- switch_mutex_unlock(globals.device_mutex);
- }
- static void switch_channel_check_device_state(switch_channel_t *channel, switch_channel_callstate_t callstate)
- {
- switch_device_record_t *drec = NULL;
- switch_device_state_binding_t *ptr = NULL;
- switch_event_t *event = NULL;
- if (!channel->device_node) {
- return;
- }
- drec = channel->device_node->parent;
- switch_mutex_lock(globals.device_mutex);
- switch_mutex_lock(drec->mutex);
- fetch_device_stats(drec);
- if (drec->state != SDS_HANGUP) {
- if (drec->stats.offhook == 0 || drec->stats.hup == drec->stats.total) {
- drec->state = SDS_HANGUP;
- } else {
- if (drec->stats.active == 0) {
- if ((drec->stats.ringing_out + drec->stats.early_out) > 0 || drec->stats.ring_wait > 0) {
- drec->state = SDS_RINGING;
- } else {
- if (drec->stats.held > 0) {
- drec->state = SDS_HELD;
- } else if (drec->stats.unheld > 0) {
- drec->state = SDS_UNHELD;
- } else {
- drec->state = SDS_DOWN;
- }
- }
- } else if (drec->stats.active == 1) {
- drec->state = SDS_ACTIVE;
- } else {
- drec->state = SDS_ACTIVE_MULTI;
- }
- }
- }
- if ((drec->state == SDS_DOWN && drec->last_state == SDS_DOWN) || (drec->state == SDS_HANGUP && drec->last_state == SDS_HANGUP)) {
- switch_mutex_unlock(drec->mutex);
- switch_mutex_unlock(globals.device_mutex);
- return;
- }
- if (!drec->call_start) {
- drec->call_start = switch_micro_time_now();
- }
- switch(drec->state) {
- case SDS_RINGING:
- if (!drec->ring_start) {
- drec->ring_start = switch_micro_time_now();
- drec->ring_stop = 0;
- }
- break;
- case SDS_ACTIVE:
- case SDS_ACTIVE_MULTI:
- if (!drec->active_start) {
- drec->active_start = switch_micro_time_now();
- drec->active_stop = 0;
- }
- break;
- case SDS_HELD:
- if (!drec->hold_start) {
- drec->hold_start = switch_micro_time_now();
- drec->hold_stop = 0;
- }
- break;
- default:
- break;
- }
- if (callstate != CCS_UNHELD && drec->active_start && drec->state != SDS_ACTIVE && drec->state != SDS_ACTIVE_MULTI) {
- drec->active_stop = switch_micro_time_now();
- }
- if (drec->ring_start && !drec->ring_stop && drec->state != SDS_RINGING) {
- drec->ring_stop = switch_micro_time_now();
- }
- if (drec->hold_start && !drec->hold_stop && drec->state != SDS_HELD) {
- drec->hold_stop = switch_micro_time_now();
- }
- if (switch_event_create(&event, SWITCH_EVENT_DEVICE_STATE) == SWITCH_STATUS_SUCCESS) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-ID", drec->device_id);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-Device-State", switch_channel_device_state2str(drec->last_state));
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-State", switch_channel_device_state2str(drec->state));
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-Call-State", switch_channel_callstate2str(callstate));
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Total-Legs", "%u", drec->stats.total);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Offhook", "%u", drec->stats.offhook);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Ringing", "%u", drec->stats.ringing);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Early", "%u", drec->stats.early);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Active", "%u", drec->stats.active);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Held", "%u", drec->stats.held);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-UnHeld", "%u", drec->stats.unheld);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Hup", "%u", drec->stats.hup);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Talk-Time-Start-Uepoch", "%"SWITCH_TIME_T_FMT, drec->active_start);
- if (drec->active_stop) {
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Talk-Time-Stop-Uepoch", "%"SWITCH_TIME_T_FMT, drec->active_stop);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Talk-Time-Milliseconds", "%u", (uint32_t)(drec->active_stop - drec->active_start) / 1000);
- }
- }
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1,
- "%s device: %s\nState: %s Dev State: %s/%s Total:%u Offhook:%u "
- "Ringing:%u Early:%u Active:%u Held:%u Unheld:%u Hungup:%u Dur: %u Ringtime: %u Holdtime: %u %s\n",
- switch_channel_get_name(channel),
- drec->device_id,
- switch_channel_callstate2str(callstate),
- switch_channel_device_state2str(drec->last_state),
- switch_channel_device_state2str(drec->state),
- drec->stats.total,
- drec->stats.offhook,
- drec->stats.ringing,
- drec->stats.early,
- drec->stats.active,
- drec->stats.held,
- drec->stats.unheld,
- drec->stats.hup,
- drec->active_stop ? (uint32_t)(drec->active_stop - drec->active_start) / 1000 : 0,
- drec->ring_stop ? (uint32_t)(drec->ring_stop - drec->ring_start) / 1000 : 0,
- drec->hold_stop ? (uint32_t)(drec->hold_stop - drec->hold_start) / 1000 : 0,
- switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG) ? "FINAL LEG" : "");
- for (ptr = globals.device_bindings; ptr; ptr = ptr->next) {
- ptr->function(channel->session, callstate, drec);
- }
- drec->last_stats = drec->stats;
- if (drec->active_stop) {
- drec->active_start = drec->active_stop = 0;
- if (drec->state == SDS_ACTIVE || drec->state == SDS_ACTIVE_MULTI) {
- drec->active_start = switch_micro_time_now();
- }
- }
- if (drec->hold_stop) {
- drec->hold_start = drec->hold_stop = 0;
- if (drec->state == SDS_HELD) {
- drec->hold_start = switch_micro_time_now();
- }
- }
- if (drec->ring_stop) {
- drec->ring_start = drec->ring_stop = 0;
- if (drec->state == SDS_RINGING) {
- drec->ring_start = switch_micro_time_now();
- }
- }
- drec->last_call_time = switch_micro_time_now();
- drec->last_state = drec->state;
- switch_mutex_unlock(drec->mutex);
- switch_mutex_unlock(globals.device_mutex);
- if (event) {
- switch_event_fire(&event);
- }
- }
- /* assumed to be called under a lock */
- static void add_uuid(switch_device_record_t *drec, switch_channel_t *channel)
- {
- switch_device_node_t *node;
- switch_assert(drec);
- switch_channel_set_flag(channel, CF_DEVICE_LEG);
- node = switch_core_alloc(drec->pool, sizeof(*node));
- node->uuid = switch_core_strdup(drec->pool, switch_core_session_get_uuid(channel->session));
- node->parent = drec;
- node->callstate = channel->callstate;
- node->direction = channel->logical_direction == SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND;
- channel->device_node = node;
- if (!drec->uuid_list) {
- drec->uuid_list = node;
- drec->uuid = node->uuid;
- } else {
- drec->uuid_tail->next = node;
- }
- drec->uuid_tail = node;
- drec->refs++;
- }
- static switch_status_t create_device_record(switch_device_record_t **drecp, const char *device_id)
- {
- switch_device_record_t *drec;
- switch_memory_pool_t *pool;
- switch_assert(drecp);
- switch_core_new_memory_pool(&pool);
- drec = switch_core_alloc(pool, sizeof(*drec));
- drec->pool = pool;
- drec->device_id = switch_core_strdup(drec->pool, device_id);
- switch_mutex_init(&drec->mutex, SWITCH_MUTEX_NESTED, drec->pool);
- *drecp = drec;
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(const char *) switch_channel_set_device_id(switch_channel_t *channel, const char *device_id)
- {
- switch_device_record_t *drec;
- if (channel->device_node) {
- return NULL;
- }
- channel->device_id = switch_core_session_strdup(channel->session, device_id);
- switch_mutex_lock(globals.device_mutex);
- if (!(drec = switch_core_hash_find(globals.device_hash, channel->device_id))) {
- create_device_record(&drec, channel->device_id);
- switch_core_hash_insert(globals.device_hash, drec->device_id, drec);
- }
- add_uuid(drec, channel);
- switch_mutex_unlock(globals.device_mutex);
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Setting DEVICE ID to [%s]\n", device_id);
- switch_channel_check_device_state(channel, channel->callstate);
- return device_id;
- }
- SWITCH_DECLARE(switch_device_record_t *) switch_channel_get_device_record(switch_channel_t *channel)
- {
- if (channel->device_node) {
- switch_mutex_lock(channel->device_node->parent->mutex);
- return channel->device_node->parent;
- }
- return NULL;
- }
- SWITCH_DECLARE(void) switch_channel_release_device_record(switch_device_record_t **drecp)
- {
- if (drecp && *drecp) {
- switch_mutex_unlock((*drecp)->mutex);
- *drecp = NULL;
- }
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_bind_device_state_handler(switch_device_state_function_t function, void *user_data)
- {
- switch_device_state_binding_t *binding = NULL, *ptr = NULL;
- assert(function != NULL);
- if (!(binding = (switch_device_state_binding_t *) switch_core_alloc(globals.pool, sizeof(*binding)))) {
- return SWITCH_STATUS_MEMERR;
- }
- binding->function = function;
- binding->user_data = user_data;
- switch_mutex_lock(globals.device_mutex);
- for (ptr = globals.device_bindings; ptr && ptr->next; ptr = ptr->next);
- if (ptr) {
- ptr->next = binding;
- } else {
- globals.device_bindings = binding;
- }
- switch_mutex_unlock(globals.device_mutex);
- return SWITCH_STATUS_SUCCESS;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_unbind_device_state_handler(switch_device_state_function_t function)
- {
- switch_device_state_binding_t *ptr, *last = NULL;
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_mutex_lock(globals.device_mutex);
- for (ptr = globals.device_bindings; ptr; ptr = ptr->next) {
- if (ptr->function == function) {
- status = SWITCH_STATUS_SUCCESS;
- if (last) {
- last->next = ptr->next;
- } else {
- globals.device_bindings = ptr->next;
- last = NULL;
- continue;
- }
- }
- last = ptr;
- }
- switch_mutex_unlock(globals.device_mutex);
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_channel, switch_channel_t *to_channel, const char *sdp)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- char *use_sdp = (char *) sdp;
- char *patched_sdp = NULL;
- if (!switch_channel_get_variable(to_channel, SWITCH_B_SDP_VARIABLE)) {
- const char *var;
- if ((var = switch_channel_get_variable(from_channel, "bypass_media_sdp_filter"))) {
- if ((patched_sdp = switch_core_media_process_sdp_filter(use_sdp, var, from_channel->session))) {
- use_sdp = patched_sdp;
- }
- }
- switch_channel_set_variable(to_channel, SWITCH_B_SDP_VARIABLE, use_sdp);
- }
- switch_safe_free(patched_sdp);
- return status;
- }
- /* For Emacs:
- * Local Variables:
- * mode:c
- * indent-tabs-mode:t
- * tab-width:4
- * c-basic-offset:4
- * End:
- * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
- */
|