| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550 |
- /*
- * JsSIP v3.0.13
- * the Javascript SIP library
- * Copyright: 2012-2017 José Luis Millán <jmillan@aliax.net> (https://github.com/jmillan)
- * Homepage: http://jssip.net
- * License: MIT
- */
- (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JsSIP = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
- var pkg = require('../package.json');
- var C = {
- USER_AGENT: pkg.title + ' ' + pkg.version,
- // SIP scheme
- SIP: 'sip',
- SIPS: 'sips',
- // End and Failure causes
- causes: {
- // Generic error causes
- CONNECTION_ERROR: 'Connection Error',
- REQUEST_TIMEOUT: 'Request Timeout',
- SIP_FAILURE_CODE: 'SIP Failure Code',
- INTERNAL_ERROR: 'Internal Error',
- // SIP error causes
- BUSY: 'Busy',
- REJECTED: 'Rejected',
- REDIRECTED: 'Redirected',
- UNAVAILABLE: 'Unavailable',
- NOT_FOUND: 'Not Found',
- ADDRESS_INCOMPLETE: 'Address Incomplete',
- INCOMPATIBLE_SDP: 'Incompatible SDP',
- MISSING_SDP: 'Missing SDP',
- AUTHENTICATION_ERROR: 'Authentication Error',
- // Session error causes
- BYE: 'Terminated',
- WEBRTC_ERROR: 'WebRTC Error',
- CANCELED: 'Canceled',
- NO_ANSWER: 'No Answer',
- EXPIRES: 'Expires',
- NO_ACK: 'No ACK',
- DIALOG_ERROR: 'Dialog Error',
- USER_DENIED_MEDIA_ACCESS: 'User Denied Media Access',
- BAD_MEDIA_DESCRIPTION: 'Bad Media Description',
- RTP_TIMEOUT: 'RTP Timeout'
- },
- SIP_ERROR_CAUSES: {
- REDIRECTED: [300,301,302,305,380],
- BUSY: [486,600],
- REJECTED: [403,603],
- NOT_FOUND: [404,604],
- UNAVAILABLE: [480,410,408,430],
- ADDRESS_INCOMPLETE: [484, 424],
- INCOMPATIBLE_SDP: [488,606],
- AUTHENTICATION_ERROR:[401,407]
- },
- // SIP Methods
- ACK: 'ACK',
- BYE: 'BYE',
- CANCEL: 'CANCEL',
- INFO: 'INFO',
- INVITE: 'INVITE',
- MESSAGE: 'MESSAGE',
- NOTIFY: 'NOTIFY',
- OPTIONS: 'OPTIONS',
- REGISTER: 'REGISTER',
- REFER: 'REFER',
- UPDATE: 'UPDATE',
- SUBSCRIBE: 'SUBSCRIBE',
- /* SIP Response Reasons
- * DOC: http://www.iana.org/assignments/sip-parameters
- * Copied from https://github.com/versatica/OverSIP/blob/master/lib/oversip/sip/constants.rb#L7
- */
- REASON_PHRASE: {
- 100: 'Trying',
- 180: 'Ringing',
- 181: 'Call Is Being Forwarded',
- 182: 'Queued',
- 183: 'Session Progress',
- 199: 'Early Dialog Terminated', // draft-ietf-sipcore-199
- 200: 'OK',
- 202: 'Accepted', // RFC 3265
- 204: 'No Notification', //RFC 5839
- 300: 'Multiple Choices',
- 301: 'Moved Permanently',
- 302: 'Moved Temporarily',
- 305: 'Use Proxy',
- 380: 'Alternative Service',
- 400: 'Bad Request',
- 401: 'Unauthorized',
- 402: 'Payment Required',
- 403: 'Forbidden',
- 404: 'Not Found',
- 405: 'Method Not Allowed',
- 406: 'Not Acceptable',
- 407: 'Proxy Authentication Required',
- 408: 'Request Timeout',
- 410: 'Gone',
- 412: 'Conditional Request Failed', // RFC 3903
- 413: 'Request Entity Too Large',
- 414: 'Request-URI Too Long',
- 415: 'Unsupported Media Type',
- 416: 'Unsupported URI Scheme',
- 417: 'Unknown Resource-Priority', // RFC 4412
- 420: 'Bad Extension',
- 421: 'Extension Required',
- 422: 'Session Interval Too Small', // RFC 4028
- 423: 'Interval Too Brief',
- 424: 'Bad Location Information', // RFC 6442
- 428: 'Use Identity Header', // RFC 4474
- 429: 'Provide Referrer Identity', // RFC 3892
- 430: 'Flow Failed', // RFC 5626
- 433: 'Anonymity Disallowed', // RFC 5079
- 436: 'Bad Identity-Info', // RFC 4474
- 437: 'Unsupported Certificate', // RFC 4744
- 438: 'Invalid Identity Header', // RFC 4744
- 439: 'First Hop Lacks Outbound Support', // RFC 5626
- 440: 'Max-Breadth Exceeded', // RFC 5393
- 469: 'Bad Info Package', // draft-ietf-sipcore-info-events
- 470: 'Consent Needed', // RFC 5360
- 478: 'Unresolvable Destination', // Custom code copied from Kamailio.
- 480: 'Temporarily Unavailable',
- 481: 'Call/Transaction Does Not Exist',
- 482: 'Loop Detected',
- 483: 'Too Many Hops',
- 484: 'Address Incomplete',
- 485: 'Ambiguous',
- 486: 'Busy Here',
- 487: 'Request Terminated',
- 488: 'Not Acceptable Here',
- 489: 'Bad Event', // RFC 3265
- 491: 'Request Pending',
- 493: 'Undecipherable',
- 494: 'Security Agreement Required', // RFC 3329
- 500: 'JsSIP Internal Error',
- 501: 'Not Implemented',
- 502: 'Bad Gateway',
- 503: 'Service Unavailable',
- 504: 'Server Time-out',
- 505: 'Version Not Supported',
- 513: 'Message Too Large',
- 580: 'Precondition Failure', // RFC 3312
- 600: 'Busy Everywhere',
- 603: 'Decline',
- 604: 'Does Not Exist Anywhere',
- 606: 'Not Acceptable'
- },
- ALLOWED_METHODS: 'INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO',
- ACCEPTED_BODY_TYPES: 'application/sdp, application/dtmf-relay',
- MAX_FORWARDS: 69,
- SESSION_EXPIRES: 90,
- MIN_SESSION_EXPIRES: 60
- };
- module.exports = C;
- },{"../package.json":51}],2:[function(require,module,exports){
- module.exports = Dialog;
- var C = {
- // Dialog states
- STATUS_EARLY: 1,
- STATUS_CONFIRMED: 2
- };
- /**
- * Expose C object.
- */
- Dialog.C = C;
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP:Dialog');
- var SIPMessage = require('./SIPMessage');
- var JsSIP_C = require('./Constants');
- var Transactions = require('./Transactions');
- var Dialog_RequestSender = require('./Dialog/RequestSender');
- // RFC 3261 12.1
- function Dialog(owner, message, type, state) {
- var contact;
- this.uac_pending_reply = false;
- this.uas_pending_reply = false;
- if(!message.hasHeader('contact')) {
- return {
- error: 'unable to create a Dialog without Contact header field'
- };
- }
- if(message instanceof SIPMessage.IncomingResponse) {
- state = (message.status_code < 200) ? C.STATUS_EARLY : C.STATUS_CONFIRMED;
- } else {
- // Create confirmed dialog if state is not defined
- state = state || C.STATUS_CONFIRMED;
- }
- contact = message.parseHeader('contact');
- // RFC 3261 12.1.1
- if(type === 'UAS') {
- this.id = {
- call_id: message.call_id,
- local_tag: message.to_tag,
- remote_tag: message.from_tag,
- toString: function() {
- return this.call_id + this.local_tag + this.remote_tag;
- }
- };
- this.state = state;
- this.remote_seqnum = message.cseq;
- this.local_uri = message.parseHeader('to').uri;
- this.remote_uri = message.parseHeader('from').uri;
- this.remote_target = contact.uri;
- this.route_set = message.getHeaders('record-route');
- }
- // RFC 3261 12.1.2
- else if(type === 'UAC') {
- this.id = {
- call_id: message.call_id,
- local_tag: message.from_tag,
- remote_tag: message.to_tag,
- toString: function() {
- return this.call_id + this.local_tag + this.remote_tag;
- }
- };
- this.state = state;
- this.local_seqnum = message.cseq;
- this.local_uri = message.parseHeader('from').uri;
- this.remote_uri = message.parseHeader('to').uri;
- this.remote_target = contact.uri;
- this.route_set = message.getHeaders('record-route').reverse();
- }
- this.owner = owner;
- owner.ua.dialogs[this.id.toString()] = this;
- debug('new ' + type + ' dialog created with status ' + (this.state === C.STATUS_EARLY ? 'EARLY': 'CONFIRMED'));
- }
- Dialog.prototype = {
- update: function(message, type) {
- this.state = C.STATUS_CONFIRMED;
- debug('dialog '+ this.id.toString() +' changed to CONFIRMED state');
- if(type === 'UAC') {
- // RFC 3261 13.2.2.4
- this.route_set = message.getHeaders('record-route').reverse();
- }
- },
- terminate: function() {
- debug('dialog ' + this.id.toString() + ' deleted');
- delete this.owner.ua.dialogs[this.id.toString()];
- },
- // RFC 3261 12.2.1.1
- createRequest: function(method, extraHeaders, body) {
- var cseq, request;
- extraHeaders = extraHeaders && extraHeaders.slice() || [];
- if(!this.local_seqnum) { this.local_seqnum = Math.floor(Math.random() * 10000); }
- cseq = (method === JsSIP_C.CANCEL || method === JsSIP_C.ACK) ? this.local_seqnum : this.local_seqnum += 1;
- request = new SIPMessage.OutgoingRequest(
- method,
- this.remote_target,
- this.owner.ua, {
- 'cseq': cseq,
- 'call_id': this.id.call_id,
- 'from_uri': this.local_uri,
- 'from_tag': this.id.local_tag,
- 'to_uri': this.remote_uri,
- 'to_tag': this.id.remote_tag,
- 'route_set': this.route_set
- }, extraHeaders, body);
- request.dialog = this;
- return request;
- },
- // RFC 3261 12.2.2
- checkInDialogRequest: function(request) {
- var self = this;
- if(!this.remote_seqnum) {
- this.remote_seqnum = request.cseq;
- } else if(request.cseq < this.remote_seqnum) {
- //Do not try to reply to an ACK request.
- if (request.method !== JsSIP_C.ACK) {
- request.reply(500);
- }
- return false;
- } else if(request.cseq > this.remote_seqnum) {
- this.remote_seqnum = request.cseq;
- }
- // RFC3261 14.2 Modifying an Existing Session -UAS BEHAVIOR-
- if (request.method === JsSIP_C.INVITE || (request.method === JsSIP_C.UPDATE && request.body)) {
- if (this.uac_pending_reply === true) {
- request.reply(491);
- } else if (this.uas_pending_reply === true) {
- var retryAfter = (Math.random() * 10 | 0) + 1;
- request.reply(500, null, ['Retry-After:'+ retryAfter]);
- return false;
- } else {
- this.uas_pending_reply = true;
- request.server_transaction.on('stateChanged', function stateChanged(){
- if (this.state === Transactions.C.STATUS_ACCEPTED ||
- this.state === Transactions.C.STATUS_COMPLETED ||
- this.state === Transactions.C.STATUS_TERMINATED) {
- request.server_transaction.removeListener('stateChanged', stateChanged);
- self.uas_pending_reply = false;
- }
- });
- }
- // RFC3261 12.2.2 Replace the dialog`s remote target URI if the request is accepted
- if(request.hasHeader('contact')) {
- request.server_transaction.on('stateChanged', function(){
- if (this.state === Transactions.C.STATUS_ACCEPTED) {
- self.remote_target = request.parseHeader('contact').uri;
- }
- });
- }
- }
- else if (request.method === JsSIP_C.NOTIFY) {
- // RFC6665 3.2 Replace the dialog`s remote target URI if the request is accepted
- if(request.hasHeader('contact')) {
- request.server_transaction.on('stateChanged', function(){
- if (this.state === Transactions.C.STATUS_COMPLETED) {
- self.remote_target = request.parseHeader('contact').uri;
- }
- });
- }
- }
- return true;
- },
- sendRequest: function(applicant, method, options) {
- options = options || {};
- var
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body || null,
- request = this.createRequest(method, extraHeaders, body),
- request_sender = new Dialog_RequestSender(this, applicant, request);
- request_sender.send();
- // Return the instance of OutgoingRequest
- return request;
- },
- receiveRequest: function(request) {
- //Check in-dialog request
- if(!this.checkInDialogRequest(request)) {
- return;
- }
- this.owner.receiveRequest(request);
- }
- };
- },{"./Constants":1,"./Dialog/RequestSender":3,"./SIPMessage":19,"./Transactions":22,"debug":35}],3:[function(require,module,exports){
- module.exports = DialogRequestSender;
- /**
- * Dependencies.
- */
- var JsSIP_C = require('../Constants');
- var Transactions = require('../Transactions');
- var RTCSession = require('../RTCSession');
- var RequestSender = require('../RequestSender');
- function DialogRequestSender(dialog, applicant, request) {
- this.dialog = dialog;
- this.applicant = applicant;
- this.request = request;
- // RFC3261 14.1 Modifying an Existing Session. UAC Behavior.
- this.reattempt = false;
- this.reattemptTimer = null;
- }
- DialogRequestSender.prototype = {
- send: function() {
- var
- self = this,
- request_sender = new RequestSender(this, this.dialog.owner.ua);
- request_sender.send();
- // RFC3261 14.2 Modifying an Existing Session -UAC BEHAVIOR-
- if ((this.request.method === JsSIP_C.INVITE || (this.request.method === JsSIP_C.UPDATE && this.request.body)) &&
- request_sender.clientTransaction.state !== Transactions.C.STATUS_TERMINATED) {
- this.dialog.uac_pending_reply = true;
- request_sender.clientTransaction.on('stateChanged', function stateChanged(){
- if (this.state === Transactions.C.STATUS_ACCEPTED ||
- this.state === Transactions.C.STATUS_COMPLETED ||
- this.state === Transactions.C.STATUS_TERMINATED) {
- request_sender.clientTransaction.removeListener('stateChanged', stateChanged);
- self.dialog.uac_pending_reply = false;
- }
- });
- }
- },
- onRequestTimeout: function() {
- this.applicant.onRequestTimeout();
- },
- onTransportError: function() {
- this.applicant.onTransportError();
- },
- receiveResponse: function(response) {
- var self = this;
- // RFC3261 12.2.1.2 408 or 481 is received for a request within a dialog.
- if (response.status_code === 408 || response.status_code === 481) {
- this.applicant.onDialogError(response);
- } else if (response.method === JsSIP_C.INVITE && response.status_code === 491) {
- if (this.reattempt) {
- this.applicant.receiveResponse(response);
- } else {
- this.request.cseq.value = this.dialog.local_seqnum += 1;
- this.reattemptTimer = setTimeout(function() {
- if (self.applicant.owner.status !== RTCSession.C.STATUS_TERMINATED) {
- self.reattempt = true;
- self.request_sender.send();
- }
- }, 1000);
- }
- } else {
- this.applicant.receiveResponse(response);
- }
- }
- };
- },{"../Constants":1,"../RTCSession":11,"../RequestSender":18,"../Transactions":22}],4:[function(require,module,exports){
- module.exports = DigestAuthentication;
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP:DigestAuthentication');
- var debugerror = require('debug')('JsSIP:ERROR:DigestAuthentication');
- debugerror.log = console.warn.bind(console);
- var Utils = require('./Utils');
- function DigestAuthentication(credentials) {
- this.credentials = credentials;
- this.cnonce = null;
- this.nc = 0;
- this.ncHex = '00000000';
- this.algorithm = null;
- this.realm = null;
- this.nonce = null;
- this.opaque = null;
- this.stale = null;
- this.qop = null;
- this.method = null;
- this.uri = null;
- this.ha1 = null;
- this.response = null;
- }
- DigestAuthentication.prototype.get = function(parameter) {
- switch (parameter) {
- case 'realm':
- return this.realm;
- case 'ha1':
- return this.ha1;
- default:
- debugerror('get() | cannot get "%s" parameter', parameter);
- return undefined;
- }
- };
- /**
- * Performs Digest authentication given a SIP request and the challenge
- * received in a response to that request.
- * Returns true if auth was successfully generated, false otherwise.
- */
- DigestAuthentication.prototype.authenticate = function(request, challenge) {
- var ha2, hex;
- this.algorithm = challenge.algorithm;
- this.realm = challenge.realm;
- this.nonce = challenge.nonce;
- this.opaque = challenge.opaque;
- this.stale = challenge.stale;
- if (this.algorithm) {
- if (this.algorithm !== 'MD5') {
- debugerror('authenticate() | challenge with Digest algorithm different than "MD5", authentication aborted');
- return false;
- }
- } else {
- this.algorithm = 'MD5';
- }
- if (!this.nonce) {
- debugerror('authenticate() | challenge without Digest nonce, authentication aborted');
- return false;
- }
- if (!this.realm) {
- debugerror('authenticate() | challenge without Digest realm, authentication aborted');
- return false;
- }
- // If no plain SIP password is provided.
- if (!this.credentials.password) {
- // If ha1 is not provided we cannot authenticate.
- if (!this.credentials.ha1) {
- debugerror('authenticate() | no plain SIP password nor ha1 provided, authentication aborted');
- return false;
- }
- // If the realm does not match the stored realm we cannot authenticate.
- if (this.credentials.realm !== this.realm) {
- debugerror('authenticate() | no plain SIP password, and stored `realm` does not match the given `realm`, cannot authenticate [stored:"%s", given:"%s"]', this.credentials.realm, this.realm);
- return false;
- }
- }
- // 'qop' can contain a list of values (Array). Let's choose just one.
- if (challenge.qop) {
- if (challenge.qop.indexOf('auth') > -1) {
- this.qop = 'auth';
- } else if (challenge.qop.indexOf('auth-int') > -1) {
- this.qop = 'auth-int';
- } else {
- // Otherwise 'qop' is present but does not contain 'auth' or 'auth-int', so abort here.
- debugerror('authenticate() | challenge without Digest qop different than "auth" or "auth-int", authentication aborted');
- return false;
- }
- } else {
- this.qop = null;
- }
- // Fill other attributes.
- this.method = request.method;
- this.uri = request.ruri;
- this.cnonce = Utils.createRandomToken(12);
- this.nc += 1;
- hex = Number(this.nc).toString(16);
- this.ncHex = '00000000'.substr(0, 8-hex.length) + hex;
- // nc-value = 8LHEX. Max value = 'FFFFFFFF'.
- if (this.nc === 4294967296) {
- this.nc = 1;
- this.ncHex = '00000001';
- }
- // Calculate the Digest "response" value.
- // If we have plain SIP password then regenerate ha1.
- if (this.credentials.password) {
- // HA1 = MD5(A1) = MD5(username:realm:password)
- this.ha1 = Utils.calculateMD5(this.credentials.username + ':' + this.realm + ':' + this.credentials.password);
- //
- // Otherwise reuse the stored ha1.
- } else {
- this.ha1 = this.credentials.ha1;
- }
- if (this.qop === 'auth') {
- // HA2 = MD5(A2) = MD5(method:digestURI)
- ha2 = Utils.calculateMD5(this.method + ':' + this.uri);
- // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
- this.response = Utils.calculateMD5(this.ha1 + ':' + this.nonce + ':' + this.ncHex + ':' + this.cnonce + ':auth:' + ha2);
- } else if (this.qop === 'auth-int') {
- // HA2 = MD5(A2) = MD5(method:digestURI:MD5(entityBody))
- ha2 = Utils.calculateMD5(this.method + ':' + this.uri + ':' + Utils.calculateMD5(this.body ? this.body : ''));
- // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
- this.response = Utils.calculateMD5(this.ha1 + ':' + this.nonce + ':' + this.ncHex + ':' + this.cnonce + ':auth-int:' + ha2);
- } else if (this.qop === null) {
- // HA2 = MD5(A2) = MD5(method:digestURI)
- ha2 = Utils.calculateMD5(this.method + ':' + this.uri);
- // response = MD5(HA1:nonce:HA2)
- this.response = Utils.calculateMD5(this.ha1 + ':' + this.nonce + ':' + ha2);
- }
- debug('authenticate() | response generated');
- return true;
- };
- /**
- * Return the Proxy-Authorization or WWW-Authorization header value.
- */
- DigestAuthentication.prototype.toString = function() {
- var auth_params = [];
- if (!this.response) {
- throw new Error('response field does not exist, cannot generate Authorization header');
- }
- auth_params.push('algorithm=' + this.algorithm);
- auth_params.push('username="' + this.credentials.username + '"');
- auth_params.push('realm="' + this.realm + '"');
- auth_params.push('nonce="' + this.nonce + '"');
- auth_params.push('uri="' + this.uri + '"');
- auth_params.push('response="' + this.response + '"');
- if (this.opaque) {
- auth_params.push('opaque="' + this.opaque + '"');
- }
- if (this.qop) {
- auth_params.push('qop=' + this.qop);
- auth_params.push('cnonce="' + this.cnonce + '"');
- auth_params.push('nc=' + this.ncHex);
- }
- return 'Digest ' + auth_params.join(', ');
- };
- },{"./Utils":26,"debug":35}],5:[function(require,module,exports){
- /**
- * @namespace Exceptions
- * @memberOf JsSIP
- */
- var Exceptions = {
- /**
- * Exception thrown when a valid parameter is given to the JsSIP.UA constructor.
- * @class ConfigurationError
- * @memberOf JsSIP.Exceptions
- */
- ConfigurationError: (function(){
- var exception = function(parameter, value) {
- this.code = 1;
- this.name = 'CONFIGURATION_ERROR';
- this.parameter = parameter;
- this.value = value;
- this.message = (!this.value)? 'Missing parameter: '+ this.parameter : 'Invalid value '+ JSON.stringify(this.value) +' for parameter "'+ this.parameter +'"';
- };
- exception.prototype = new Error();
- return exception;
- }()),
- InvalidStateError: (function(){
- var exception = function(status) {
- this.code = 2;
- this.name = 'INVALID_STATE_ERROR';
- this.status = status;
- this.message = 'Invalid status: '+ status;
- };
- exception.prototype = new Error();
- return exception;
- }()),
- NotSupportedError: (function(){
- var exception = function(message) {
- this.code = 3;
- this.name = 'NOT_SUPPORTED_ERROR';
- this.message = message;
- };
- exception.prototype = new Error();
- return exception;
- }()),
- NotReadyError: (function(){
- var exception = function(message) {
- this.code = 4;
- this.name = 'NOT_READY_ERROR';
- this.message = message;
- };
- exception.prototype = new Error();
- return exception;
- }())
- };
- module.exports = Exceptions;
- },{}],6:[function(require,module,exports){
- module.exports = (function(){
- /*
- * Generated by PEG.js 0.7.0.
- *
- * http://pegjs.majda.cz/
- */
- function quote(s) {
- /*
- * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
- * string literal except for the closing quote character, backslash,
- * carriage return, line separator, paragraph separator, and line feed.
- * Any character may appear in the form of an escape sequence.
- *
- * For portability, we also escape escape all control and non-ASCII
- * characters. Note that "\0" and "\v" escape sequences are not used
- * because JSHint does not like the first and IE the second.
- */
- return '"' + s
- .replace(/\\/g, '\\\\') // backslash
- .replace(/"/g, '\\"') // closing quote character
- .replace(/\x08/g, '\\b') // backspace
- .replace(/\t/g, '\\t') // horizontal tab
- .replace(/\n/g, '\\n') // line feed
- .replace(/\f/g, '\\f') // form feed
- .replace(/\r/g, '\\r') // carriage return
- .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
- + '"';
- }
- var result = {
- /*
- * Parses the input with a generated parser. If the parsing is successfull,
- * returns a value explicitly or implicitly specified by the grammar from
- * which the parser was generated (see |PEG.buildParser|). If the parsing is
- * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
- */
- parse: function(input, startRule) {
- var parseFunctions = {
- "CRLF": parse_CRLF,
- "DIGIT": parse_DIGIT,
- "ALPHA": parse_ALPHA,
- "HEXDIG": parse_HEXDIG,
- "WSP": parse_WSP,
- "OCTET": parse_OCTET,
- "DQUOTE": parse_DQUOTE,
- "SP": parse_SP,
- "HTAB": parse_HTAB,
- "alphanum": parse_alphanum,
- "reserved": parse_reserved,
- "unreserved": parse_unreserved,
- "mark": parse_mark,
- "escaped": parse_escaped,
- "LWS": parse_LWS,
- "SWS": parse_SWS,
- "HCOLON": parse_HCOLON,
- "TEXT_UTF8_TRIM": parse_TEXT_UTF8_TRIM,
- "TEXT_UTF8char": parse_TEXT_UTF8char,
- "UTF8_NONASCII": parse_UTF8_NONASCII,
- "UTF8_CONT": parse_UTF8_CONT,
- "LHEX": parse_LHEX,
- "token": parse_token,
- "token_nodot": parse_token_nodot,
- "separators": parse_separators,
- "word": parse_word,
- "STAR": parse_STAR,
- "SLASH": parse_SLASH,
- "EQUAL": parse_EQUAL,
- "LPAREN": parse_LPAREN,
- "RPAREN": parse_RPAREN,
- "RAQUOT": parse_RAQUOT,
- "LAQUOT": parse_LAQUOT,
- "COMMA": parse_COMMA,
- "SEMI": parse_SEMI,
- "COLON": parse_COLON,
- "LDQUOT": parse_LDQUOT,
- "RDQUOT": parse_RDQUOT,
- "comment": parse_comment,
- "ctext": parse_ctext,
- "quoted_string": parse_quoted_string,
- "quoted_string_clean": parse_quoted_string_clean,
- "qdtext": parse_qdtext,
- "quoted_pair": parse_quoted_pair,
- "SIP_URI_noparams": parse_SIP_URI_noparams,
- "SIP_URI": parse_SIP_URI,
- "uri_scheme": parse_uri_scheme,
- "uri_scheme_sips": parse_uri_scheme_sips,
- "uri_scheme_sip": parse_uri_scheme_sip,
- "userinfo": parse_userinfo,
- "user": parse_user,
- "user_unreserved": parse_user_unreserved,
- "password": parse_password,
- "hostport": parse_hostport,
- "host": parse_host,
- "hostname": parse_hostname,
- "domainlabel": parse_domainlabel,
- "toplabel": parse_toplabel,
- "IPv6reference": parse_IPv6reference,
- "IPv6address": parse_IPv6address,
- "h16": parse_h16,
- "ls32": parse_ls32,
- "IPv4address": parse_IPv4address,
- "dec_octet": parse_dec_octet,
- "port": parse_port,
- "uri_parameters": parse_uri_parameters,
- "uri_parameter": parse_uri_parameter,
- "transport_param": parse_transport_param,
- "user_param": parse_user_param,
- "method_param": parse_method_param,
- "ttl_param": parse_ttl_param,
- "maddr_param": parse_maddr_param,
- "lr_param": parse_lr_param,
- "other_param": parse_other_param,
- "pname": parse_pname,
- "pvalue": parse_pvalue,
- "paramchar": parse_paramchar,
- "param_unreserved": parse_param_unreserved,
- "headers": parse_headers,
- "header": parse_header,
- "hname": parse_hname,
- "hvalue": parse_hvalue,
- "hnv_unreserved": parse_hnv_unreserved,
- "Request_Response": parse_Request_Response,
- "Request_Line": parse_Request_Line,
- "Request_URI": parse_Request_URI,
- "absoluteURI": parse_absoluteURI,
- "hier_part": parse_hier_part,
- "net_path": parse_net_path,
- "abs_path": parse_abs_path,
- "opaque_part": parse_opaque_part,
- "uric": parse_uric,
- "uric_no_slash": parse_uric_no_slash,
- "path_segments": parse_path_segments,
- "segment": parse_segment,
- "param": parse_param,
- "pchar": parse_pchar,
- "scheme": parse_scheme,
- "authority": parse_authority,
- "srvr": parse_srvr,
- "reg_name": parse_reg_name,
- "query": parse_query,
- "SIP_Version": parse_SIP_Version,
- "INVITEm": parse_INVITEm,
- "ACKm": parse_ACKm,
- "OPTIONSm": parse_OPTIONSm,
- "BYEm": parse_BYEm,
- "CANCELm": parse_CANCELm,
- "REGISTERm": parse_REGISTERm,
- "SUBSCRIBEm": parse_SUBSCRIBEm,
- "NOTIFYm": parse_NOTIFYm,
- "REFERm": parse_REFERm,
- "Method": parse_Method,
- "Status_Line": parse_Status_Line,
- "Status_Code": parse_Status_Code,
- "extension_code": parse_extension_code,
- "Reason_Phrase": parse_Reason_Phrase,
- "Allow_Events": parse_Allow_Events,
- "Call_ID": parse_Call_ID,
- "Contact": parse_Contact,
- "contact_param": parse_contact_param,
- "name_addr": parse_name_addr,
- "display_name": parse_display_name,
- "contact_params": parse_contact_params,
- "c_p_q": parse_c_p_q,
- "c_p_expires": parse_c_p_expires,
- "delta_seconds": parse_delta_seconds,
- "qvalue": parse_qvalue,
- "generic_param": parse_generic_param,
- "gen_value": parse_gen_value,
- "Content_Disposition": parse_Content_Disposition,
- "disp_type": parse_disp_type,
- "disp_param": parse_disp_param,
- "handling_param": parse_handling_param,
- "Content_Encoding": parse_Content_Encoding,
- "Content_Length": parse_Content_Length,
- "Content_Type": parse_Content_Type,
- "media_type": parse_media_type,
- "m_type": parse_m_type,
- "discrete_type": parse_discrete_type,
- "composite_type": parse_composite_type,
- "extension_token": parse_extension_token,
- "x_token": parse_x_token,
- "m_subtype": parse_m_subtype,
- "m_parameter": parse_m_parameter,
- "m_value": parse_m_value,
- "CSeq": parse_CSeq,
- "CSeq_value": parse_CSeq_value,
- "Expires": parse_Expires,
- "Event": parse_Event,
- "event_type": parse_event_type,
- "From": parse_From,
- "from_param": parse_from_param,
- "tag_param": parse_tag_param,
- "Max_Forwards": parse_Max_Forwards,
- "Min_Expires": parse_Min_Expires,
- "Name_Addr_Header": parse_Name_Addr_Header,
- "Proxy_Authenticate": parse_Proxy_Authenticate,
- "challenge": parse_challenge,
- "other_challenge": parse_other_challenge,
- "auth_param": parse_auth_param,
- "digest_cln": parse_digest_cln,
- "realm": parse_realm,
- "realm_value": parse_realm_value,
- "domain": parse_domain,
- "URI": parse_URI,
- "nonce": parse_nonce,
- "nonce_value": parse_nonce_value,
- "opaque": parse_opaque,
- "stale": parse_stale,
- "algorithm": parse_algorithm,
- "qop_options": parse_qop_options,
- "qop_value": parse_qop_value,
- "Proxy_Require": parse_Proxy_Require,
- "Record_Route": parse_Record_Route,
- "rec_route": parse_rec_route,
- "Reason": parse_Reason,
- "reason_param": parse_reason_param,
- "reason_cause": parse_reason_cause,
- "Require": parse_Require,
- "Route": parse_Route,
- "route_param": parse_route_param,
- "Subscription_State": parse_Subscription_State,
- "substate_value": parse_substate_value,
- "subexp_params": parse_subexp_params,
- "event_reason_value": parse_event_reason_value,
- "Subject": parse_Subject,
- "Supported": parse_Supported,
- "To": parse_To,
- "to_param": parse_to_param,
- "Via": parse_Via,
- "via_param": parse_via_param,
- "via_params": parse_via_params,
- "via_ttl": parse_via_ttl,
- "via_maddr": parse_via_maddr,
- "via_received": parse_via_received,
- "via_branch": parse_via_branch,
- "response_port": parse_response_port,
- "sent_protocol": parse_sent_protocol,
- "protocol_name": parse_protocol_name,
- "transport": parse_transport,
- "sent_by": parse_sent_by,
- "via_host": parse_via_host,
- "via_port": parse_via_port,
- "ttl": parse_ttl,
- "WWW_Authenticate": parse_WWW_Authenticate,
- "Session_Expires": parse_Session_Expires,
- "s_e_expires": parse_s_e_expires,
- "s_e_params": parse_s_e_params,
- "s_e_refresher": parse_s_e_refresher,
- "extension_header": parse_extension_header,
- "header_value": parse_header_value,
- "message_body": parse_message_body,
- "uuid_URI": parse_uuid_URI,
- "uuid": parse_uuid,
- "hex4": parse_hex4,
- "hex8": parse_hex8,
- "hex12": parse_hex12,
- "Refer_To": parse_Refer_To,
- "Replaces": parse_Replaces,
- "call_id": parse_call_id,
- "replaces_param": parse_replaces_param,
- "to_tag": parse_to_tag,
- "from_tag": parse_from_tag,
- "early_flag": parse_early_flag
- };
- if (startRule !== undefined) {
- if (parseFunctions[startRule] === undefined) {
- throw new Error("Invalid rule name: " + quote(startRule) + ".");
- }
- } else {
- startRule = "CRLF";
- }
- var pos = 0;
- var reportFailures = 0;
- var rightmostFailuresPos = 0;
- var rightmostFailuresExpected = [];
- function padLeft(input, padding, length) {
- var result = input;
- var padLength = length - input.length;
- for (var i = 0; i < padLength; i++) {
- result = padding + result;
- }
- return result;
- }
- function escape(ch) {
- var charCode = ch.charCodeAt(0);
- var escapeChar;
- var length;
- if (charCode <= 0xFF) {
- escapeChar = 'x';
- length = 2;
- } else {
- escapeChar = 'u';
- length = 4;
- }
- return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
- }
- function matchFailed(failure) {
- if (pos < rightmostFailuresPos) {
- return;
- }
- if (pos > rightmostFailuresPos) {
- rightmostFailuresPos = pos;
- rightmostFailuresExpected = [];
- }
- rightmostFailuresExpected.push(failure);
- }
- function parse_CRLF() {
- var result0;
- if (input.substr(pos, 2) === "\r\n") {
- result0 = "\r\n";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\r\\n\"");
- }
- }
- return result0;
- }
- function parse_DIGIT() {
- var result0;
- if (/^[0-9]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[0-9]");
- }
- }
- return result0;
- }
- function parse_ALPHA() {
- var result0;
- if (/^[a-zA-Z]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z]");
- }
- }
- return result0;
- }
- function parse_HEXDIG() {
- var result0;
- if (/^[0-9a-fA-F]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[0-9a-fA-F]");
- }
- }
- return result0;
- }
- function parse_WSP() {
- var result0;
- result0 = parse_SP();
- if (result0 === null) {
- result0 = parse_HTAB();
- }
- return result0;
- }
- function parse_OCTET() {
- var result0;
- if (/^[\0-\xFF]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\0-\\xFF]");
- }
- }
- return result0;
- }
- function parse_DQUOTE() {
- var result0;
- if (/^["]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\"]");
- }
- }
- return result0;
- }
- function parse_SP() {
- var result0;
- if (input.charCodeAt(pos) === 32) {
- result0 = " ";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\" \"");
- }
- }
- return result0;
- }
- function parse_HTAB() {
- var result0;
- if (input.charCodeAt(pos) === 9) {
- result0 = "\t";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\t\"");
- }
- }
- return result0;
- }
- function parse_alphanum() {
- var result0;
- if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z0-9]");
- }
- }
- return result0;
- }
- function parse_reserved() {
- var result0;
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_unreserved() {
- var result0;
- result0 = parse_alphanum();
- if (result0 === null) {
- result0 = parse_mark();
- }
- return result0;
- }
- function parse_mark() {
- var result0;
- if (input.charCodeAt(pos) === 45) {
- result0 = "-";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 95) {
- result0 = "_";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 46) {
- result0 = ".";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 33) {
- result0 = "!";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 126) {
- result0 = "~";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 42) {
- result0 = "*";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 39) {
- result0 = "'";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 40) {
- result0 = "(";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 41) {
- result0 = ")";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_escaped() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 37) {
- result0 = "%";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_HEXDIG();
- if (result1 !== null) {
- result2 = parse_HEXDIG();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, escaped) {return escaped.join(''); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_LWS() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- pos2 = pos;
- result0 = [];
- result1 = parse_WSP();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_WSP();
- }
- if (result0 !== null) {
- result1 = parse_CRLF();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos2;
- }
- } else {
- result0 = null;
- pos = pos2;
- }
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result2 = parse_WSP();
- if (result2 !== null) {
- result1 = [];
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_WSP();
- }
- } else {
- result1 = null;
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return " "; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_SWS() {
- var result0;
- result0 = parse_LWS();
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
- function parse_HCOLON() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = [];
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- }
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ':'; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_TEXT_UTF8_TRIM() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result1 = parse_TEXT_UTF8char();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_TEXT_UTF8char();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = [];
- result3 = parse_LWS();
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_LWS();
- }
- if (result2 !== null) {
- result3 = parse_TEXT_UTF8char();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = [];
- result3 = parse_LWS();
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_LWS();
- }
- if (result2 !== null) {
- result3 = parse_TEXT_UTF8char();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_TEXT_UTF8char() {
- var result0;
- if (/^[!-~]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[!-~]");
- }
- }
- if (result0 === null) {
- result0 = parse_UTF8_NONASCII();
- }
- return result0;
- }
- function parse_UTF8_NONASCII() {
- var result0;
- if (/^[\x80-\uFFFF]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x80-\\uFFFF]");
- }
- }
- return result0;
- }
- function parse_UTF8_CONT() {
- var result0;
- if (/^[\x80-\xBF]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x80-\\xBF]");
- }
- }
- return result0;
- }
- function parse_LHEX() {
- var result0;
- result0 = parse_DIGIT();
- if (result0 === null) {
- if (/^[a-f]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[a-f]");
- }
- }
- }
- return result0;
- }
- function parse_token() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_token_nodot() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_separators() {
- var result0;
- if (input.charCodeAt(pos) === 40) {
- result0 = "(";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 41) {
- result0 = ")";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 60) {
- result0 = "<";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 62) {
- result0 = ">";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 92) {
- result0 = "\\";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result0 === null) {
- result0 = parse_DQUOTE();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 93) {
- result0 = "]";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 123) {
- result0 = "{";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"{\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 125) {
- result0 = "}";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"}\"");
- }
- }
- if (result0 === null) {
- result0 = parse_SP();
- if (result0 === null) {
- result0 = parse_HTAB();
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_word() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 40) {
- result1 = "(";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 41) {
- result1 = ")";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 60) {
- result1 = "<";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 62) {
- result1 = ">";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 92) {
- result1 = "\\";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result1 === null) {
- result1 = parse_DQUOTE();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 91) {
- result1 = "[";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 93) {
- result1 = "]";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 63) {
- result1 = "?";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 123) {
- result1 = "{";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"{\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 125) {
- result1 = "}";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"}\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 40) {
- result1 = "(";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 41) {
- result1 = ")";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 60) {
- result1 = "<";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 62) {
- result1 = ">";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 92) {
- result1 = "\\";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result1 === null) {
- result1 = parse_DQUOTE();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 91) {
- result1 = "[";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 93) {
- result1 = "]";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 63) {
- result1 = "?";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 123) {
- result1 = "{";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"{\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 125) {
- result1 = "}";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"}\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_STAR() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "*"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_SLASH() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "/"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_EQUAL() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "="; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_LPAREN() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 40) {
- result1 = "(";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "("; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_RPAREN() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 41) {
- result1 = ")";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ")"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_RAQUOT() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 62) {
- result0 = ">";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_SWS();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ">"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_LAQUOT() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 60) {
- result1 = "<";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "<"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_COMMA() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ","; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_SEMI() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ";"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_COLON() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ":"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_LDQUOT() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- result1 = parse_DQUOTE();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "\""; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_RDQUOT() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DQUOTE();
- if (result0 !== null) {
- result1 = parse_SWS();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "\""; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_comment() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_LPAREN();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_ctext();
- if (result2 === null) {
- result2 = parse_quoted_pair();
- if (result2 === null) {
- result2 = parse_comment();
- }
- }
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_ctext();
- if (result2 === null) {
- result2 = parse_quoted_pair();
- if (result2 === null) {
- result2 = parse_comment();
- }
- }
- }
- if (result1 !== null) {
- result2 = parse_RPAREN();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_ctext() {
- var result0;
- if (/^[!-']/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[!-']");
- }
- }
- if (result0 === null) {
- if (/^[*-[]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[*-[]");
- }
- }
- if (result0 === null) {
- if (/^[\]-~]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\]-~]");
- }
- }
- if (result0 === null) {
- result0 = parse_UTF8_NONASCII();
- if (result0 === null) {
- result0 = parse_LWS();
- }
- }
- }
- }
- return result0;
- }
- function parse_quoted_string() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- result1 = parse_DQUOTE();
- if (result1 !== null) {
- result2 = [];
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- }
- if (result2 !== null) {
- result3 = parse_DQUOTE();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_quoted_string_clean() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- result1 = parse_DQUOTE();
- if (result1 !== null) {
- result2 = [];
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- }
- if (result2 !== null) {
- result3 = parse_DQUOTE();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos-1, offset+1); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_qdtext() {
- var result0;
- result0 = parse_LWS();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 33) {
- result0 = "!";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result0 === null) {
- if (/^[#-[]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[#-[]");
- }
- }
- if (result0 === null) {
- if (/^[\]-~]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\]-~]");
- }
- }
- if (result0 === null) {
- result0 = parse_UTF8_NONASCII();
- }
- }
- }
- }
- return result0;
- }
- function parse_quoted_pair() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- if (input.charCodeAt(pos) === 92) {
- result0 = "\\";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result0 !== null) {
- if (/^[\0-\t]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[\\0-\\t]");
- }
- }
- if (result1 === null) {
- if (/^[\x0B-\f]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x0B-\\f]");
- }
- }
- if (result1 === null) {
- if (/^[\x0E-]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x0E-]");
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_SIP_URI_noparams() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_uri_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_userinfo();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_hostport();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- try {
- data.uri = new URI(data.scheme, data.user, data.host, data.port);
- delete data.scheme;
- delete data.user;
- delete data.host;
- delete data.host_type;
- delete data.port;
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_SIP_URI() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_uri_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_userinfo();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_hostport();
- if (result3 !== null) {
- result4 = parse_uri_parameters();
- if (result4 !== null) {
- result5 = parse_headers();
- result5 = result5 !== null ? result5 : "";
- if (result5 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var header;
- try {
- data.uri = new URI(data.scheme, data.user, data.host, data.port, data.uri_params, data.uri_headers);
- delete data.scheme;
- delete data.user;
- delete data.host;
- delete data.host_type;
- delete data.port;
- delete data.uri_params;
- if (startRule === 'SIP_URI') { data = data.uri;}
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_uri_scheme() {
- var result0;
- result0 = parse_uri_scheme_sips();
- if (result0 === null) {
- result0 = parse_uri_scheme_sip();
- }
- return result0;
- }
- function parse_uri_scheme_sips() {
- var result0;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 4).toLowerCase() === "sips") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"sips\"");
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, scheme) {
- data.scheme = scheme.toLowerCase(); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_uri_scheme_sip() {
- var result0;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 3).toLowerCase() === "sip") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"sip\"");
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, scheme) {
- data.scheme = scheme.toLowerCase(); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_userinfo() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_user();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_password();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 64) {
- result2 = "@";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.user = decodeURIComponent(input.substring(pos-1, offset));})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_user() {
- var result0, result1;
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_user_unreserved();
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_user_unreserved();
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
- function parse_user_unreserved() {
- var result0;
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_password() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result0 = [];
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.password = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_hostport() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_host();
- if (result0 !== null) {
- pos1 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_port();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos1;
- }
- } else {
- result1 = null;
- pos = pos1;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_host() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_hostname();
- if (result0 === null) {
- result0 = parse_IPv4address();
- if (result0 === null) {
- result0 = parse_IPv6reference();
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host = input.substring(pos, offset).toLowerCase();
- return data.host; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_hostname() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = [];
- pos2 = pos;
- result1 = parse_domainlabel();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- while (result1 !== null) {
- result0.push(result1);
- pos2 = pos;
- result1 = parse_domainlabel();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- }
- if (result0 !== null) {
- result1 = parse_toplabel();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'domain';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_domainlabel() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_alphanum();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_alphanum();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 95) {
- result2 = "_";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- }
- }
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_alphanum();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 95) {
- result2 = "_";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_toplabel() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_ALPHA();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_alphanum();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 95) {
- result2 = "_";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- }
- }
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_alphanum();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 95) {
- result2 = "_";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_IPv6reference() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_IPv6address();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 93) {
- result2 = "]";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'IPv6';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_IPv6address() {
- var result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11, result12;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result7 = ":";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_h16();
- if (result8 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result9 = ":";
- pos++;
- } else {
- result9 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result9 !== null) {
- result10 = parse_h16();
- if (result10 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result11 = ":";
- pos++;
- } else {
- result11 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result11 !== null) {
- result12 = parse_ls32();
- if (result12 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11, result12];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result8 = ":";
- pos++;
- } else {
- result8 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result8 !== null) {
- result9 = parse_h16();
- if (result9 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result10 = ":";
- pos++;
- } else {
- result10 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result10 !== null) {
- result11 = parse_ls32();
- if (result11 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result8 = ":";
- pos++;
- } else {
- result8 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result8 !== null) {
- result9 = parse_ls32();
- if (result9 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_ls32();
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_ls32();
- if (result5 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_ls32();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_ls32();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- if (input.substr(pos, 2) === "::") {
- result1 = "::";
- pos += 2;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result7 = ":";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_h16();
- if (result8 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result9 = ":";
- pos++;
- } else {
- result9 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result9 !== null) {
- result10 = parse_ls32();
- if (result10 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- if (input.substr(pos, 2) === "::") {
- result2 = "::";
- pos += 2;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result8 = ":";
- pos++;
- } else {
- result8 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result8 !== null) {
- result9 = parse_ls32();
- if (result9 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- if (input.substr(pos, 2) === "::") {
- result3 = "::";
- pos += 2;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result7 = ":";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_ls32();
- if (result8 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- if (input.substr(pos, 2) === "::") {
- result4 = "::";
- pos += 2;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_ls32();
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos2;
- }
- } else {
- result4 = null;
- pos = pos2;
- }
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- if (input.substr(pos, 2) === "::") {
- result5 = "::";
- pos += 2;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_ls32();
- if (result6 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos2;
- }
- } else {
- result4 = null;
- pos = pos2;
- }
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- result5 = result5 !== null ? result5 : "";
- if (result5 !== null) {
- if (input.substr(pos, 2) === "::") {
- result6 = "::";
- pos += 2;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos2;
- }
- } else {
- result4 = null;
- pos = pos2;
- }
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- result5 = result5 !== null ? result5 : "";
- if (result5 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- result6 = [result6, result7];
- } else {
- result6 = null;
- pos = pos2;
- }
- } else {
- result6 = null;
- pos = pos2;
- }
- result6 = result6 !== null ? result6 : "";
- if (result6 !== null) {
- if (input.substr(pos, 2) === "::") {
- result7 = "::";
- pos += 2;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'IPv6';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_h16() {
- var result0, result1, result2, result3;
- var pos0;
- pos0 = pos;
- result0 = parse_HEXDIG();
- if (result0 !== null) {
- result1 = parse_HEXDIG();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_HEXDIG();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_HEXDIG();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_ls32() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_IPv4address();
- }
- return result0;
- }
- function parse_IPv4address() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_dec_octet();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_dec_octet();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result3 = ".";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_dec_octet();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result5 = ".";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_dec_octet();
- if (result6 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'IPv4';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_dec_octet() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 2) === "25") {
- result0 = "25";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"25\"");
- }
- }
- if (result0 !== null) {
- if (/^[0-5]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[0-5]");
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- if (input.charCodeAt(pos) === 50) {
- result0 = "2";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"2\"");
- }
- }
- if (result0 !== null) {
- if (/^[0-4]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[0-4]");
- }
- }
- if (result1 !== null) {
- result2 = parse_DIGIT();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- if (input.charCodeAt(pos) === 49) {
- result0 = "1";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"1\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result2 = parse_DIGIT();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- if (/^[1-9]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[1-9]");
- }
- }
- if (result0 !== null) {
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_DIGIT();
- }
- }
- }
- }
- return result0;
- }
- function parse_port() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DIGIT();
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_DIGIT();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_DIGIT();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result4 = parse_DIGIT();
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, port) {
- port = parseInt(port.join(''));
- data.port = port;
- return port; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_uri_parameters() {
- var result0, result1, result2;
- var pos0;
- result0 = [];
- pos0 = pos;
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_uri_parameter();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos0;
- }
- } else {
- result1 = null;
- pos = pos0;
- }
- while (result1 !== null) {
- result0.push(result1);
- pos0 = pos;
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_uri_parameter();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos0;
- }
- } else {
- result1 = null;
- pos = pos0;
- }
- }
- return result0;
- }
- function parse_uri_parameter() {
- var result0;
- result0 = parse_transport_param();
- if (result0 === null) {
- result0 = parse_user_param();
- if (result0 === null) {
- result0 = parse_method_param();
- if (result0 === null) {
- result0 = parse_ttl_param();
- if (result0 === null) {
- result0 = parse_maddr_param();
- if (result0 === null) {
- result0 = parse_lr_param();
- if (result0 === null) {
- result0 = parse_other_param();
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_transport_param() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 10).toLowerCase() === "transport=") {
- result0 = input.substr(pos, 10);
- pos += 10;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"transport=\"");
- }
- }
- if (result0 !== null) {
- if (input.substr(pos, 3).toLowerCase() === "udp") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"udp\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tcp") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"tcp\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 4).toLowerCase() === "sctp") {
- result1 = input.substr(pos, 4);
- pos += 4;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"sctp\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tls") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"tls\"");
- }
- }
- if (result1 === null) {
- result1 = parse_token();
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, transport) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['transport'] = transport.toLowerCase(); })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_user_param() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "user=") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"user=\"");
- }
- }
- if (result0 !== null) {
- if (input.substr(pos, 5).toLowerCase() === "phone") {
- result1 = input.substr(pos, 5);
- pos += 5;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"phone\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 2).toLowerCase() === "ip") {
- result1 = input.substr(pos, 2);
- pos += 2;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"ip\"");
- }
- }
- if (result1 === null) {
- result1 = parse_token();
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, user) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['user'] = user.toLowerCase(); })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_method_param() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 7).toLowerCase() === "method=") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"method=\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_Method();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, method) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['method'] = method; })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_ttl_param() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 4).toLowerCase() === "ttl=") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"ttl=\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_ttl();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, ttl) {
- if(!data.params) data.params={};
- data.params['ttl'] = ttl; })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_maddr_param() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "maddr=") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"maddr=\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_host();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, maddr) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['maddr'] = maddr; })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_lr_param() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 2).toLowerCase() === "lr") {
- result0 = input.substr(pos, 2);
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"lr\"");
- }
- }
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['lr'] = undefined; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_other_param() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_pname();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_pvalue();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, param, value) {
- if(!data.uri_params) data.uri_params = {};
- if (typeof value === 'undefined'){
- value = undefined;
- }
- else {
- value = value[1];
- }
- data.uri_params[param.toLowerCase()] = value;})(pos0, result0[0], result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_pname() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_paramchar();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_paramchar();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, pname) {return pname.join(''); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_pvalue() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_paramchar();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_paramchar();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, pvalue) {return pvalue.join(''); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_paramchar() {
- var result0;
- result0 = parse_param_unreserved();
- if (result0 === null) {
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- }
- }
- return result0;
- }
- function parse_param_unreserved() {
- var result0;
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 93) {
- result0 = "]";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_headers() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1;
- pos0 = pos;
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_header();
- if (result1 !== null) {
- result2 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 38) {
- result3 = "&";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_header();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos1;
- }
- } else {
- result3 = null;
- pos = pos1;
- }
- while (result3 !== null) {
- result2.push(result3);
- pos1 = pos;
- if (input.charCodeAt(pos) === 38) {
- result3 = "&";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_header();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos1;
- }
- } else {
- result3 = null;
- pos = pos1;
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_header() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_hname();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_hvalue();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, hname, hvalue) {
- hname = hname.join('').toLowerCase();
- hvalue = hvalue.join('');
- if(!data.uri_headers) data.uri_headers = {};
- if (!data.uri_headers[hname]) {
- data.uri_headers[hname] = [hvalue];
- } else {
- data.uri_headers[hname].push(hvalue);
- }})(pos0, result0[0], result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_hname() {
- var result0, result1;
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
- function parse_hvalue() {
- var result0, result1;
- result0 = [];
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- }
- return result0;
- }
- function parse_hnv_unreserved() {
- var result0;
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 93) {
- result0 = "]";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_Request_Response() {
- var result0;
- result0 = parse_Status_Line();
- if (result0 === null) {
- result0 = parse_Request_Line();
- }
- return result0;
- }
- function parse_Request_Line() {
- var result0, result1, result2, result3, result4;
- var pos0;
- pos0 = pos;
- result0 = parse_Method();
- if (result0 !== null) {
- result1 = parse_SP();
- if (result1 !== null) {
- result2 = parse_Request_URI();
- if (result2 !== null) {
- result3 = parse_SP();
- if (result3 !== null) {
- result4 = parse_SIP_Version();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Request_URI() {
- var result0;
- result0 = parse_SIP_URI();
- if (result0 === null) {
- result0 = parse_absoluteURI();
- }
- return result0;
- }
- function parse_absoluteURI() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_hier_part();
- if (result2 === null) {
- result2 = parse_opaque_part();
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_hier_part() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_net_path();
- if (result0 === null) {
- result0 = parse_abs_path();
- }
- if (result0 !== null) {
- pos1 = pos;
- if (input.charCodeAt(pos) === 63) {
- result1 = "?";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_query();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos1;
- }
- } else {
- result1 = null;
- pos = pos1;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_net_path() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 2) === "//") {
- result0 = "//";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"//\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_authority();
- if (result1 !== null) {
- result2 = parse_abs_path();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_abs_path() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_path_segments();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_opaque_part() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_uric_no_slash();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_uric();
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_uric();
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_uric() {
- var result0;
- result0 = parse_reserved();
- if (result0 === null) {
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- }
- }
- return result0;
- }
- function parse_uric_no_slash() {
- var result0;
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_path_segments() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_segment();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 47) {
- result2 = "/";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_segment();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- if (input.charCodeAt(pos) === 47) {
- result2 = "/";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_segment();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_segment() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = [];
- result1 = parse_pchar();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_pchar();
- }
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 59) {
- result2 = ";";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- if (input.charCodeAt(pos) === 59) {
- result2 = ";";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_param() {
- var result0, result1;
- result0 = [];
- result1 = parse_pchar();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_pchar();
- }
- return result0;
- }
- function parse_pchar() {
- var result0;
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_scheme() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_ALPHA();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_ALPHA();
- if (result2 === null) {
- result2 = parse_DIGIT();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 43) {
- result2 = "+";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- }
- }
- }
- }
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_ALPHA();
- if (result2 === null) {
- result2 = parse_DIGIT();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 43) {
- result2 = "+";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.scheme= input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_authority() {
- var result0;
- result0 = parse_srvr();
- if (result0 === null) {
- result0 = parse_reg_name();
- }
- return result0;
- }
- function parse_srvr() {
- var result0, result1;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_userinfo();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_hostport();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
- function parse_reg_name() {
- var result0, result1;
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
- function parse_query() {
- var result0, result1;
- result0 = [];
- result1 = parse_uric();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_uric();
- }
- return result0;
- }
- function parse_SIP_Version() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 3).toLowerCase() === "sip") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SIP\"");
- }
- }
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 !== null) {
- result3 = parse_DIGIT();
- if (result3 !== null) {
- result2 = [];
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_DIGIT();
- }
- } else {
- result2 = null;
- }
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result3 = ".";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result3 !== null) {
- result5 = parse_DIGIT();
- if (result5 !== null) {
- result4 = [];
- while (result5 !== null) {
- result4.push(result5);
- result5 = parse_DIGIT();
- }
- } else {
- result4 = null;
- }
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.sip_version = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_INVITEm() {
- var result0;
- if (input.substr(pos, 6) === "INVITE") {
- result0 = "INVITE";
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"INVITE\"");
- }
- }
- return result0;
- }
- function parse_ACKm() {
- var result0;
- if (input.substr(pos, 3) === "ACK") {
- result0 = "ACK";
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"ACK\"");
- }
- }
- return result0;
- }
- function parse_OPTIONSm() {
- var result0;
- if (input.substr(pos, 7) === "OPTIONS") {
- result0 = "OPTIONS";
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"OPTIONS\"");
- }
- }
- return result0;
- }
- function parse_BYEm() {
- var result0;
- if (input.substr(pos, 3) === "BYE") {
- result0 = "BYE";
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"BYE\"");
- }
- }
- return result0;
- }
- function parse_CANCELm() {
- var result0;
- if (input.substr(pos, 6) === "CANCEL") {
- result0 = "CANCEL";
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"CANCEL\"");
- }
- }
- return result0;
- }
- function parse_REGISTERm() {
- var result0;
- if (input.substr(pos, 8) === "REGISTER") {
- result0 = "REGISTER";
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"REGISTER\"");
- }
- }
- return result0;
- }
- function parse_SUBSCRIBEm() {
- var result0;
- if (input.substr(pos, 9) === "SUBSCRIBE") {
- result0 = "SUBSCRIBE";
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SUBSCRIBE\"");
- }
- }
- return result0;
- }
- function parse_NOTIFYm() {
- var result0;
- if (input.substr(pos, 6) === "NOTIFY") {
- result0 = "NOTIFY";
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"NOTIFY\"");
- }
- }
- return result0;
- }
- function parse_REFERm() {
- var result0;
- if (input.substr(pos, 5) === "REFER") {
- result0 = "REFER";
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"REFER\"");
- }
- }
- return result0;
- }
- function parse_Method() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_INVITEm();
- if (result0 === null) {
- result0 = parse_ACKm();
- if (result0 === null) {
- result0 = parse_OPTIONSm();
- if (result0 === null) {
- result0 = parse_BYEm();
- if (result0 === null) {
- result0 = parse_CANCELm();
- if (result0 === null) {
- result0 = parse_REGISTERm();
- if (result0 === null) {
- result0 = parse_SUBSCRIBEm();
- if (result0 === null) {
- result0 = parse_NOTIFYm();
- if (result0 === null) {
- result0 = parse_REFERm();
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.method = input.substring(pos, offset);
- return data.method; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Status_Line() {
- var result0, result1, result2, result3, result4;
- var pos0;
- pos0 = pos;
- result0 = parse_SIP_Version();
- if (result0 !== null) {
- result1 = parse_SP();
- if (result1 !== null) {
- result2 = parse_Status_Code();
- if (result2 !== null) {
- result3 = parse_SP();
- if (result3 !== null) {
- result4 = parse_Reason_Phrase();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Status_Code() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_extension_code();
- if (result0 !== null) {
- result0 = (function(offset, status_code) {
- data.status_code = parseInt(status_code.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_extension_code() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_DIGIT();
- if (result0 !== null) {
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result2 = parse_DIGIT();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Reason_Phrase() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result0 = [];
- result1 = parse_reserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_UTF8_NONASCII();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- }
- }
- }
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_reserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_UTF8_NONASCII();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.reason_phrase = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Allow_Events() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_event_type();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_event_type();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_event_type();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Call_ID() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_word();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_word();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Contact() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- result0 = parse_STAR();
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_contact_param();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_contact_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_contact_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var idx, length;
- length = data.multi_header.length;
- for (idx = 0; idx < length; idx++) {
- if (data.multi_header[idx].parsed === null) {
- data = null;
- break;
- }
- }
- if (data !== null) {
- data = data.multi_header;
- } else {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_contact_param() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SIP_URI_noparams();
- if (result0 === null) {
- result0 = parse_name_addr();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_contact_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_contact_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var header;
- if(!data.multi_header) data.multi_header = [];
- try {
- header = new NameAddrHeader(data.uri, data.display_name, data.params);
- delete data.uri;
- delete data.display_name;
- delete data.params;
- } catch(e) {
- header = null;
- }
- data.multi_header.push( { 'possition': pos,
- 'offset': offset,
- 'parsed': header
- });})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_name_addr() {
- var result0, result1, result2, result3;
- var pos0;
- pos0 = pos;
- result0 = parse_display_name();
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_LAQUOT();
- if (result1 !== null) {
- result2 = parse_SIP_URI();
- if (result2 !== null) {
- result3 = parse_RAQUOT();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_display_name() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_LWS();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_LWS();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- result0 = parse_quoted_string();
- }
- if (result0 !== null) {
- result0 = (function(offset, display_name) {
- display_name = input.substring(pos, offset).trim();
- if (display_name[0] === '\"') {
- display_name = display_name.substring(1, display_name.length-1);
- }
- data.display_name = display_name; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_contact_params() {
- var result0;
- result0 = parse_c_p_q();
- if (result0 === null) {
- result0 = parse_c_p_expires();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- }
- return result0;
- }
- function parse_c_p_q() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 1).toLowerCase() === "q") {
- result0 = input.substr(pos, 1);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"q\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_qvalue();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, q) {
- if(!data.params) data.params = {};
- data.params['q'] = q; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_c_p_expires() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 7).toLowerCase() === "expires") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"expires\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_delta_seconds();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, expires) {
- if(!data.params) data.params = {};
- data.params['expires'] = expires; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_delta_seconds() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, delta_seconds) {
- return parseInt(delta_seconds.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_qvalue() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 48) {
- result0 = "0";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"0\"");
- }
- }
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_DIGIT();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result4 = parse_DIGIT();
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- result1 = [result1, result2, result3, result4];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return parseFloat(input.substring(pos, offset)); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_generic_param() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- pos2 = pos;
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_gen_value();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, param, value) {
- if(!data.params) data.params = {};
- if (typeof value === 'undefined'){
- value = undefined;
- }
- else {
- value = value[1];
- }
- data.params[param.toLowerCase()] = value;})(pos0, result0[0], result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_gen_value() {
- var result0;
- result0 = parse_token();
- if (result0 === null) {
- result0 = parse_host();
- if (result0 === null) {
- result0 = parse_quoted_string();
- }
- }
- return result0;
- }
- function parse_Content_Disposition() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_disp_type();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_disp_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_disp_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_disp_type() {
- var result0;
- if (input.substr(pos, 6).toLowerCase() === "render") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"render\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 7).toLowerCase() === "session") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"session\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "icon") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"icon\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "alert") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"alert\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- return result0;
- }
- function parse_disp_param() {
- var result0;
- result0 = parse_handling_param();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
- function parse_handling_param() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 8).toLowerCase() === "handling") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"handling\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- if (input.substr(pos, 8).toLowerCase() === "optional") {
- result2 = input.substr(pos, 8);
- pos += 8;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"optional\"");
- }
- }
- if (result2 === null) {
- if (input.substr(pos, 8).toLowerCase() === "required") {
- result2 = input.substr(pos, 8);
- pos += 8;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"required\"");
- }
- }
- if (result2 === null) {
- result2 = parse_token();
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Content_Encoding() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Content_Length() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, length) {
- data = parseInt(length.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Content_Type() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_media_type();
- if (result0 !== null) {
- result0 = (function(offset) {
- data = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_media_type() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_m_type();
- if (result0 !== null) {
- result1 = parse_SLASH();
- if (result1 !== null) {
- result2 = parse_m_subtype();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_m_parameter();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_m_parameter();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_m_type() {
- var result0;
- result0 = parse_discrete_type();
- if (result0 === null) {
- result0 = parse_composite_type();
- }
- return result0;
- }
- function parse_discrete_type() {
- var result0;
- if (input.substr(pos, 4).toLowerCase() === "text") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"text\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "image") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"image\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "audio") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"audio\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "video") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"video\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 11).toLowerCase() === "application") {
- result0 = input.substr(pos, 11);
- pos += 11;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"application\"");
- }
- }
- if (result0 === null) {
- result0 = parse_extension_token();
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_composite_type() {
- var result0;
- if (input.substr(pos, 7).toLowerCase() === "message") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"message\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 9).toLowerCase() === "multipart") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"multipart\"");
- }
- }
- if (result0 === null) {
- result0 = parse_extension_token();
- }
- }
- return result0;
- }
- function parse_extension_token() {
- var result0;
- result0 = parse_token();
- if (result0 === null) {
- result0 = parse_x_token();
- }
- return result0;
- }
- function parse_x_token() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 2).toLowerCase() === "x-") {
- result0 = input.substr(pos, 2);
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"x-\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_token();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_m_subtype() {
- var result0;
- result0 = parse_extension_token();
- if (result0 === null) {
- result0 = parse_token();
- }
- return result0;
- }
- function parse_m_parameter() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_m_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_m_value() {
- var result0;
- result0 = parse_token();
- if (result0 === null) {
- result0 = parse_quoted_string();
- }
- return result0;
- }
- function parse_CSeq() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_CSeq_value();
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_Method();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_CSeq_value() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, cseq_value) {
- data.value=parseInt(cseq_value.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Expires() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_delta_seconds();
- if (result0 !== null) {
- result0 = (function(offset, expires) {data = expires; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Event() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_event_type();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, event_type) {
- data.event = event_type.join('').toLowerCase(); })(pos0, result0[0]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_event_type() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_token_nodot();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_token_nodot();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_token_nodot();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_From() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SIP_URI_noparams();
- if (result0 === null) {
- result0 = parse_name_addr();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_from_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_from_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var tag = data.tag;
- try {
- data = new NameAddrHeader(data.uri, data.display_name, data.params);
- if (tag) {data.setParam('tag',tag)}
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_from_param() {
- var result0;
- result0 = parse_tag_param();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
- function parse_tag_param() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 3).toLowerCase() === "tag") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"tag\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, tag) {data.tag = tag; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Max_Forwards() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, forwards) {
- data = parseInt(forwards.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Min_Expires() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_delta_seconds();
- if (result0 !== null) {
- result0 = (function(offset, min_expires) {data = min_expires; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Name_Addr_Header() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = [];
- result1 = parse_display_name();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_display_name();
- }
- if (result0 !== null) {
- result1 = parse_LAQUOT();
- if (result1 !== null) {
- result2 = parse_SIP_URI();
- if (result2 !== null) {
- result3 = parse_RAQUOT();
- if (result3 !== null) {
- result4 = [];
- pos2 = pos;
- result5 = parse_SEMI();
- if (result5 !== null) {
- result6 = parse_generic_param();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- while (result5 !== null) {
- result4.push(result5);
- pos2 = pos;
- result5 = parse_SEMI();
- if (result5 !== null) {
- result6 = parse_generic_param();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- }
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- try {
- data = new NameAddrHeader(data.uri, data.display_name, data.params);
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Proxy_Authenticate() {
- var result0;
- result0 = parse_challenge();
- return result0;
- }
- function parse_challenge() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
- pos0 = pos;
- if (input.substr(pos, 6).toLowerCase() === "digest") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"Digest\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_digest_cln();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_digest_cln();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_digest_cln();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_other_challenge();
- }
- return result0;
- }
- function parse_other_challenge() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_auth_param();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_auth_param();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_auth_param();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_auth_param() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 === null) {
- result2 = parse_quoted_string();
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_digest_cln() {
- var result0;
- result0 = parse_realm();
- if (result0 === null) {
- result0 = parse_domain();
- if (result0 === null) {
- result0 = parse_nonce();
- if (result0 === null) {
- result0 = parse_opaque();
- if (result0 === null) {
- result0 = parse_stale();
- if (result0 === null) {
- result0 = parse_algorithm();
- if (result0 === null) {
- result0 = parse_qop_options();
- if (result0 === null) {
- result0 = parse_auth_param();
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_realm() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "realm") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"realm\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_realm_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_realm_value() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_quoted_string_clean();
- if (result0 !== null) {
- result0 = (function(offset, realm) { data.realm = realm; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_domain() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1;
- pos0 = pos;
- if (input.substr(pos, 6).toLowerCase() === "domain") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"domain\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_LDQUOT();
- if (result2 !== null) {
- result3 = parse_URI();
- if (result3 !== null) {
- result4 = [];
- pos1 = pos;
- result6 = parse_SP();
- if (result6 !== null) {
- result5 = [];
- while (result6 !== null) {
- result5.push(result6);
- result6 = parse_SP();
- }
- } else {
- result5 = null;
- }
- if (result5 !== null) {
- result6 = parse_URI();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos1;
- }
- } else {
- result5 = null;
- pos = pos1;
- }
- while (result5 !== null) {
- result4.push(result5);
- pos1 = pos;
- result6 = parse_SP();
- if (result6 !== null) {
- result5 = [];
- while (result6 !== null) {
- result5.push(result6);
- result6 = parse_SP();
- }
- } else {
- result5 = null;
- }
- if (result5 !== null) {
- result6 = parse_URI();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos1;
- }
- } else {
- result5 = null;
- pos = pos1;
- }
- }
- if (result4 !== null) {
- result5 = parse_RDQUOT();
- if (result5 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_URI() {
- var result0;
- result0 = parse_absoluteURI();
- if (result0 === null) {
- result0 = parse_abs_path();
- }
- return result0;
- }
- function parse_nonce() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "nonce") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"nonce\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_nonce_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_nonce_value() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_quoted_string_clean();
- if (result0 !== null) {
- result0 = (function(offset, nonce) { data.nonce=nonce; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_opaque() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "opaque") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"opaque\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_quoted_string_clean();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, opaque) { data.opaque=opaque; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_stale() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "stale") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"stale\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- pos1 = pos;
- if (input.substr(pos, 4).toLowerCase() === "true") {
- result2 = input.substr(pos, 4);
- pos += 4;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"true\"");
- }
- }
- if (result2 !== null) {
- result2 = (function(offset) { data.stale=true; })(pos1);
- }
- if (result2 === null) {
- pos = pos1;
- }
- if (result2 === null) {
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "false") {
- result2 = input.substr(pos, 5);
- pos += 5;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"false\"");
- }
- }
- if (result2 !== null) {
- result2 = (function(offset) { data.stale=false; })(pos1);
- }
- if (result2 === null) {
- pos = pos1;
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_algorithm() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 9).toLowerCase() === "algorithm") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"algorithm\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- if (input.substr(pos, 3).toLowerCase() === "md5") {
- result2 = input.substr(pos, 3);
- pos += 3;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"MD5\"");
- }
- }
- if (result2 === null) {
- if (input.substr(pos, 8).toLowerCase() === "md5-sess") {
- result2 = input.substr(pos, 8);
- pos += 8;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"MD5-sess\"");
- }
- }
- if (result2 === null) {
- result2 = parse_token();
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, algorithm) {
- data.algorithm=algorithm.toUpperCase(); })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_qop_options() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1, pos2;
- pos0 = pos;
- if (input.substr(pos, 3).toLowerCase() === "qop") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"qop\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_LDQUOT();
- if (result2 !== null) {
- pos1 = pos;
- result3 = parse_qop_value();
- if (result3 !== null) {
- result4 = [];
- pos2 = pos;
- if (input.charCodeAt(pos) === 44) {
- result5 = ",";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_qop_value();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- while (result5 !== null) {
- result4.push(result5);
- pos2 = pos;
- if (input.charCodeAt(pos) === 44) {
- result5 = ",";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_qop_value();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- }
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos1;
- }
- } else {
- result3 = null;
- pos = pos1;
- }
- if (result3 !== null) {
- result4 = parse_RDQUOT();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_qop_value() {
- var result0;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 8).toLowerCase() === "auth-int") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"auth-int\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "auth") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"auth\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, qop_value) {
- data.qop || (data.qop=[]);
- data.qop.push(qop_value.toLowerCase()); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Proxy_Require() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Record_Route() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_rec_route();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_rec_route();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_rec_route();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var idx, length;
- length = data.multi_header.length;
- for (idx = 0; idx < length; idx++) {
- if (data.multi_header[idx].parsed === null) {
- data = null;
- break;
- }
- }
- if (data !== null) {
- data = data.multi_header;
- } else {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_rec_route() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_name_addr();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var header;
- if(!data.multi_header) data.multi_header = [];
- try {
- header = new NameAddrHeader(data.uri, data.display_name, data.params);
- delete data.uri;
- delete data.display_name;
- delete data.params;
- } catch(e) {
- header = null;
- }
- data.multi_header.push( { 'possition': pos,
- 'offset': offset,
- 'parsed': header
- });})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Reason() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 3).toLowerCase() === "sip") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SIP\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_reason_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_reason_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, protocol) {
- data.protocol = protocol.toLowerCase();
- if (!data.params) data.params = {};
- if (data.params.text && data.params.text[0] === '"') {
- var text = data.params.text;
- data.text = text.substring(1, text.length-1);
- delete data.params.text;
- }
- })(pos0, result0[0]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_reason_param() {
- var result0;
- result0 = parse_reason_cause();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
- function parse_reason_cause() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "cause") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"cause\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result3 = parse_DIGIT();
- if (result3 !== null) {
- result2 = [];
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_DIGIT();
- }
- } else {
- result2 = null;
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, cause) {
- data.cause = parseInt(cause.join(''));
- })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Require() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Route() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_route_param();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_route_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_route_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_route_param() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_name_addr();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Subscription_State() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_substate_value();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_subexp_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_subexp_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_substate_value() {
- var result0;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 6).toLowerCase() === "active") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"active\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 7).toLowerCase() === "pending") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"pending\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 10).toLowerCase() === "terminated") {
- result0 = input.substr(pos, 10);
- pos += 10;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"terminated\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.state = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_subexp_params() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "reason") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"reason\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_event_reason_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, reason) {
- if (typeof reason !== 'undefined') data.reason = reason; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 7).toLowerCase() === "expires") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"expires\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_delta_seconds();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, expires) {
- if (typeof expires !== 'undefined') data.expires = expires; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 11).toLowerCase() === "retry_after") {
- result0 = input.substr(pos, 11);
- pos += 11;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"retry_after\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_delta_seconds();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, retry_after) {
- if (typeof retry_after !== 'undefined') data.retry_after = retry_after; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- }
- }
- return result0;
- }
- function parse_event_reason_value() {
- var result0;
- if (input.substr(pos, 11).toLowerCase() === "deactivated") {
- result0 = input.substr(pos, 11);
- pos += 11;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"deactivated\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 9).toLowerCase() === "probation") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"probation\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 8).toLowerCase() === "rejected") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"rejected\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 7).toLowerCase() === "timeout") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"timeout\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 6).toLowerCase() === "giveup") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"giveup\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 10).toLowerCase() === "noresource") {
- result0 = input.substr(pos, 10);
- pos += 10;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"noresource\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 9).toLowerCase() === "invariant") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"invariant\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_Subject() {
- var result0;
- result0 = parse_TEXT_UTF8_TRIM();
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
- function parse_Supported() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
- function parse_To() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SIP_URI_noparams();
- if (result0 === null) {
- result0 = parse_name_addr();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_to_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_to_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var tag = data.tag;
- try {
- data = new NameAddrHeader(data.uri, data.display_name, data.params);
- if (tag) {data.setParam('tag',tag)}
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_to_param() {
- var result0;
- result0 = parse_tag_param();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
- function parse_Via() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_via_param();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_via_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_via_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_via_param() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_sent_protocol();
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_sent_by();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_via_params();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_via_params();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_via_params() {
- var result0;
- result0 = parse_via_ttl();
- if (result0 === null) {
- result0 = parse_via_maddr();
- if (result0 === null) {
- result0 = parse_via_received();
- if (result0 === null) {
- result0 = parse_via_branch();
- if (result0 === null) {
- result0 = parse_response_port();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- }
- }
- }
- }
- return result0;
- }
- function parse_via_ttl() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 3).toLowerCase() === "ttl") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"ttl\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_ttl();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_ttl_value) {
- data.ttl = via_ttl_value; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_via_maddr() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "maddr") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"maddr\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_host();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_maddr) {
- data.maddr = via_maddr; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_via_received() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 8).toLowerCase() === "received") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"received\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_IPv4address();
- if (result2 === null) {
- result2 = parse_IPv6address();
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_received) {
- data.received = via_received; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_via_branch() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "branch") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"branch\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_branch) {
- data.branch = via_branch; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_response_port() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "rport") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"rport\"");
- }
- }
- if (result0 !== null) {
- pos2 = pos;
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = [];
- result3 = parse_DIGIT();
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_DIGIT();
- }
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- if(typeof response_port !== 'undefined')
- data.rport = response_port.join(''); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_sent_protocol() {
- var result0, result1, result2, result3, result4;
- var pos0;
- pos0 = pos;
- result0 = parse_protocol_name();
- if (result0 !== null) {
- result1 = parse_SLASH();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result3 = parse_SLASH();
- if (result3 !== null) {
- result4 = parse_transport();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_protocol_name() {
- var result0;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 3).toLowerCase() === "sip") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SIP\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- if (result0 !== null) {
- result0 = (function(offset, via_protocol) {
- data.protocol = via_protocol; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_transport() {
- var result0;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 3).toLowerCase() === "udp") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"UDP\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tcp") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"TCP\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tls") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"TLS\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "sctp") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SCTP\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, via_transport) {
- data.transport = via_transport; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_sent_by() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_via_host();
- if (result0 !== null) {
- pos1 = pos;
- result1 = parse_COLON();
- if (result1 !== null) {
- result2 = parse_via_port();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos1;
- }
- } else {
- result1 = null;
- pos = pos1;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_via_host() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_IPv4address();
- if (result0 === null) {
- result0 = parse_IPv6reference();
- if (result0 === null) {
- result0 = parse_hostname();
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_via_port() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DIGIT();
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_DIGIT();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_DIGIT();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result4 = parse_DIGIT();
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_sent_by_port) {
- data.port = parseInt(via_sent_by_port.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_ttl() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DIGIT();
- if (result0 !== null) {
- result1 = parse_DIGIT();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, ttl) {
- return parseInt(ttl.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_WWW_Authenticate() {
- var result0;
- result0 = parse_challenge();
- return result0;
- }
- function parse_Session_Expires() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_s_e_expires();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_s_e_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_s_e_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_s_e_expires() {
- var result0;
- var pos0;
- pos0 = pos;
- result0 = parse_delta_seconds();
- if (result0 !== null) {
- result0 = (function(offset, expires) { data.expires = expires; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_s_e_params() {
- var result0;
- result0 = parse_s_e_refresher();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
- function parse_s_e_refresher() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 9).toLowerCase() === "refresher") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"refresher\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- if (input.substr(pos, 3).toLowerCase() === "uac") {
- result2 = input.substr(pos, 3);
- pos += 3;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"uac\"");
- }
- }
- if (result2 === null) {
- if (input.substr(pos, 3).toLowerCase() === "uas") {
- result2 = input.substr(pos, 3);
- pos += 3;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"uas\"");
- }
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, s_e_refresher_value) { data.refresher = s_e_refresher_value.toLowerCase(); })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_extension_header() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_HCOLON();
- if (result1 !== null) {
- result2 = parse_header_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_header_value() {
- var result0, result1;
- result0 = [];
- result1 = parse_TEXT_UTF8char();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_LWS();
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_TEXT_UTF8char();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_LWS();
- }
- }
- }
- return result0;
- }
- function parse_message_body() {
- var result0, result1;
- result0 = [];
- result1 = parse_OCTET();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_OCTET();
- }
- return result0;
- }
- function parse_uuid_URI() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 5) === "uuid:") {
- result0 = "uuid:";
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"uuid:\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_uuid();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_uuid() {
- var result0, result1, result2, result3, result4, result5, result6, result7, result8;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_hex8();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_hex4();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result3 = "-";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_hex4();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result5 = "-";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_hex4();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result7 = "-";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_hex12();
- if (result8 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, uuid) {
- data = input.substring(pos+5, offset); })(pos0, result0[0]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_hex4() {
- var result0, result1, result2, result3;
- var pos0;
- pos0 = pos;
- result0 = parse_HEXDIG();
- if (result0 !== null) {
- result1 = parse_HEXDIG();
- if (result1 !== null) {
- result2 = parse_HEXDIG();
- if (result2 !== null) {
- result3 = parse_HEXDIG();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_hex8() {
- var result0, result1;
- var pos0;
- pos0 = pos;
- result0 = parse_hex4();
- if (result0 !== null) {
- result1 = parse_hex4();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_hex12() {
- var result0, result1, result2;
- var pos0;
- pos0 = pos;
- result0 = parse_hex4();
- if (result0 !== null) {
- result1 = parse_hex4();
- if (result1 !== null) {
- result2 = parse_hex4();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_Refer_To() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SIP_URI_noparams();
- if (result0 === null) {
- result0 = parse_name_addr();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- try {
- data = new NameAddrHeader(data.uri, data.display_name, data.params);
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_Replaces() {
- var result0, result1, result2, result3;
- var pos0, pos1;
- pos0 = pos;
- result0 = parse_call_id();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_replaces_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_replaces_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
- function parse_call_id() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
- pos0 = pos;
- pos1 = pos;
- result0 = parse_word();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_word();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.call_id = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_replaces_param() {
- var result0;
- result0 = parse_to_tag();
- if (result0 === null) {
- result0 = parse_from_tag();
- if (result0 === null) {
- result0 = parse_early_flag();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- }
- }
- return result0;
- }
- function parse_to_tag() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6) === "to-tag") {
- result0 = "to-tag";
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"to-tag\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, to_tag) {
- data.to_tag = to_tag; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_from_tag() {
- var result0, result1, result2;
- var pos0, pos1;
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 8) === "from-tag") {
- result0 = "from-tag";
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"from-tag\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, from_tag) {
- data.from_tag = from_tag; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function parse_early_flag() {
- var result0;
- var pos0;
- pos0 = pos;
- if (input.substr(pos, 10) === "early-only") {
- result0 = "early-only";
- pos += 10;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"early-only\"");
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.early_only = true; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
- function cleanupExpected(expected) {
- expected.sort();
- var lastExpected = null;
- var cleanExpected = [];
- for (var i = 0; i < expected.length; i++) {
- if (expected[i] !== lastExpected) {
- cleanExpected.push(expected[i]);
- lastExpected = expected[i];
- }
- }
- return cleanExpected;
- }
- function computeErrorPosition() {
- /*
- * The first idea was to use |String.split| to break the input up to the
- * error position along newlines and derive the line and column from
- * there. However IE's |split| implementation is so broken that it was
- * enough to prevent it.
- */
- var line = 1;
- var column = 1;
- var seenCR = false;
- for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {
- var ch = input.charAt(i);
- if (ch === "\n") {
- if (!seenCR) { line++; }
- column = 1;
- seenCR = false;
- } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
- line++;
- column = 1;
- seenCR = true;
- } else {
- column++;
- seenCR = false;
- }
- }
- return { line: line, column: column };
- }
- var URI = require('./URI');
- var NameAddrHeader = require('./NameAddrHeader');
- var data = {};
- var result = parseFunctions[startRule]();
- /*
- * The parser is now in one of the following three states:
- *
- * 1. The parser successfully parsed the whole input.
- *
- * - |result !== null|
- * - |pos === input.length|
- * - |rightmostFailuresExpected| may or may not contain something
- *
- * 2. The parser successfully parsed only a part of the input.
- *
- * - |result !== null|
- * - |pos < input.length|
- * - |rightmostFailuresExpected| may or may not contain something
- *
- * 3. The parser did not successfully parse any part of the input.
- *
- * - |result === null|
- * - |pos === 0|
- * - |rightmostFailuresExpected| contains at least one failure
- *
- * All code following this comment (including called functions) must
- * handle these states.
- */
- if (result === null || pos !== input.length) {
- var offset = Math.max(pos, rightmostFailuresPos);
- var found = offset < input.length ? input.charAt(offset) : null;
- var errorPosition = computeErrorPosition();
- new this.SyntaxError(
- cleanupExpected(rightmostFailuresExpected),
- found,
- offset,
- errorPosition.line,
- errorPosition.column
- );
- return -1;
- }
- return data;
- },
- /* Returns the parser source code. */
- toSource: function() { return this._source; }
- };
- /* Thrown when a parser encounters a syntax error. */
- result.SyntaxError = function(expected, found, offset, line, column) {
- function buildMessage(expected, found) {
- var expectedHumanized, foundHumanized;
- switch (expected.length) {
- case 0:
- expectedHumanized = "end of input";
- break;
- case 1:
- expectedHumanized = expected[0];
- break;
- default:
- expectedHumanized = expected.slice(0, expected.length - 1).join(", ")
- + " or "
- + expected[expected.length - 1];
- }
- foundHumanized = found ? quote(found) : "end of input";
- return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";
- }
- this.name = "SyntaxError";
- this.expected = expected;
- this.found = found;
- this.message = buildMessage(expected, found);
- this.offset = offset;
- this.line = line;
- this.column = column;
- };
- result.SyntaxError.prototype = Error.prototype;
- return result;
- })();
- },{"./NameAddrHeader":9,"./URI":25}],7:[function(require,module,exports){
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP');
- var adapter = require('webrtc-adapter');
- var pkg = require('../package.json');
- debug('version %s', pkg.version);
- var C = require('./Constants');
- var Exceptions = require('./Exceptions');
- var Utils = require('./Utils');
- var UA = require('./UA');
- var URI = require('./URI');
- var NameAddrHeader = require('./NameAddrHeader');
- var Grammar = require('./Grammar');
- var WebSocketInterface = require('./WebSocketInterface');
- /**
- * Expose the JsSIP module.
- */
- var JsSIP = module.exports = {
- C: C,
- Exceptions: Exceptions,
- Utils: Utils,
- UA: UA,
- URI: URI,
- NameAddrHeader: NameAddrHeader,
- WebSocketInterface: WebSocketInterface,
- Grammar: Grammar,
- // Expose the debug module.
- debug: require('debug'),
- // Expose the adapter module.
- adapter: adapter
- };
- Object.defineProperties(JsSIP, {
- name: {
- get: function() { return pkg.title; }
- },
- version: {
- get: function() { return pkg.version; }
- }
- });
- },{"../package.json":51,"./Constants":1,"./Exceptions":5,"./Grammar":6,"./NameAddrHeader":9,"./UA":24,"./URI":25,"./Utils":26,"./WebSocketInterface":27,"debug":35,"webrtc-adapter":42}],8:[function(require,module,exports){
- module.exports = Message;
- /**
- * Dependencies.
- */
- var util = require('util');
- var events = require('events');
- var JsSIP_C = require('./Constants');
- var SIPMessage = require('./SIPMessage');
- var Utils = require('./Utils');
- var RequestSender = require('./RequestSender');
- var Transactions = require('./Transactions');
- var Exceptions = require('./Exceptions');
- function Message(ua) {
- this.ua = ua;
- // Custom message empty object for high level use
- this.data = {};
- events.EventEmitter.call(this);
- }
- util.inherits(Message, events.EventEmitter);
- Message.prototype.send = function(target, body, options) {
- var request_sender, event, contentType, eventHandlers, extraHeaders,
- originalTarget = target;
- if (target === undefined || body === undefined) {
- throw new TypeError('Not enough arguments');
- }
- // Check target validity
- target = this.ua.normalizeTarget(target);
- if (!target) {
- throw new TypeError('Invalid target: '+ originalTarget);
- }
- // Get call options
- options = options || {};
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [];
- eventHandlers = options.eventHandlers || {};
- contentType = options.contentType || 'text/plain';
- this.content_type = contentType;
- // Set event handlers
- for (event in eventHandlers) {
- this.on(event, eventHandlers[event]);
- }
- this.closed = false;
- this.ua.applicants[this] = this;
- extraHeaders.push('Content-Type: '+ contentType);
- this.request = new SIPMessage.OutgoingRequest(JsSIP_C.MESSAGE, target, this.ua, null, extraHeaders);
- if(body) {
- this.request.body = body;
- this.content = body;
- } else {
- this.content = null;
- }
- request_sender = new RequestSender(this, this.ua);
- this.newMessage('local', this.request);
- request_sender.send();
- };
- Message.prototype.receiveResponse = function(response) {
- var cause;
- if(this.closed) {
- return;
- }
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- delete this.ua.applicants[this];
- this.emit('succeeded', {
- originator: 'remote',
- response: response
- });
- break;
- default:
- delete this.ua.applicants[this];
- cause = Utils.sipErrorCause(response.status_code);
- this.emit('failed', {
- originator: 'remote',
- response: response,
- cause: cause
- });
- break;
- }
- };
- Message.prototype.onRequestTimeout = function() {
- if(this.closed) {
- return;
- }
- this.emit('failed', {
- originator: 'system',
- cause: JsSIP_C.causes.REQUEST_TIMEOUT
- });
- };
- Message.prototype.onTransportError = function() {
- if(this.closed) {
- return;
- }
- this.emit('failed', {
- originator: 'system',
- cause: JsSIP_C.causes.CONNECTION_ERROR
- });
- };
- Message.prototype.close = function() {
- this.closed = true;
- delete this.ua.applicants[this];
- };
- Message.prototype.init_incoming = function(request) {
- var transaction;
- this.request = request;
- this.content_type = request.getHeader('Content-Type');
- if (request.body) {
- this.content = request.body;
- } else {
- this.content = null;
- }
- this.newMessage('remote', request);
- transaction = this.ua.transactions.nist[request.via_branch];
- if (transaction && (transaction.state === Transactions.C.STATUS_TRYING || transaction.state === Transactions.C.STATUS_PROCEEDING)) {
- request.reply(200);
- }
- };
- /**
- * Accept the incoming Message
- * Only valid for incoming Messages
- */
- Message.prototype.accept = function(options) {
- options = options || {};
- var
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body;
- if (this.direction !== 'incoming') {
- throw new Exceptions.NotSupportedError('"accept" not supported for outgoing Message');
- }
- this.request.reply(200, null, extraHeaders, body);
- };
- /**
- * Reject the incoming Message
- * Only valid for incoming Messages
- */
- Message.prototype.reject = function(options) {
- options = options || {};
- var
- status_code = options.status_code || 480,
- reason_phrase = options.reason_phrase,
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body;
- if (this.direction !== 'incoming') {
- throw new Exceptions.NotSupportedError('"reject" not supported for outgoing Message');
- }
- if (status_code < 300 || status_code >= 700) {
- throw new TypeError('Invalid status_code: '+ status_code);
- }
- this.request.reply(status_code, reason_phrase, extraHeaders, body);
- };
- /**
- * Internal Callbacks
- */
- Message.prototype.newMessage = function(originator, request) {
- if (originator === 'remote') {
- this.direction = 'incoming';
- this.local_identity = request.to;
- this.remote_identity = request.from;
- } else if (originator === 'local'){
- this.direction = 'outgoing';
- this.local_identity = request.from;
- this.remote_identity = request.to;
- }
- this.ua.newMessage({
- originator: originator,
- message: this,
- request: request
- });
- };
- },{"./Constants":1,"./Exceptions":5,"./RequestSender":18,"./SIPMessage":19,"./Transactions":22,"./Utils":26,"events":29,"util":33}],9:[function(require,module,exports){
- module.exports = NameAddrHeader;
- /**
- * Dependencies.
- */
- var URI = require('./URI');
- var Grammar = require('./Grammar');
- function NameAddrHeader(uri, display_name, parameters) {
- var param;
- // Checks
- if(!uri || !(uri instanceof URI)) {
- throw new TypeError('missing or invalid "uri" parameter');
- }
- // Initialize parameters
- this.uri = uri;
- this.parameters = {};
- for (param in parameters) {
- this.setParam(param, parameters[param]);
- }
- Object.defineProperties(this, {
- display_name: {
- get: function() { return display_name; },
- set: function(value) {
- display_name = (value === 0) ? '0' : value;
- }
- }
- });
- }
- NameAddrHeader.prototype = {
- setParam: function(key, value) {
- if (key) {
- this.parameters[key.toLowerCase()] = (typeof value === 'undefined' || value === null) ? null : value.toString();
- }
- },
- getParam: function(key) {
- if(key) {
- return this.parameters[key.toLowerCase()];
- }
- },
- hasParam: function(key) {
- if(key) {
- return (this.parameters.hasOwnProperty(key.toLowerCase()) && true) || false;
- }
- },
- deleteParam: function(parameter) {
- var value;
- parameter = parameter.toLowerCase();
- if (this.parameters.hasOwnProperty(parameter)) {
- value = this.parameters[parameter];
- delete this.parameters[parameter];
- return value;
- }
- },
- clearParams: function() {
- this.parameters = {};
- },
- clone: function() {
- return new NameAddrHeader(
- this.uri.clone(),
- this.display_name,
- JSON.parse(JSON.stringify(this.parameters)));
- },
- toString: function() {
- var body, parameter;
- body = (this.display_name || this.display_name === 0) ? '"' + this.display_name + '" ' : '';
- body += '<' + this.uri.toString() + '>';
- for (parameter in this.parameters) {
- body += ';' + parameter;
- if (this.parameters[parameter] !== null) {
- body += '='+ this.parameters[parameter];
- }
- }
- return body;
- }
- };
- /**
- * Parse the given string and returns a NameAddrHeader instance or undefined if
- * it is an invalid NameAddrHeader.
- */
- NameAddrHeader.parse = function(name_addr_header) {
- name_addr_header = Grammar.parse(name_addr_header,'Name_Addr_Header');
- if (name_addr_header !== -1) {
- return name_addr_header;
- } else {
- return undefined;
- }
- };
- },{"./Grammar":6,"./URI":25}],10:[function(require,module,exports){
- var Parser = {};
- module.exports = Parser;
- /**
- * Dependencies.
- */
- var debugerror = require('debug')('JsSIP:ERROR:Parser');
- debugerror.log = console.warn.bind(console);
- var Grammar = require('./Grammar');
- var SIPMessage = require('./SIPMessage');
- /**
- * Extract and parse every header of a SIP message.
- */
- function getHeader(data, headerStart) {
- var
- // 'start' position of the header.
- start = headerStart,
- // 'end' position of the header.
- end = 0,
- // 'partial end' position of the header.
- partialEnd = 0;
- //End of message.
- if (data.substring(start, start + 2).match(/(^\r\n)/)) {
- return -2;
- }
- while(end === 0) {
- // Partial End of Header.
- partialEnd = data.indexOf('\r\n', start);
- // 'indexOf' returns -1 if the value to be found never occurs.
- if (partialEnd === -1) {
- return partialEnd;
- }
- if(!data.substring(partialEnd + 2, partialEnd + 4).match(/(^\r\n)/) && data.charAt(partialEnd + 2).match(/(^\s+)/)) {
- // Not the end of the message. Continue from the next position.
- start = partialEnd + 2;
- } else {
- end = partialEnd;
- }
- }
- return end;
- }
- function parseHeader(message, data, headerStart, headerEnd) {
- var header, idx, length, parsed,
- hcolonIndex = data.indexOf(':', headerStart),
- headerName = data.substring(headerStart, hcolonIndex).trim(),
- headerValue = data.substring(hcolonIndex + 1, headerEnd).trim();
- // If header-field is well-known, parse it.
- switch(headerName.toLowerCase()) {
- case 'via':
- case 'v':
- message.addHeader('via', headerValue);
- if(message.getHeaders('via').length === 1) {
- parsed = message.parseHeader('Via');
- if(parsed) {
- message.via = parsed;
- message.via_branch = parsed.branch;
- }
- } else {
- parsed = 0;
- }
- break;
- case 'from':
- case 'f':
- message.setHeader('from', headerValue);
- parsed = message.parseHeader('from');
- if(parsed) {
- message.from = parsed;
- message.from_tag = parsed.getParam('tag');
- }
- break;
- case 'to':
- case 't':
- message.setHeader('to', headerValue);
- parsed = message.parseHeader('to');
- if(parsed) {
- message.to = parsed;
- message.to_tag = parsed.getParam('tag');
- }
- break;
- case 'record-route':
- parsed = Grammar.parse(headerValue, 'Record_Route');
- if (parsed === -1) {
- parsed = undefined;
- } else {
- length = parsed.length;
- for (idx = 0; idx < length; idx++) {
- header = parsed[idx];
- message.addHeader('record-route', headerValue.substring(header.possition, header.offset));
- message.headers['Record-Route'][message.getHeaders('record-route').length - 1].parsed = header.parsed;
- }
- }
- break;
- case 'call-id':
- case 'i':
- message.setHeader('call-id', headerValue);
- parsed = message.parseHeader('call-id');
- if(parsed) {
- message.call_id = headerValue;
- }
- break;
- case 'contact':
- case 'm':
- parsed = Grammar.parse(headerValue, 'Contact');
- if (parsed === -1) {
- parsed = undefined;
- } else {
- length = parsed.length;
- for (idx = 0; idx < length; idx++) {
- header = parsed[idx];
- message.addHeader('contact', headerValue.substring(header.possition, header.offset));
- message.headers.Contact[message.getHeaders('contact').length - 1].parsed = header.parsed;
- }
- }
- break;
- case 'content-length':
- case 'l':
- message.setHeader('content-length', headerValue);
- parsed = message.parseHeader('content-length');
- break;
- case 'content-type':
- case 'c':
- message.setHeader('content-type', headerValue);
- parsed = message.parseHeader('content-type');
- break;
- case 'cseq':
- message.setHeader('cseq', headerValue);
- parsed = message.parseHeader('cseq');
- if(parsed) {
- message.cseq = parsed.value;
- }
- if(message instanceof SIPMessage.IncomingResponse) {
- message.method = parsed.method;
- }
- break;
- case 'max-forwards':
- message.setHeader('max-forwards', headerValue);
- parsed = message.parseHeader('max-forwards');
- break;
- case 'www-authenticate':
- message.setHeader('www-authenticate', headerValue);
- parsed = message.parseHeader('www-authenticate');
- break;
- case 'proxy-authenticate':
- message.setHeader('proxy-authenticate', headerValue);
- parsed = message.parseHeader('proxy-authenticate');
- break;
- case 'session-expires':
- case 'x':
- message.setHeader('session-expires', headerValue);
- parsed = message.parseHeader('session-expires');
- if (parsed) {
- message.session_expires = parsed.expires;
- message.session_expires_refresher = parsed.refresher;
- }
- break;
- case 'refer-to':
- case 'r':
- message.setHeader('refer-to', headerValue);
- parsed = message.parseHeader('refer-to');
- if(parsed) {
- message.refer_to = parsed;
- }
- break;
- case 'replaces':
- message.setHeader('replaces', headerValue);
- parsed = message.parseHeader('replaces');
- if(parsed) {
- message.replaces = parsed;
- }
- break;
- case 'event':
- case 'o':
- message.setHeader('event', headerValue);
- parsed = message.parseHeader('event');
- if(parsed) {
- message.event = parsed;
- }
- break;
- default:
- // Do not parse this header.
- message.setHeader(headerName, headerValue);
- parsed = 0;
- }
- if (parsed === undefined) {
- return {
- error: 'error parsing header "'+ headerName +'"'
- };
- } else {
- return true;
- }
- }
- /**
- * Parse SIP Message
- */
- Parser.parseMessage = function(data, ua) {
- var message, firstLine, contentLength, bodyStart, parsed,
- headerStart = 0,
- headerEnd = data.indexOf('\r\n');
- if(headerEnd === -1) {
- debugerror('parseMessage() | no CRLF found, not a SIP message');
- return;
- }
- // Parse first line. Check if it is a Request or a Reply.
- firstLine = data.substring(0, headerEnd);
- parsed = Grammar.parse(firstLine, 'Request_Response');
- if(parsed === -1) {
- debugerror('parseMessage() | error parsing first line of SIP message: "' + firstLine + '"');
- return;
- } else if(!parsed.status_code) {
- message = new SIPMessage.IncomingRequest(ua);
- message.method = parsed.method;
- message.ruri = parsed.uri;
- } else {
- message = new SIPMessage.IncomingResponse();
- message.status_code = parsed.status_code;
- message.reason_phrase = parsed.reason_phrase;
- }
- message.data = data;
- headerStart = headerEnd + 2;
- /* Loop over every line in data. Detect the end of each header and parse
- * it or simply add to the headers collection.
- */
- while(true) {
- headerEnd = getHeader(data, headerStart);
- // The SIP message has normally finished.
- if(headerEnd === -2) {
- bodyStart = headerStart + 2;
- break;
- }
- // data.indexOf returned -1 due to a malformed message.
- else if(headerEnd === -1) {
- debugerror('parseMessage() | malformed message');
- return;
- }
- parsed = parseHeader(message, data, headerStart, headerEnd);
- if(parsed !== true) {
- debugerror('parseMessage() |', parsed.error);
- return;
- }
- headerStart = headerEnd + 2;
- }
- /* RFC3261 18.3.
- * If there are additional bytes in the transport packet
- * beyond the end of the body, they MUST be discarded.
- */
- if(message.hasHeader('content-length')) {
- contentLength = message.getHeader('content-length');
- message.body = data.substr(bodyStart, contentLength);
- } else {
- message.body = data.substring(bodyStart);
- }
- return message;
- };
- },{"./Grammar":6,"./SIPMessage":19,"debug":35}],11:[function(require,module,exports){
- /* globals RTCPeerConnection: false, RTCSessionDescription: false */
- module.exports = RTCSession;
- var C = {
- // RTCSession states
- STATUS_NULL: 0,
- STATUS_INVITE_SENT: 1,
- STATUS_1XX_RECEIVED: 2,
- STATUS_INVITE_RECEIVED: 3,
- STATUS_WAITING_FOR_ANSWER: 4,
- STATUS_ANSWERED: 5,
- STATUS_WAITING_FOR_ACK: 6,
- STATUS_CANCELED: 7,
- STATUS_TERMINATED: 8,
- STATUS_CONFIRMED: 9
- };
- /**
- * Expose C object.
- */
- RTCSession.C = C;
- /**
- * Dependencies.
- */
- var util = require('util');
- var events = require('events');
- var debug = require('debug')('JsSIP:RTCSession');
- var debugerror = require('debug')('JsSIP:ERROR:RTCSession');
- debugerror.log = console.warn.bind(console);
- var sdp_transform = require('sdp-transform');
- var JsSIP_C = require('./Constants');
- var Exceptions = require('./Exceptions');
- var Transactions = require('./Transactions');
- var Utils = require('./Utils');
- var Timers = require('./Timers');
- var SIPMessage = require('./SIPMessage');
- var Dialog = require('./Dialog');
- var RequestSender = require('./RequestSender');
- var RTCSession_Request = require('./RTCSession/Request');
- var RTCSession_DTMF = require('./RTCSession/DTMF');
- var RTCSession_Info = require('./RTCSession/Info');
- var RTCSession_ReferNotifier = require('./RTCSession/ReferNotifier');
- var RTCSession_ReferSubscriber = require('./RTCSession/ReferSubscriber');
- /**
- * Local variables.
- */
- var holdMediaTypes = ['audio', 'video'];
- function RTCSession(ua) {
- debug('new');
- this.ua = ua;
- this.status = C.STATUS_NULL;
- this.dialog = null;
- this.earlyDialogs = {};
- this.connection = null; // The RTCPeerConnection instance (public attribute).
- // RTCSession confirmation flag
- this.is_confirmed = false;
- // is late SDP being negotiated
- this.late_sdp = false;
- // Default rtcOfferConstraints and rtcAnswerConstrainsts (passed in connect() or answer()).
- this.rtcOfferConstraints = null;
- this.rtcAnswerConstraints = null;
- // Local MediaStream.
- this.localMediaStream = null;
- this.localMediaStreamLocallyGenerated = false;
- // Flag to indicate PeerConnection ready for new actions.
- this.rtcReady = true;
- // SIP Timers
- this.timers = {
- ackTimer: null,
- expiresTimer: null,
- invite2xxTimer: null,
- userNoAnswerTimer: null
- };
- // Session info
- this.direction = null;
- this.local_identity = null;
- this.remote_identity = null;
- this.start_time = null;
- this.end_time = null;
- this.tones = null;
- // Mute/Hold state
- this.audioMuted = false;
- this.videoMuted = false;
- this.localHold = false;
- this.remoteHold = false;
- // Session Timers (RFC 4028)
- this.sessionTimers = {
- enabled: this.ua.configuration.session_timers,
- defaultExpires: JsSIP_C.SESSION_EXPIRES,
- currentExpires: null,
- running: false,
- refresher: false,
- timer: null // A setTimeout.
- };
- // Map of ReferSubscriber instances indexed by the REFER's CSeq number
- this.referSubscribers = {};
- // Custom session empty object for high level use
- this.data = {};
- // Expose session failed/ended causes as a property of the RTCSession instance
- this.causes = JsSIP_C.causes;
- events.EventEmitter.call(this);
- }
- util.inherits(RTCSession, events.EventEmitter);
- /**
- * User API
- */
- RTCSession.prototype.isInProgress = function() {
- switch(this.status) {
- case C.STATUS_NULL:
- case C.STATUS_INVITE_SENT:
- case C.STATUS_1XX_RECEIVED:
- case C.STATUS_INVITE_RECEIVED:
- case C.STATUS_WAITING_FOR_ANSWER:
- return true;
- default:
- return false;
- }
- };
- RTCSession.prototype.isEstablished = function() {
- switch(this.status) {
- case C.STATUS_ANSWERED:
- case C.STATUS_WAITING_FOR_ACK:
- case C.STATUS_CONFIRMED:
- return true;
- default:
- return false;
- }
- };
- RTCSession.prototype.isEnded = function() {
- switch(this.status) {
- case C.STATUS_CANCELED:
- case C.STATUS_TERMINATED:
- return true;
- default:
- return false;
- }
- };
- RTCSession.prototype.isMuted = function() {
- return {
- audio: this.audioMuted,
- video: this.videoMuted
- };
- };
- RTCSession.prototype.isOnHold = function() {
- return {
- local: this.localHold,
- remote: this.remoteHold
- };
- };
- /**
- * Check if RTCSession is ready for an outgoing re-INVITE or UPDATE with SDP.
- */
- RTCSession.prototype.isReadyToReOffer = function() {
- if (! this.rtcReady) {
- debug('isReadyToReOffer() | internal WebRTC status not ready');
- return false;
- }
- // No established yet.
- if (! this.dialog) {
- debug('isReadyToReOffer() | session not established yet');
- return false;
- }
- // Another INVITE transaction is in progress
- if (this.dialog.uac_pending_reply === true || this.dialog.uas_pending_reply === true) {
- debug('isReadyToReOffer() | there is another INVITE/UPDATE transaction in progress');
- return false;
- }
- return true;
- };
- RTCSession.prototype.connect = function(target, options, initCallback) {
- debug('connect()');
- options = options || {};
- var event, requestParams,
- originalTarget = target,
- eventHandlers = options.eventHandlers || {},
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- mediaConstraints = options.mediaConstraints || {audio: true, video: true},
- mediaStream = options.mediaStream || null,
- pcConfig = options.pcConfig || {iceServers:[]},
- rtcConstraints = options.rtcConstraints || null,
- rtcOfferConstraints = options.rtcOfferConstraints || null;
- this.rtcOfferConstraints = rtcOfferConstraints;
- this.rtcAnswerConstraints = options.rtcAnswerConstraints || null;
- // Session Timers.
- if (this.sessionTimers.enabled) {
- if (Utils.isDecimal(options.sessionTimersExpires)) {
- if (options.sessionTimersExpires >= JsSIP_C.MIN_SESSION_EXPIRES) {
- this.sessionTimers.defaultExpires = options.sessionTimersExpires;
- }
- else {
- this.sessionTimers.defaultExpires = JsSIP_C.SESSION_EXPIRES;
- }
- }
- }
- this.data = options.data || this.data;
- if (target === undefined) {
- throw new TypeError('Not enough arguments');
- }
- // Check WebRTC support.
- if (!window.RTCPeerConnection) {
- throw new Exceptions.NotSupportedError('WebRTC not supported');
- }
- // Check target validity
- target = this.ua.normalizeTarget(target);
- if (!target) {
- throw new TypeError('Invalid target: '+ originalTarget);
- }
- // Check Session Status
- if (this.status !== C.STATUS_NULL) {
- throw new Exceptions.InvalidStateError(this.status);
- }
- // Set event handlers
- for (event in eventHandlers) {
- this.on(event, eventHandlers[event]);
- }
- // Session parameter initialization
- this.from_tag = Utils.newTag();
- // Set anonymous property
- this.anonymous = options.anonymous || false;
- // OutgoingSession specific parameters
- this.isCanceled = false;
- requestParams = {from_tag: this.from_tag};
- this.contact = this.ua.contact.toString({
- anonymous: this.anonymous,
- outbound: true
- });
- if (this.anonymous) {
- requestParams.from_display_name = 'Anonymous';
- requestParams.from_uri = 'sip:anonymous@anonymous.invalid';
- extraHeaders.push('P-Preferred-Identity: '+ this.ua.configuration.uri.toString());
- extraHeaders.push('Privacy: id');
- }
- extraHeaders.push('Contact: '+ this.contact);
- extraHeaders.push('Content-Type: application/sdp');
- if (this.sessionTimers.enabled) {
- extraHeaders.push('Session-Expires: ' + this.sessionTimers.defaultExpires);
- }
- this.request = new SIPMessage.OutgoingRequest(JsSIP_C.INVITE, target, this.ua, requestParams, extraHeaders);
- this.id = this.request.call_id + this.from_tag;
- // Create a new RTCPeerConnection instance.
- createRTCConnection.call(this, pcConfig, rtcConstraints);
- // Save the session into the ua sessions collection.
- this.ua.sessions[this.id] = this;
- // Set internal properties
- this.direction = 'outgoing';
- this.local_identity = this.request.from;
- this.remote_identity = this.request.to;
- // User explicitly provided a newRTCSession callback for this session
- if (initCallback) {
- initCallback(this);
- } else {
- newRTCSession.call(this, 'local', this.request);
- }
- sendInitialRequest.call(this, mediaConstraints, rtcOfferConstraints, mediaStream);
- };
- RTCSession.prototype.init_incoming = function(request, initCallback) {
- debug('init_incoming()');
- var expires,
- self = this,
- contentType = request.getHeader('Content-Type');
- // Check body and content type
- if (request.body && (contentType !== 'application/sdp')) {
- request.reply(415);
- return;
- }
- // Session parameter initialization
- this.status = C.STATUS_INVITE_RECEIVED;
- this.from_tag = request.from_tag;
- this.id = request.call_id + this.from_tag;
- this.request = request;
- this.contact = this.ua.contact.toString();
- // Save the session into the ua sessions collection.
- this.ua.sessions[this.id] = this;
- // Get the Expires header value if exists
- if (request.hasHeader('expires')) {
- expires = request.getHeader('expires') * 1000;
- }
- /* Set the to_tag before
- * replying a response code that will create a dialog.
- */
- request.to_tag = Utils.newTag();
- // An error on dialog creation will fire 'failed' event
- if (! createDialog.call(this, request, 'UAS', true)) {
- request.reply(500, 'Missing Contact header field');
- return;
- }
- if (request.body) {
- this.late_sdp = false;
- }
- else {
- this.late_sdp = true;
- }
- this.status = C.STATUS_WAITING_FOR_ANSWER;
- // Set userNoAnswerTimer
- this.timers.userNoAnswerTimer = setTimeout(function() {
- request.reply(408);
- failed.call(self, 'local',null, JsSIP_C.causes.NO_ANSWER);
- }, this.ua.configuration.no_answer_timeout
- );
- /* Set expiresTimer
- * RFC3261 13.3.1
- */
- if (expires) {
- this.timers.expiresTimer = setTimeout(function() {
- if(self.status === C.STATUS_WAITING_FOR_ANSWER) {
- request.reply(487);
- failed.call(self, 'system', null, JsSIP_C.causes.EXPIRES);
- }
- }, expires
- );
- }
- // Set internal properties
- this.direction = 'incoming';
- this.local_identity = request.to;
- this.remote_identity = request.from;
- // A init callback was specifically defined
- if (initCallback) {
- initCallback(this);
- // Fire 'newRTCSession' event.
- } else {
- newRTCSession.call(this, 'remote', request);
- }
- // The user may have rejected the call in the 'newRTCSession' event.
- if (this.status === C.STATUS_TERMINATED) {
- return;
- }
- // Reply 180.
- request.reply(180, null, ['Contact: ' + self.contact]);
- // Fire 'progress' event.
- // TODO: Document that 'response' field in 'progress' event is null for
- // incoming calls.
- progress.call(self, 'local', null);
- };
- /**
- * Answer the call.
- */
- RTCSession.prototype.answer = function(options) {
- debug('answer()');
- options = options || {};
- var idx, length, sdp, tracks,
- peerHasAudioLine = false,
- peerHasVideoLine = false,
- peerOffersFullAudio = false,
- peerOffersFullVideo = false,
- self = this,
- request = this.request,
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- mediaConstraints = options.mediaConstraints || {},
- mediaStream = options.mediaStream || null,
- pcConfig = options.pcConfig || {iceServers:[]},
- rtcConstraints = options.rtcConstraints || null,
- rtcAnswerConstraints = options.rtcAnswerConstraints || null;
- this.rtcAnswerConstraints = rtcAnswerConstraints;
- this.rtcOfferConstraints = options.rtcOfferConstraints || null;
- // Session Timers.
- if (this.sessionTimers.enabled) {
- if (Utils.isDecimal(options.sessionTimersExpires)) {
- if (options.sessionTimersExpires >= JsSIP_C.MIN_SESSION_EXPIRES) {
- this.sessionTimers.defaultExpires = options.sessionTimersExpires;
- }
- else {
- this.sessionTimers.defaultExpires = JsSIP_C.SESSION_EXPIRES;
- }
- }
- }
- this.data = options.data || this.data;
- // Check Session Direction and Status
- if (this.direction !== 'incoming') {
- throw new Exceptions.NotSupportedError('"answer" not supported for outgoing RTCSession');
- } else if (this.status !== C.STATUS_WAITING_FOR_ANSWER) {
- throw new Exceptions.InvalidStateError(this.status);
- }
- this.status = C.STATUS_ANSWERED;
- // An error on dialog creation will fire 'failed' event
- if (! createDialog.call(this, request, 'UAS')) {
- request.reply(500, 'Error creating dialog');
- return;
- }
- clearTimeout(this.timers.userNoAnswerTimer);
- extraHeaders.unshift('Contact: ' + self.contact);
- // Determine incoming media from incoming SDP offer (if any).
- sdp = request.parseSDP();
- // Make sure sdp.media is an array, not the case if there is only one media
- if (! Array.isArray(sdp.media)) {
- sdp.media = [sdp.media];
- }
- // Go through all medias in SDP to find offered capabilities to answer with
- idx = sdp.media.length;
- while(idx--) {
- var m = sdp.media[idx];
- if (m.type === 'audio') {
- peerHasAudioLine = true;
- if (!m.direction || m.direction === 'sendrecv') {
- peerOffersFullAudio = true;
- }
- }
- if (m.type === 'video') {
- peerHasVideoLine = true;
- if (!m.direction || m.direction === 'sendrecv') {
- peerOffersFullVideo = true;
- }
- }
- }
- // Remove audio from mediaStream if suggested by mediaConstraints
- if (mediaStream && mediaConstraints.audio === false) {
- tracks = mediaStream.getAudioTracks();
- length = tracks.length;
- for (idx=0; idx<length; idx++) {
- mediaStream.removeTrack(tracks[idx]);
- }
- }
- // Remove video from mediaStream if suggested by mediaConstraints
- if (mediaStream && mediaConstraints.video === false) {
- tracks = mediaStream.getVideoTracks();
- length = tracks.length;
- for (idx=0; idx<length; idx++) {
- mediaStream.removeTrack(tracks[idx]);
- }
- }
- // Set audio constraints based on incoming stream if not supplied
- if (!mediaStream && mediaConstraints.audio === undefined) {
- mediaConstraints.audio = peerOffersFullAudio;
- }
- // Set video constraints based on incoming stream if not supplied
- if (!mediaStream && mediaConstraints.video === undefined) {
- mediaConstraints.video = peerOffersFullVideo;
- }
- // Don't ask for audio if the incoming offer has no audio section
- if (!mediaStream && !peerHasAudioLine) {
- mediaConstraints.audio = false;
- }
- // Don't ask for video if the incoming offer has no video section
- if (!mediaStream && !peerHasVideoLine) {
- mediaConstraints.video = false;
- }
- // Create a new RTCPeerConnection instance.
- // TODO: This may throw an error, should react.
- createRTCConnection.call(this, pcConfig, rtcConstraints);
- // If a local MediaStream is given use it.
- if (mediaStream) {
- userMediaSucceeded(mediaStream);
- // If at least audio or video is requested prompt getUserMedia.
- } else if (mediaConstraints.audio || mediaConstraints.video) {
- self.localMediaStreamLocallyGenerated = true;
- navigator.mediaDevices.getUserMedia(mediaConstraints)
- .then(userMediaSucceeded)
- .catch(function(error) {
- userMediaFailed(error);
- debugerror('emit "getusermediafailed" [error:%o]', error);
- self.emit('getusermediafailed', error);
- });
- // Otherwise don't prompt getUserMedia.
- } else {
- userMediaSucceeded(null);
- }
- // User media succeeded
- function userMediaSucceeded(stream) {
- if (self.status === C.STATUS_TERMINATED) { return; }
- self.localMediaStream = stream;
- if (stream) {
- self.connection.addStream(stream);
- }
- debug('emit "peerconnection"');
- self.emit('peerconnection', {
- peerconnection: self.connection
- });
- if (! self.late_sdp) {
- var e = {originator:'remote', type:'offer', sdp:request.body};
- debug('emit "sdp"');
- self.emit('sdp', e);
- var offer = new RTCSessionDescription({type:'offer', sdp:e.sdp});
- self.connection.setRemoteDescription(offer)
- .then(remoteDescriptionSucceededOrNotNeeded)
- .catch(function(error) {
- request.reply(488);
- failed.call(self, 'system', null, JsSIP_C.causes.WEBRTC_ERROR);
- debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- }
- else {
- remoteDescriptionSucceededOrNotNeeded();
- }
- }
- // User media failed
- function userMediaFailed() {
- if (self.status === C.STATUS_TERMINATED) { return; }
- request.reply(480);
- failed.call(self, 'local', null, JsSIP_C.causes.USER_DENIED_MEDIA_ACCESS);
- }
- function remoteDescriptionSucceededOrNotNeeded() {
- connecting.call(self, request);
- if (! self.late_sdp) {
- createLocalDescription.call(self, 'answer', rtcSucceeded, rtcFailed, rtcAnswerConstraints);
- } else {
- createLocalDescription.call(self, 'offer', rtcSucceeded, rtcFailed, self.rtcOfferConstraints);
- }
- }
- function rtcSucceeded(desc) {
- if (self.status === C.STATUS_TERMINATED) { return; }
- // run for reply success callback
- function replySucceeded() {
- self.status = C.STATUS_WAITING_FOR_ACK;
- setInvite2xxTimer.call(self, request, desc);
- setACKTimer.call(self);
- accepted.call(self, 'local');
- }
- // run for reply failure callback
- function replyFailed() {
- failed.call(self, 'system', null, JsSIP_C.causes.CONNECTION_ERROR);
- }
- handleSessionTimersInIncomingRequest.call(self, request, extraHeaders);
- request.reply(200, null, extraHeaders,
- desc,
- replySucceeded,
- replyFailed
- );
- }
- function rtcFailed() {
- if (self.status === C.STATUS_TERMINATED) { return; }
- request.reply(500);
- failed.call(self, 'system', null, JsSIP_C.causes.WEBRTC_ERROR);
- }
- };
- /**
- * Terminate the call.
- */
- RTCSession.prototype.terminate = function(options) {
- debug('terminate()');
- options = options || {};
- var cancel_reason, dialog,
- cause = options.cause || JsSIP_C.causes.BYE,
- status_code = options.status_code,
- reason_phrase = options.reason_phrase,
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body,
- self = this;
- // Check Session Status
- if (this.status === C.STATUS_TERMINATED) {
- throw new Exceptions.InvalidStateError(this.status);
- }
- switch(this.status) {
- // - UAC -
- case C.STATUS_NULL:
- case C.STATUS_INVITE_SENT:
- case C.STATUS_1XX_RECEIVED:
- debug('canceling session');
- if (status_code && (status_code < 200 || status_code >= 700)) {
- throw new TypeError('Invalid status_code: '+ status_code);
- } else if (status_code) {
- reason_phrase = reason_phrase || JsSIP_C.REASON_PHRASE[status_code] || '';
- cancel_reason = 'SIP ;cause=' + status_code + ' ;text="' + reason_phrase + '"';
- }
- // Check Session Status
- if (this.status === C.STATUS_NULL) {
- this.isCanceled = true;
- this.cancelReason = cancel_reason;
- } else if (this.status === C.STATUS_INVITE_SENT) {
- this.isCanceled = true;
- this.cancelReason = cancel_reason;
- } else if(this.status === C.STATUS_1XX_RECEIVED) {
- this.request.cancel(cancel_reason);
- }
- this.status = C.STATUS_CANCELED;
- failed.call(this, 'local', null, JsSIP_C.causes.CANCELED);
- break;
- // - UAS -
- case C.STATUS_WAITING_FOR_ANSWER:
- case C.STATUS_ANSWERED:
- debug('rejecting session');
- status_code = status_code || 480;
- if (status_code < 300 || status_code >= 700) {
- throw new TypeError('Invalid status_code: '+ status_code);
- }
- this.request.reply(status_code, reason_phrase, extraHeaders, body);
- failed.call(this, 'local', null, JsSIP_C.causes.REJECTED);
- break;
- case C.STATUS_WAITING_FOR_ACK:
- case C.STATUS_CONFIRMED:
- debug('terminating session');
- reason_phrase = options.reason_phrase || JsSIP_C.REASON_PHRASE[status_code] || '';
- if (status_code && (status_code < 200 || status_code >= 700)) {
- throw new TypeError('Invalid status_code: '+ status_code);
- } else if (status_code) {
- extraHeaders.push('Reason: SIP ;cause=' + status_code + '; text="' + reason_phrase + '"');
- }
- /* RFC 3261 section 15 (Terminating a session):
- *
- * "...the callee's UA MUST NOT send a BYE on a confirmed dialog
- * until it has received an ACK for its 2xx response or until the server
- * transaction times out."
- */
- if (this.status === C.STATUS_WAITING_FOR_ACK &&
- this.direction === 'incoming' &&
- this.request.server_transaction.state !== Transactions.C.STATUS_TERMINATED) {
- // Save the dialog for later restoration
- dialog = this.dialog;
- // Send the BYE as soon as the ACK is received...
- this.receiveRequest = function(request) {
- if(request.method === JsSIP_C.ACK) {
- sendRequest.call(this, JsSIP_C.BYE, {
- extraHeaders: extraHeaders,
- body: body
- });
- dialog.terminate();
- }
- };
- // .., or when the INVITE transaction times out
- this.request.server_transaction.on('stateChanged', function(){
- if (this.state === Transactions.C.STATUS_TERMINATED) {
- sendRequest.call(self, JsSIP_C.BYE, {
- extraHeaders: extraHeaders,
- body: body
- });
- dialog.terminate();
- }
- });
- ended.call(this, 'local', null, cause);
- // Restore the dialog into 'this' in order to be able to send the in-dialog BYE :-)
- this.dialog = dialog;
- // Restore the dialog into 'ua' so the ACK can reach 'this' session
- this.ua.dialogs[dialog.id.toString()] = dialog;
- } else {
- sendRequest.call(this, JsSIP_C.BYE, {
- extraHeaders: extraHeaders,
- body: body
- });
- ended.call(this, 'local', null, cause);
- }
- }
- };
- RTCSession.prototype.close = function() {
- debug('close()');
- var idx;
- if (this.status === C.STATUS_TERMINATED) {
- return;
- }
- // Terminate RTC.
- if (this.connection) {
- try {
- this.connection.close();
- } catch(error) {
- debugerror('close() | error closing the RTCPeerConnection: %o', error);
- }
- }
- // Close local MediaStream if it was not given by the user.
- if (this.localMediaStream && this.localMediaStreamLocallyGenerated) {
- debug('close() | closing local MediaStream');
- Utils.closeMediaStream(this.localMediaStream);
- }
- // Terminate signaling.
- // Clear SIP timers
- for(idx in this.timers) {
- clearTimeout(this.timers[idx]);
- }
- // Clear Session Timers.
- clearTimeout(this.sessionTimers.timer);
- // Terminate confirmed dialog
- if (this.dialog) {
- this.dialog.terminate();
- delete this.dialog;
- }
- // Terminate early dialogs
- for(idx in this.earlyDialogs) {
- this.earlyDialogs[idx].terminate();
- delete this.earlyDialogs[idx];
- }
- this.status = C.STATUS_TERMINATED;
- delete this.ua.sessions[this.id];
- };
- RTCSession.prototype.sendDTMF = function(tones, options) {
- debug('sendDTMF() | tones: %s', tones);
- var duration, interToneGap,
- position = 0,
- self = this;
- options = options || {};
- duration = options.duration || null;
- interToneGap = options.interToneGap || null;
- if (tones === undefined) {
- throw new TypeError('Not enough arguments');
- }
- // Check Session Status
- if (this.status !== C.STATUS_CONFIRMED && this.status !== C.STATUS_WAITING_FOR_ACK) {
- throw new Exceptions.InvalidStateError(this.status);
- }
- // Convert to string
- if(typeof tones === 'number') {
- tones = tones.toString();
- }
- // Check tones
- if (!tones || typeof tones !== 'string' || !tones.match(/^[0-9A-DR#*,]+$/i)) {
- throw new TypeError('Invalid tones: '+ tones);
- }
- // Check duration
- if (duration && !Utils.isDecimal(duration)) {
- throw new TypeError('Invalid tone duration: '+ duration);
- } else if (!duration) {
- duration = RTCSession_DTMF.C.DEFAULT_DURATION;
- } else if (duration < RTCSession_DTMF.C.MIN_DURATION) {
- debug('"duration" value is lower than the minimum allowed, setting it to '+ RTCSession_DTMF.C.MIN_DURATION+ ' milliseconds');
- duration = RTCSession_DTMF.C.MIN_DURATION;
- } else if (duration > RTCSession_DTMF.C.MAX_DURATION) {
- debug('"duration" value is greater than the maximum allowed, setting it to '+ RTCSession_DTMF.C.MAX_DURATION +' milliseconds');
- duration = RTCSession_DTMF.C.MAX_DURATION;
- } else {
- duration = Math.abs(duration);
- }
- options.duration = duration;
- // Check interToneGap
- if (interToneGap && !Utils.isDecimal(interToneGap)) {
- throw new TypeError('Invalid interToneGap: '+ interToneGap);
- } else if (!interToneGap) {
- interToneGap = RTCSession_DTMF.C.DEFAULT_INTER_TONE_GAP;
- } else if (interToneGap < RTCSession_DTMF.C.MIN_INTER_TONE_GAP) {
- debug('"interToneGap" value is lower than the minimum allowed, setting it to '+ RTCSession_DTMF.C.MIN_INTER_TONE_GAP +' milliseconds');
- interToneGap = RTCSession_DTMF.C.MIN_INTER_TONE_GAP;
- } else {
- interToneGap = Math.abs(interToneGap);
- }
- if (this.tones) {
- // Tones are already queued, just add to the queue
- this.tones += tones;
- return;
- }
- this.tones = tones;
- // Send the first tone
- _sendDTMF();
- function _sendDTMF() {
- var tone, timeout;
- if (self.status === C.STATUS_TERMINATED || !self.tones || position >= self.tones.length) {
- // Stop sending DTMF
- self.tones = null;
- return;
- }
- tone = self.tones[position];
- position += 1;
- if (tone === ',') {
- timeout = 2000;
- } else {
- var dtmf = new RTCSession_DTMF(self);
- options.eventHandlers = {
- onFailed: function() { self.tones = null; }
- };
- dtmf.send(tone, options);
- timeout = duration + interToneGap;
- }
- // Set timeout for the next tone
- setTimeout(_sendDTMF, timeout);
- }
- };
- RTCSession.prototype.sendInfo = function(contentType, body, options) {
- debug('sendInfo()');
- options = options || {};
- // Check Session Status
- if (this.status !== C.STATUS_CONFIRMED && this.status !== C.STATUS_WAITING_FOR_ACK) {
- throw new Exceptions.InvalidStateError(this.status);
- }
- var info = new RTCSession_Info(this);
- info.send(contentType, body, options);
- };
- /**
- * Mute
- */
- RTCSession.prototype.mute = function(options) {
- debug('mute()');
- options = options || {audio:true, video:false};
- var
- audioMuted = false,
- videoMuted = false;
- if (this.audioMuted === false && options.audio) {
- audioMuted = true;
- this.audioMuted = true;
- toogleMuteAudio.call(this, true);
- }
- if (this.videoMuted === false && options.video) {
- videoMuted = true;
- this.videoMuted = true;
- toogleMuteVideo.call(this, true);
- }
- if (audioMuted === true || videoMuted === true) {
- onmute.call(this, {
- audio: audioMuted,
- video: videoMuted
- });
- }
- };
- /**
- * Unmute
- */
- RTCSession.prototype.unmute = function(options) {
- debug('unmute()');
- options = options || {audio:true, video:true};
- var
- audioUnMuted = false,
- videoUnMuted = false;
- if (this.audioMuted === true && options.audio) {
- audioUnMuted = true;
- this.audioMuted = false;
- if (this.localHold === false) {
- toogleMuteAudio.call(this, false);
- }
- }
- if (this.videoMuted === true && options.video) {
- videoUnMuted = true;
- this.videoMuted = false;
- if (this.localHold === false) {
- toogleMuteVideo.call(this, false);
- }
- }
- if (audioUnMuted === true || videoUnMuted === true) {
- onunmute.call(this, {
- audio: audioUnMuted,
- video: videoUnMuted
- });
- }
- };
- /**
- * Hold
- */
- RTCSession.prototype.hold = function(options, done) {
- debug('hold()');
- options = options || {};
- var self = this,
- eventHandlers;
- if (this.status !== C.STATUS_WAITING_FOR_ACK && this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- if (this.localHold === true) {
- return false;
- }
- if (! this.isReadyToReOffer()) {
- return false;
- }
- this.localHold = true;
- onhold.call(this, 'local');
- eventHandlers = {
- succeeded: function() {
- if (done) { done(); }
- },
- failed: function() {
- self.terminate({
- cause: JsSIP_C.causes.WEBRTC_ERROR,
- status_code: 500,
- reason_phrase: 'Hold Failed'
- });
- }
- };
- if (options.useUpdate) {
- sendUpdate.call(this, {
- sdpOffer: true,
- eventHandlers: eventHandlers,
- extraHeaders: options.extraHeaders
- });
- } else {
- sendReinvite.call(this, {
- eventHandlers: eventHandlers,
- extraHeaders: options.extraHeaders
- });
- }
- return true;
- };
- RTCSession.prototype.unhold = function(options, done) {
- debug('unhold()');
- options = options || {};
- var self = this,
- eventHandlers;
- if (this.status !== C.STATUS_WAITING_FOR_ACK && this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- if (this.localHold === false) {
- return false;
- }
- if (! this.isReadyToReOffer()) {
- return false;
- }
- this.localHold = false;
- onunhold.call(this, 'local');
- eventHandlers = {
- succeeded: function() {
- if (done) { done(); }
- },
- failed: function() {
- self.terminate({
- cause: JsSIP_C.causes.WEBRTC_ERROR,
- status_code: 500,
- reason_phrase: 'Unhold Failed'
- });
- }
- };
- if (options.useUpdate) {
- sendUpdate.call(this, {
- sdpOffer: true,
- eventHandlers: eventHandlers,
- extraHeaders: options.extraHeaders
- });
- } else {
- sendReinvite.call(this, {
- eventHandlers: eventHandlers,
- extraHeaders: options.extraHeaders
- });
- }
- return true;
- };
- RTCSession.prototype.renegotiate = function(options, done) {
- debug('renegotiate()');
- options = options || {};
- var self = this,
- eventHandlers,
- rtcOfferConstraints = options.rtcOfferConstraints || null;
- if (this.status !== C.STATUS_WAITING_FOR_ACK && this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- if (! this.isReadyToReOffer()) {
- return false;
- }
- eventHandlers = {
- succeeded: function() {
- if (done) { done(); }
- },
- failed: function() {
- self.terminate({
- cause: JsSIP_C.causes.WEBRTC_ERROR,
- status_code: 500,
- reason_phrase: 'Media Renegotiation Failed'
- });
- }
- };
- setLocalMediaStatus.call(this);
- if (options.useUpdate) {
- sendUpdate.call(this, {
- sdpOffer: true,
- eventHandlers: eventHandlers,
- rtcOfferConstraints: rtcOfferConstraints,
- extraHeaders: options.extraHeaders
- });
- } else {
- sendReinvite.call(this, {
- eventHandlers: eventHandlers,
- rtcOfferConstraints: rtcOfferConstraints,
- extraHeaders: options.extraHeaders
- });
- }
- return true;
- };
- /**
- * Refer
- */
- RTCSession.prototype.refer = function(target, options) {
- debug('refer()');
- var self = this,
- originalTarget = target,
- referSubscriber,
- id;
- if (this.status !== C.STATUS_WAITING_FOR_ACK && this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- // Check target validity
- target = this.ua.normalizeTarget(target);
- if (!target) {
- throw new TypeError('Invalid target: '+ originalTarget);
- }
- referSubscriber = new RTCSession_ReferSubscriber(this);
- referSubscriber.sendRefer(target, options);
- // Store in the map
- id = referSubscriber.outgoingRequest.cseq;
- this.referSubscribers[id] = referSubscriber;
- // Listen for ending events so we can remove it from the map
- referSubscriber.on('requestFailed', function() {
- delete self.referSubscribers[id];
- });
- referSubscriber.on('accepted', function() {
- delete self.referSubscribers[id];
- });
- referSubscriber.on('failed', function() {
- delete self.referSubscribers[id];
- });
- return referSubscriber;
- };
- /**
- * In dialog Request Reception
- */
- RTCSession.prototype.receiveRequest = function(request) {
- debug('receiveRequest()');
- var contentType,
- self = this;
- if(request.method === JsSIP_C.CANCEL) {
- /* RFC3261 15 States that a UAS may have accepted an invitation while a CANCEL
- * was in progress and that the UAC MAY continue with the session established by
- * any 2xx response, or MAY terminate with BYE. JsSIP does continue with the
- * established session. So the CANCEL is processed only if the session is not yet
- * established.
- */
- /*
- * Terminate the whole session in case the user didn't accept (or yet send the answer)
- * nor reject the request opening the session.
- */
- if(this.status === C.STATUS_WAITING_FOR_ANSWER || this.status === C.STATUS_ANSWERED) {
- this.status = C.STATUS_CANCELED;
- this.request.reply(487);
- failed.call(this, 'remote', request, JsSIP_C.causes.CANCELED);
- }
- } else {
- // Requests arriving here are in-dialog requests.
- switch(request.method) {
- case JsSIP_C.ACK:
- if (this.status !== C.STATUS_WAITING_FOR_ACK) {
- return;
- }
- // Update signaling status.
- this.status = C.STATUS_CONFIRMED;
- clearTimeout(this.timers.ackTimer);
- clearTimeout(this.timers.invite2xxTimer);
- if (this.late_sdp) {
- if (!request.body) {
- this.terminate({
- cause: JsSIP_C.causes.MISSING_SDP,
- status_code: 400
- });
- break;
- }
- var e = {originator:'remote', type:'answer', sdp:request.body};
- var answer = new RTCSessionDescription({type:'answer', sdp:e.sdp});
- this.emit('sdp', e);
- this.connection.setRemoteDescription(answer)
- .then(function() {
- if (!self.is_confirmed) {
- confirmed.call(self, 'remote', request);
- }
- })
- .catch(function(error) {
- self.terminate({
- cause: JsSIP_C.causes.BAD_MEDIA_DESCRIPTION,
- status_code: 488
- });
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- }
- else {
- if (!this.is_confirmed) {
- confirmed.call(this, 'remote', request);
- }
- }
- break;
- case JsSIP_C.BYE:
- if(this.status === C.STATUS_CONFIRMED) {
- request.reply(200);
- ended.call(this, 'remote', request, JsSIP_C.causes.BYE);
- }
- else if (this.status === C.STATUS_INVITE_RECEIVED) {
- request.reply(200);
- this.request.reply(487, 'BYE Received');
- ended.call(this, 'remote', request, JsSIP_C.causes.BYE);
- }
- else {
- request.reply(403, 'Wrong Status');
- }
- break;
- case JsSIP_C.INVITE:
- if(this.status === C.STATUS_CONFIRMED) {
- if (request.hasHeader('replaces')) {
- receiveReplaces.call(this, request);
- } else {
- receiveReinvite.call(this, request);
- }
- }
- else {
- request.reply(403, 'Wrong Status');
- }
- break;
- case JsSIP_C.INFO:
- if(this.status === C.STATUS_CONFIRMED || this.status === C.STATUS_WAITING_FOR_ACK || this.status === C.STATUS_INVITE_RECEIVED) {
- contentType = request.getHeader('content-type');
- if (contentType && (contentType.match(/^application\/dtmf-relay/i))) {
- new RTCSession_DTMF(this).init_incoming(request);
- }
- else if (contentType !== undefined) {
- new RTCSession_Info(this).init_incoming(request);
- }
- else {
- request.reply(415);
- }
- }
- else {
- request.reply(403, 'Wrong Status');
- }
- break;
- case JsSIP_C.UPDATE:
- if(this.status === C.STATUS_CONFIRMED) {
- receiveUpdate.call(this, request);
- }
- else {
- request.reply(403, 'Wrong Status');
- }
- break;
- case JsSIP_C.REFER:
- if(this.status === C.STATUS_CONFIRMED) {
- receiveRefer.call(this, request);
- }
- else {
- request.reply(403, 'Wrong Status');
- }
- break;
- case JsSIP_C.NOTIFY:
- if(this.status === C.STATUS_CONFIRMED) {
- receiveNotify.call(this, request);
- }
- else {
- request.reply(403, 'Wrong Status');
- }
- break;
- default:
- request.reply(501);
- }
- }
- };
- /**
- * Session Callbacks
- */
- RTCSession.prototype.onTransportError = function() {
- debugerror('onTransportError()');
- if(this.status !== C.STATUS_TERMINATED) {
- this.terminate({
- status_code: 500,
- reason_phrase: JsSIP_C.causes.CONNECTION_ERROR,
- cause: JsSIP_C.causes.CONNECTION_ERROR
- });
- }
- };
- RTCSession.prototype.onRequestTimeout = function() {
- debugerror('onRequestTimeout()');
- if(this.status !== C.STATUS_TERMINATED) {
- this.terminate({
- status_code: 408,
- reason_phrase: JsSIP_C.causes.REQUEST_TIMEOUT,
- cause: JsSIP_C.causes.REQUEST_TIMEOUT
- });
- }
- };
- RTCSession.prototype.onDialogError = function() {
- debugerror('onDialogError()');
- if(this.status !== C.STATUS_TERMINATED) {
- this.terminate({
- status_code: 500,
- reason_phrase: JsSIP_C.causes.DIALOG_ERROR,
- cause: JsSIP_C.causes.DIALOG_ERROR
- });
- }
- };
- // Called from DTMF handler.
- RTCSession.prototype.newDTMF = function(data) {
- debug('newDTMF()');
- this.emit('newDTMF', data);
- };
- // Called from Info handler.
- RTCSession.prototype.newInfo = function(data) {
- debug('newInfo()');
- this.emit('newInfo', data);
- };
- RTCSession.prototype.resetLocalMedia = function() {
- debug('resetLocalMedia()');
- // Reset all but remoteHold.
- this.localHold = false;
- this.audioMuted = false;
- this.videoMuted = false;
- setLocalMediaStatus.call(this);
- };
- /**
- * Private API.
- */
- /**
- * RFC3261 13.3.1.4
- * Response retransmissions cannot be accomplished by transaction layer
- * since it is destroyed when receiving the first 2xx answer
- */
- function setInvite2xxTimer(request, body) {
- var
- self = this,
- timeout = Timers.T1;
- this.timers.invite2xxTimer = setTimeout(function invite2xxRetransmission() {
- if (self.status !== C.STATUS_WAITING_FOR_ACK) {
- return;
- }
- request.reply(200, null, ['Contact: '+ self.contact], body);
- if (timeout < Timers.T2) {
- timeout = timeout * 2;
- if (timeout > Timers.T2) {
- timeout = Timers.T2;
- }
- }
- self.timers.invite2xxTimer = setTimeout(
- invite2xxRetransmission, timeout
- );
- }, timeout);
- }
- /**
- * RFC3261 14.2
- * If a UAS generates a 2xx response and never receives an ACK,
- * it SHOULD generate a BYE to terminate the dialog.
- */
- function setACKTimer() {
- var self = this;
- this.timers.ackTimer = setTimeout(function() {
- if(self.status === C.STATUS_WAITING_FOR_ACK) {
- debug('no ACK received, terminating the session');
- clearTimeout(self.timers.invite2xxTimer);
- sendRequest.call(self, JsSIP_C.BYE);
- ended.call(self, 'remote', null, JsSIP_C.causes.NO_ACK);
- }
- }, Timers.TIMER_H);
- }
- function createRTCConnection(pcConfig, rtcConstraints) {
- var self = this;
- this.connection = new RTCPeerConnection(pcConfig, rtcConstraints);
- this.connection.addEventListener('iceconnectionstatechange', function() {
- var state = self.connection.iceConnectionState;
- // TODO: Do more with different states.
- if (state === 'failed') {
- self.terminate({
- cause: JsSIP_C.causes.RTP_TIMEOUT,
- status_code: 408,
- reason_phrase: JsSIP_C.causes.RTP_TIMEOUT
- });
- }
- });
- }
- function createLocalDescription(type, onSuccess, onFailure, constraints) {
- debug('createLocalDescription()');
- var self = this;
- var connection = this.connection;
- this.rtcReady = false;
- if (type === 'offer') {
- connection.createOffer(constraints)
- .then(createSucceeded)
- .catch(function(error) {
- self.rtcReady = true;
- if (onFailure) { onFailure(error); }
- debugerror('emit "peerconnection:createofferfailed" [error:%o]', error);
- self.emit('peerconnection:createofferfailed', error);
- });
- }
- else if (type === 'answer') {
- connection.createAnswer(constraints)
- .then(createSucceeded)
- .catch(function(error) {
- self.rtcReady = true;
- if (onFailure) { onFailure(error); }
- debugerror('emit "peerconnection:createanswerfailed" [error:%o]', error);
- self.emit('peerconnection:createanswerfailed', error);
- });
- }
- else {
- throw new Error('createLocalDescription() | type must be "offer" or "answer", but "' +type+ '" was given');
- }
- // createAnswer or createOffer succeeded
- function createSucceeded(desc) {
- var listener;
- connection.addEventListener('icecandidate', listener = function(event) {
- var candidate = event.candidate;
- if (! candidate) {
- connection.removeEventListener('icecandidate', listener);
- self.rtcReady = true;
- if (onSuccess) {
- var e = {originator:'local', type:type, sdp:connection.localDescription.sdp};
- debug('emit "sdp"');
- self.emit('sdp', e);
- onSuccess(e.sdp);
- }
- onSuccess = null;
- }
- });
- connection.setLocalDescription(desc)
- .then(function() {
- if (connection.iceGatheringState === 'complete') {
- self.rtcReady = true;
- if (onSuccess) {
- var e = {originator:'local', type:type, sdp:connection.localDescription.sdp};
- debug('emit "sdp"');
- self.emit('sdp', e);
- onSuccess(e.sdp);
- onSuccess = null;
- }
- }
- })
- .catch(function(error) {
- self.rtcReady = true;
- if (onFailure) { onFailure(error); }
- debugerror('emit "peerconnection:setlocaldescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setlocaldescriptionfailed', error);
- });
- }
- }
- /**
- * Dialog Management
- */
- function createDialog(message, type, early) {
- var dialog, early_dialog,
- local_tag = (type === 'UAS') ? message.to_tag : message.from_tag,
- remote_tag = (type === 'UAS') ? message.from_tag : message.to_tag,
- id = message.call_id + local_tag + remote_tag;
- early_dialog = this.earlyDialogs[id];
- // Early Dialog
- if (early) {
- if (early_dialog) {
- return true;
- } else {
- early_dialog = new Dialog(this, message, type, Dialog.C.STATUS_EARLY);
- // Dialog has been successfully created.
- if(early_dialog.error) {
- debug(early_dialog.error);
- failed.call(this, 'remote', message, JsSIP_C.causes.INTERNAL_ERROR);
- return false;
- } else {
- this.earlyDialogs[id] = early_dialog;
- return true;
- }
- }
- }
- // Confirmed Dialog
- else {
- this.from_tag = message.from_tag;
- this.to_tag = message.to_tag;
- // In case the dialog is in _early_ state, update it
- if (early_dialog) {
- early_dialog.update(message, type);
- this.dialog = early_dialog;
- delete this.earlyDialogs[id];
- return true;
- }
- // Otherwise, create a _confirmed_ dialog
- dialog = new Dialog(this, message, type);
- if(dialog.error) {
- debug(dialog.error);
- failed.call(this, 'remote', message, JsSIP_C.causes.INTERNAL_ERROR);
- return false;
- } else {
- this.dialog = dialog;
- return true;
- }
- }
- }
- /**
- * In dialog INVITE Reception
- */
- function receiveReinvite(request) {
- debug('receiveReinvite()');
- var
- sdp, idx, direction, m,
- self = this,
- contentType = request.getHeader('Content-Type'),
- hold = false,
- rejected = false,
- data = {
- request: request,
- callback: undefined,
- reject: reject.bind(this)
- };
- function reject(options) {
- options = options || {};
- rejected = true;
- var
- status_code = options.status_code || 403,
- reason_phrase = options.reason_phrase || '',
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [];
- if (this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- if (status_code < 300 || status_code >= 700) {
- throw new TypeError('Invalid status_code: '+ status_code);
- }
- request.reply(status_code, reason_phrase, extraHeaders);
- }
- // Emit 'reinvite'.
- this.emit('reinvite', data);
- if (rejected) {
- return;
- }
- if (request.body) {
- this.late_sdp = false;
- if (contentType !== 'application/sdp') {
- debug('invalid Content-Type');
- request.reply(415);
- return;
- }
- sdp = request.parseSDP();
- for (idx=0; idx < sdp.media.length; idx++) {
- m = sdp.media[idx];
- if (holdMediaTypes.indexOf(m.type) === -1) {
- continue;
- }
- direction = m.direction || sdp.direction || 'sendrecv';
- if (direction === 'sendonly' || direction === 'inactive') {
- hold = true;
- }
- // If at least one of the streams is active don't emit 'hold'.
- else {
- hold = false;
- break;
- }
- }
- var e = {originator:'remote', type:'offer', sdp:request.body};
- var offer = new RTCSessionDescription({type:'offer', sdp:e.sdp});
- this.emit('sdp', e);
- this.connection.setRemoteDescription(offer)
- .then(doAnswer)
- .catch(function(error) {
- request.reply(488);
- debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- }
- else {
- this.late_sdp = true;
- doAnswer();
- }
- function doAnswer() {
- createSdp(
- // onSuccess
- function(sdp) {
- var extraHeaders = ['Contact: ' + self.contact];
- handleSessionTimersInIncomingRequest.call(self, request, extraHeaders);
- if (self.late_sdp) {
- sdp = mangleOffer.call(self, sdp);
- }
- request.reply(200, null, extraHeaders, sdp,
- function() {
- self.status = C.STATUS_WAITING_FOR_ACK;
- setInvite2xxTimer.call(self, request, sdp);
- setACKTimer.call(self);
- }
- );
- // If callback is given execute it.
- if (typeof data.callback === 'function') {
- data.callback();
- }
- },
- // onFailure
- function() {
- request.reply(500);
- }
- );
- }
- function createSdp(onSuccess, onFailure) {
- if (! self.late_sdp) {
- if (self.remoteHold === true && hold === false) {
- self.remoteHold = false;
- onunhold.call(self, 'remote');
- } else if (self.remoteHold === false && hold === true) {
- self.remoteHold = true;
- onhold.call(self, 'remote');
- }
- createLocalDescription.call(self, 'answer', onSuccess, onFailure, self.rtcAnswerConstraints);
- } else {
- createLocalDescription.call(self, 'offer', onSuccess, onFailure, self.rtcOfferConstraints);
- }
- }
- }
- /**
- * In dialog UPDATE Reception
- */
- function receiveUpdate(request) {
- debug('receiveUpdate()');
- var
- sdp, idx, direction, m,
- self = this,
- contentType = request.getHeader('Content-Type'),
- rejected = false,
- hold = false,
- data = {
- request: request,
- callback: undefined,
- reject: reject.bind(this)
- };
- function reject(options) {
- options = options || {};
- rejected = true;
- var
- status_code = options.status_code || 403,
- reason_phrase = options.reason_phrase || '',
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [];
- if (this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- if (status_code < 300 || status_code >= 700) {
- throw new TypeError('Invalid status_code: '+ status_code);
- }
- request.reply(status_code, reason_phrase, extraHeaders);
- }
- // Emit 'update'.
- this.emit('update', data);
- if (rejected) {
- return;
- }
- if (! request.body) {
- var extraHeaders = [];
- handleSessionTimersInIncomingRequest.call(this, request, extraHeaders);
- request.reply(200, null, extraHeaders);
- return;
- }
- if (contentType !== 'application/sdp') {
- debug('invalid Content-Type');
- request.reply(415);
- return;
- }
- sdp = request.parseSDP();
- for (idx=0; idx < sdp.media.length; idx++) {
- m = sdp.media[idx];
- if (holdMediaTypes.indexOf(m.type) === -1) {
- continue;
- }
- direction = m.direction || sdp.direction || 'sendrecv';
- if (direction === 'sendonly' || direction === 'inactive') {
- hold = true;
- }
- // If at least one of the streams is active don't emit 'hold'.
- else {
- hold = false;
- break;
- }
- }
- var e = {originator:'remote', type:'offer', sdp:request.body};
- debug('emit "sdp"');
- this.emit('sdp', e);
- var offer = new RTCSessionDescription({type:'offer', sdp:e.sdp});
- this.connection.setRemoteDescription(offer)
- .then(function() {
- if (self.remoteHold === true && hold === false) {
- self.remoteHold = false;
- onunhold.call(self, 'remote');
- } else if (self.remoteHold === false && hold === true) {
- self.remoteHold = true;
- onhold.call(self, 'remote');
- }
- createLocalDescription.call(self, 'answer',
- // success
- function(sdp) {
- var extraHeaders = ['Contact: ' + self.contact];
- handleSessionTimersInIncomingRequest.call(self, request, extraHeaders);
- request.reply(200, null, extraHeaders, sdp);
- // If callback is given execute it.
- if (typeof data.callback === 'function') {
- data.callback();
- }
- },
- // failure
- function() {
- request.reply(500);
- }
- );
- })
- .catch(function(error) {
- request.reply(488);
- debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- }
- /**
- * In dialog Refer Reception
- */
- function receiveRefer(request) {
- debug('receiveRefer()');
- var notifier,
- self = this;
- function accept(initCallback, options) {
- var session, replaces;
- options = options || {};
- initCallback = (typeof initCallback === 'function')? initCallback : null;
- if (this.status !== C.STATUS_WAITING_FOR_ACK && this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- session = new RTCSession(this.ua);
- session.on('progress', function(e) {
- notifier.notify(e.response.status_code, e.response.reason_phrase);
- });
- session.on('accepted', function(e) {
- notifier.notify(e.response.status_code, e.response.reason_phrase);
- });
- session.on('failed', function(e) {
- if (e.message) {
- notifier.notify(e.message.status_code, e.message.reason_phrase);
- } else {
- notifier.notify(487, e.cause);
- }
- });
- // Consider the Replaces header present in the Refer-To URI
- if (request.refer_to.uri.hasHeader('replaces')) {
- replaces = decodeURIComponent(request.refer_to.uri.getHeader('replaces'));
- options.extraHeaders = options.extraHeaders || [];
- options.extraHeaders.push('Replaces: '+ replaces);
- }
- session.connect(request.refer_to.uri.toAor(), options, initCallback);
- }
- function reject() {
- notifier.notify(603);
- }
- if (typeof request.refer_to === undefined) {
- debug('no Refer-To header field present in REFER');
- request.reply(400);
- return;
- }
- if (request.refer_to.uri.scheme !== JsSIP_C.SIP) {
- debug('Refer-To header field points to a non-SIP URI scheme');
- request.reply(416);
- return;
- }
- // reply before the transaction timer expires
- request.reply(202);
- notifier = new RTCSession_ReferNotifier(this, request.cseq);
- debug('emit "refer"');
- // Emit 'refer'.
- this.emit('refer', {
- request: request,
- accept: function(initCallback, options) { accept.call(self, initCallback, options); },
- reject: function() { reject.call(self); }
- });
- }
- /**
- * In dialog Notify Reception
- */
- function receiveNotify(request) {
- debug('receiveNotify()');
- if (typeof request.event === undefined) {
- request.reply(400);
- }
- switch (request.event.event) {
- case 'refer': {
- var id = request.event.params.id;
- var referSubscriber = this.referSubscribers[id];
- if (!referSubscriber) {
- request.reply(481, 'Subscription does not exist');
- return;
- }
- referSubscriber.receiveNotify(request);
- request.reply(200);
- break;
- }
- default: {
- request.reply(489);
- }
- }
- }
- /**
- * INVITE with Replaces Reception
- */
- function receiveReplaces(request) {
- debug('receiveReplaces()');
- var self = this;
- function accept(initCallback) {
- var session;
- if (this.status !== C.STATUS_WAITING_FOR_ACK && this.status !== C.STATUS_CONFIRMED) {
- return false;
- }
- session = new RTCSession(this.ua);
- // terminate the current session when the new one is confirmed
- session.on('confirmed', function() {
- self.terminate();
- });
- session.init_incoming(request, initCallback);
- }
- function reject() {
- debug('Replaced INVITE rejected by the user');
- request.reply(486);
- }
- // Emit 'replace'.
- this.emit('replaces', {
- request: request,
- accept: function(initCallback) { accept.call(self, initCallback); },
- reject: function() { reject.call(self); }
- });
- }
- /**
- * Initial Request Sender
- */
- function sendInitialRequest(mediaConstraints, rtcOfferConstraints, mediaStream) {
- var self = this;
- var request_sender = new RequestSender(self, this.ua);
- this.receiveResponse = function(response) {
- receiveInviteResponse.call(self, response);
- };
- // If a local MediaStream is given use it.
- if (mediaStream) {
- // Wait a bit so the app can set events such as 'peerconnection' and 'connecting'.
- setTimeout(function() {
- userMediaSucceeded(mediaStream);
- });
- // If at least audio or video is requested prompt getUserMedia.
- } else if (mediaConstraints.audio || mediaConstraints.video) {
- this.localMediaStreamLocallyGenerated = true;
- navigator.mediaDevices.getUserMedia(mediaConstraints)
- .then(userMediaSucceeded)
- .catch(function(error)
- {
- userMediaFailed(error);
- debugerror('emit "getusermediafailed" [error:%o]', error);
- self.emit('getusermediafailed', error);
- });
- // Otherwise don't prompt getUserMedia.
- } else {
- userMediaSucceeded(null);
- }
- // User media succeeded
- function userMediaSucceeded(stream) {
- if (self.status === C.STATUS_TERMINATED) { return; }
- self.localMediaStream = stream;
- if (stream) {
- self.connection.addStream(stream);
- }
- debug('emit "peerconnection"');
- // Notify the app with the RTCPeerConnection so it can do stuff on it
- // before generating the offer.
- self.emit('peerconnection', {
- peerconnection: self.connection
- });
- connecting.call(self, self.request);
- createLocalDescription.call(self, 'offer', rtcSucceeded, rtcFailed, rtcOfferConstraints);
- }
- // User media failed
- function userMediaFailed() {
- if (self.status === C.STATUS_TERMINATED) { return; }
- failed.call(self, 'local', null, JsSIP_C.causes.USER_DENIED_MEDIA_ACCESS);
- }
- function rtcSucceeded(desc) {
- if (self.isCanceled || self.status === C.STATUS_TERMINATED) { return; }
- self.request.body = desc;
- self.status = C.STATUS_INVITE_SENT;
- debug('emit "sending" [request:%o]', self.request);
- // Emit 'sending' so the app can mangle the body before the request
- // is sent.
- self.emit('sending', {
- request: self.request
- });
- request_sender.send();
- }
- function rtcFailed() {
- if (self.status === C.STATUS_TERMINATED) { return; }
- failed.call(self, 'system', null, JsSIP_C.causes.WEBRTC_ERROR);
- }
- }
- /**
- * Reception of Response for Initial INVITE
- */
- function receiveInviteResponse(response) {
- debug('receiveInviteResponse()');
- var cause, dialog, e, answer,
- self = this;
- // Handle 2XX retransmissions and responses from forked requests
- if (this.dialog && (response.status_code >=200 && response.status_code <=299)) {
- /*
- * If it is a retransmission from the endpoint that established
- * the dialog, send an ACK
- */
- if (this.dialog.id.call_id === response.call_id &&
- this.dialog.id.local_tag === response.from_tag &&
- this.dialog.id.remote_tag === response.to_tag) {
- sendRequest.call(this, JsSIP_C.ACK);
- return;
- }
- // If not, send an ACK and terminate
- else {
- dialog = new Dialog(this, response, 'UAC');
- if (dialog.error !== undefined) {
- debug(dialog.error);
- return;
- }
- dialog.sendRequest({
- owner: {status: C.STATUS_TERMINATED},
- onRequestTimeout: function(){},
- onTransportError: function(){},
- onDialogError: function(){},
- receiveResponse: function(){}
- }, JsSIP_C.ACK);
- dialog.sendRequest({
- owner: {status: C.STATUS_TERMINATED},
- onRequestTimeout: function(){},
- onTransportError: function(){},
- onDialogError: function(){},
- receiveResponse: function(){}
- }, JsSIP_C.BYE);
- return;
- }
- }
- // Proceed to cancellation if the user requested.
- if(this.isCanceled) {
- // Remove the flag. We are done.
- this.isCanceled = false;
- if(response.status_code >= 100 && response.status_code < 200) {
- this.request.cancel(this.cancelReason);
- } else if(response.status_code >= 200 && response.status_code < 299) {
- acceptAndTerminate.call(this, response);
- }
- return;
- }
- if(this.status !== C.STATUS_INVITE_SENT && this.status !== C.STATUS_1XX_RECEIVED) {
- return;
- }
- switch(true) {
- case /^100$/.test(response.status_code):
- this.status = C.STATUS_1XX_RECEIVED;
- break;
- case /^1[0-9]{2}$/.test(response.status_code):
- // Do nothing with 1xx responses without To tag.
- if (!response.to_tag) {
- debug('1xx response received without to tag');
- break;
- }
- // Create Early Dialog if 1XX comes with contact
- if (response.hasHeader('contact')) {
- // An error on dialog creation will fire 'failed' event
- if(! createDialog.call(this, response, 'UAC', true)) {
- break;
- }
- }
- this.status = C.STATUS_1XX_RECEIVED;
- progress.call(this, 'remote', response);
- if (!response.body) {
- break;
- }
- e = {originator:'remote', type:'answer', sdp:response.body};
- debug('emit "sdp"');
- this.emit('sdp', e);
- answer = new RTCSessionDescription({type:'answer', sdp:e.sdp});
- this.connection.setRemoteDescription(answer)
- .catch(function(error) {
- debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- this.status = C.STATUS_CONFIRMED;
- if(!response.body) {
- acceptAndTerminate.call(this, response, 400, JsSIP_C.causes.MISSING_SDP);
- failed.call(this, 'remote', response, JsSIP_C.causes.BAD_MEDIA_DESCRIPTION);
- break;
- }
- // An error on dialog creation will fire 'failed' event
- if (! createDialog.call(this, response, 'UAC')) {
- break;
- }
- e = {originator:'remote', type:'answer', sdp:response.body};
- debug('emit "sdp"');
- this.emit('sdp', e);
- answer = new RTCSessionDescription({type:'answer', sdp:e.sdp});
- Promise.resolve()
- .then(function() {
- // Be ready for 200 with SDP after a 180/183 with SDP. We created a SDP 'answer'
- // for it, so check the current signaling state.
- if (self.connection.signalingState === 'stable') {
- return self.connection.createOffer()
- .then(function(offer) {
- return self.connection.setLocalDescription(offer);
- })
- .catch(function(error) {
- acceptAndTerminate.call(self, response, 500, error.toString());
- failed.call(self, 'local', response, JsSIP_C.causes.WEBRTC_ERROR);
- debugerror('emit "peerconnection:setlocaldescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setlocaldescriptionfailed', error);
- });
- }
- })
- .then(function() {
- self.connection.setRemoteDescription(answer)
- .then(function() {
- // Handle Session Timers.
- handleSessionTimersInIncomingResponse.call(self, response);
- accepted.call(self, 'remote', response);
- sendRequest.call(self, JsSIP_C.ACK);
- confirmed.call(self, 'local', null);
- })
- .catch(function(error) {
- acceptAndTerminate.call(self, response, 488, 'Not Acceptable Here');
- failed.call(self, 'remote', response, JsSIP_C.causes.BAD_MEDIA_DESCRIPTION);
- debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- });
- break;
- default:
- cause = Utils.sipErrorCause(response.status_code);
- failed.call(this, 'remote', response, cause);
- }
- }
- /**
- * Send Re-INVITE
- */
- function sendReinvite(options) {
- debug('sendReinvite()');
- options = options || {};
- var
- self = this,
- extraHeaders = options.extraHeaders || [],
- eventHandlers = options.eventHandlers || {},
- rtcOfferConstraints = options.rtcOfferConstraints || this.rtcOfferConstraints || null,
- succeeded = false;
- extraHeaders.push('Contact: ' + this.contact);
- extraHeaders.push('Content-Type: application/sdp');
- // Session Timers.
- if (this.sessionTimers.running) {
- extraHeaders.push('Session-Expires: ' + this.sessionTimers.currentExpires + ';refresher=' + (this.sessionTimers.refresher ? 'uac' : 'uas'));
- }
- createLocalDescription.call(this, 'offer',
- // success
- function(sdp) {
- sdp = mangleOffer.call(self, sdp);
- var request = new RTCSession_Request(self, JsSIP_C.INVITE);
- request.send({
- extraHeaders: extraHeaders,
- body: sdp,
- eventHandlers: {
- onSuccessResponse: function(response) {
- onSucceeded(response);
- succeeded = true;
- },
- onErrorResponse: function(response) {
- onFailed(response);
- },
- onTransportError: function() {
- self.onTransportError(); // Do nothing because session ends.
- },
- onRequestTimeout: function() {
- self.onRequestTimeout(); // Do nothing because session ends.
- },
- onDialogError: function() {
- self.onDialogError(); // Do nothing because session ends.
- }
- }
- });
- },
- // failure
- function() {
- onFailed();
- },
- // RTC constraints.
- rtcOfferConstraints
- );
- function onSucceeded(response) {
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
- sendRequest.call(self, JsSIP_C.ACK);
- // If it is a 2XX retransmission exit now.
- if (succeeded) { return; }
- // Handle Session Timers.
- handleSessionTimersInIncomingResponse.call(self, response);
- // Must have SDP answer.
- if(! response.body) {
- onFailed();
- return;
- } else if (response.getHeader('Content-Type') !== 'application/sdp') {
- onFailed();
- return;
- }
- var e = {originator:'remote', type:'answer', sdp:response.body};
- debug('emit "sdp"');
- self.emit('sdp', e);
- var answer = new RTCSessionDescription({type:'answer', sdp:e.sdp});
- self.connection.setRemoteDescription(answer)
- .then(function() {
- if (eventHandlers.succeeded) {
- eventHandlers.succeeded(response);
- }
- })
- .catch(function(error) {
- onFailed();
- debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- }
- function onFailed(response) {
- if (eventHandlers.failed) {
- eventHandlers.failed(response);
- }
- }
- }
- /**
- * Send UPDATE
- */
- function sendUpdate(options) {
- debug('sendUpdate()');
- options = options || {};
- var
- self = this,
- extraHeaders = options.extraHeaders || [],
- eventHandlers = options.eventHandlers || {},
- rtcOfferConstraints = options.rtcOfferConstraints || this.rtcOfferConstraints || null,
- sdpOffer = options.sdpOffer || false,
- succeeded = false;
- extraHeaders.push('Contact: ' + this.contact);
- // Session Timers.
- if (this.sessionTimers.running) {
- extraHeaders.push('Session-Expires: ' + this.sessionTimers.currentExpires + ';refresher=' + (this.sessionTimers.refresher ? 'uac' : 'uas'));
- }
- if (sdpOffer) {
- extraHeaders.push('Content-Type: application/sdp');
- createLocalDescription.call(this, 'offer',
- // success
- function(sdp) {
- sdp = mangleOffer.call(self, sdp);
- var request = new RTCSession_Request(self, JsSIP_C.UPDATE);
- request.send({
- extraHeaders: extraHeaders,
- body: sdp,
- eventHandlers: {
- onSuccessResponse: function(response) {
- onSucceeded(response);
- succeeded = true;
- },
- onErrorResponse: function(response) {
- onFailed(response);
- },
- onTransportError: function() {
- self.onTransportError(); // Do nothing because session ends.
- },
- onRequestTimeout: function() {
- self.onRequestTimeout(); // Do nothing because session ends.
- },
- onDialogError: function() {
- self.onDialogError(); // Do nothing because session ends.
- }
- }
- });
- },
- // failure
- function() {
- onFailed();
- },
- // RTC constraints.
- rtcOfferConstraints
- );
- }
- // No SDP.
- else {
- var request = new RTCSession_Request(self, JsSIP_C.UPDATE);
- request.send({
- extraHeaders: extraHeaders,
- eventHandlers: {
- onSuccessResponse: function(response) {
- onSucceeded(response);
- },
- onErrorResponse: function(response) {
- onFailed(response);
- },
- onTransportError: function() {
- self.onTransportError(); // Do nothing because session ends.
- },
- onRequestTimeout: function() {
- self.onRequestTimeout(); // Do nothing because session ends.
- },
- onDialogError: function() {
- self.onDialogError(); // Do nothing because session ends.
- }
- }
- });
- }
- function onSucceeded(response) {
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
- // If it is a 2XX retransmission exit now.
- if (succeeded) { return; }
- // Handle Session Timers.
- handleSessionTimersInIncomingResponse.call(self, response);
- // Must have SDP answer.
- if (sdpOffer) {
- if(! response.body) {
- onFailed();
- return;
- } else if (response.getHeader('Content-Type') !== 'application/sdp') {
- onFailed();
- return;
- }
- var e = {originator:'remote', type:'answer', sdp:response.body};
- debug('emit "sdp"');
- self.emit('sdp', e);
- var answer = new RTCSessionDescription({type:'answer', sdp:e.sdp});
- self.connection.setRemoteDescription(answer)
- .then(function() {
- if (eventHandlers.succeeded) {
- eventHandlers.succeeded(response);
- }
- })
- .catch(function(error) {
- onFailed();
- debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);
- self.emit('peerconnection:setremotedescriptionfailed', error);
- });
- }
- // No SDP answer.
- else {
- if (eventHandlers.succeeded) {
- eventHandlers.succeeded(response);
- }
- }
- }
- function onFailed(response) {
- if (eventHandlers.failed) { eventHandlers.failed(response); }
- }
- }
- function acceptAndTerminate(response, status_code, reason_phrase) {
- debug('acceptAndTerminate()');
- var extraHeaders = [];
- if (status_code) {
- reason_phrase = reason_phrase || JsSIP_C.REASON_PHRASE[status_code] || '';
- extraHeaders.push('Reason: SIP ;cause=' + status_code + '; text="' + reason_phrase + '"');
- }
- // An error on dialog creation will fire 'failed' event
- if (this.dialog || createDialog.call(this, response, 'UAC')) {
- sendRequest.call(this, JsSIP_C.ACK);
- sendRequest.call(this, JsSIP_C.BYE, {
- extraHeaders: extraHeaders
- });
- }
- // Update session status.
- this.status = C.STATUS_TERMINATED;
- }
- /**
- * Send a generic in-dialog Request
- */
- function sendRequest(method, options) {
- debug('sendRequest()');
- var request = new RTCSession_Request(this, method);
- request.send(options);
- }
- /**
- * Correctly set the SDP direction attributes if the call is on local hold
- */
- function mangleOffer(sdp) {
- var idx, length, m;
- if (! this.localHold && ! this.remoteHold) {
- return sdp;
- }
- sdp = sdp_transform.parse(sdp);
- // Local hold.
- if (this.localHold && ! this.remoteHold) {
- debug('mangleOffer() | me on hold, mangling offer');
- length = sdp.media.length;
- for (idx=0; idx<length; idx++) {
- m = sdp.media[idx];
- if (holdMediaTypes.indexOf(m.type) === -1) {
- continue;
- }
- if (!m.direction) {
- m.direction = 'sendonly';
- } else if (m.direction === 'sendrecv') {
- m.direction = 'sendonly';
- } else if (m.direction === 'recvonly') {
- m.direction = 'inactive';
- }
- }
- }
- // Local and remote hold.
- else if (this.localHold && this.remoteHold) {
- debug('mangleOffer() | both on hold, mangling offer');
- length = sdp.media.length;
- for (idx=0; idx<length; idx++) {
- m = sdp.media[idx];
- if (holdMediaTypes.indexOf(m.type) === -1) {
- continue;
- }
- m.direction = 'inactive';
- }
- }
- // Remote hold.
- else if (this.remoteHold) {
- debug('mangleOffer() | remote on hold, mangling offer');
- length = sdp.media.length;
- for (idx=0; idx<length; idx++) {
- m = sdp.media[idx];
- if (holdMediaTypes.indexOf(m.type) === -1) {
- continue;
- }
- if (!m.direction) {
- m.direction = 'recvonly';
- } else if (m.direction === 'sendrecv') {
- m.direction = 'recvonly';
- } else if (m.direction === 'recvonly') {
- m.direction = 'inactive';
- }
- }
- }
- return sdp_transform.write(sdp);
- }
- function setLocalMediaStatus() {
- var enableAudio = true,
- enableVideo = true;
- if (this.localHold || this.remoteHold) {
- enableAudio = false;
- enableVideo = false;
- }
- if (this.audioMuted) {
- enableAudio = false;
- }
- if (this.videoMuted) {
- enableVideo = false;
- }
- toogleMuteAudio.call(this, !enableAudio);
- toogleMuteVideo.call(this, !enableVideo);
- }
- /**
- * Handle SessionTimers for an incoming INVITE or UPDATE.
- * @param {IncomingRequest} request
- * @param {Array} responseExtraHeaders Extra headers for the 200 response.
- */
- function handleSessionTimersInIncomingRequest(request, responseExtraHeaders) {
- if (! this.sessionTimers.enabled) { return; }
- var session_expires_refresher;
- if (request.session_expires && request.session_expires >= JsSIP_C.MIN_SESSION_EXPIRES) {
- this.sessionTimers.currentExpires = request.session_expires;
- session_expires_refresher = request.session_expires_refresher || 'uas';
- }
- else {
- this.sessionTimers.currentExpires = this.sessionTimers.defaultExpires;
- session_expires_refresher = 'uas';
- }
- responseExtraHeaders.push('Session-Expires: ' + this.sessionTimers.currentExpires + ';refresher=' + session_expires_refresher);
- this.sessionTimers.refresher = (session_expires_refresher === 'uas');
- runSessionTimer.call(this);
- }
- /**
- * Handle SessionTimers for an incoming response to INVITE or UPDATE.
- * @param {IncomingResponse} response
- */
- function handleSessionTimersInIncomingResponse(response) {
- if (! this.sessionTimers.enabled) { return; }
- var session_expires_refresher;
- if (response.session_expires && response.session_expires >= JsSIP_C.MIN_SESSION_EXPIRES) {
- this.sessionTimers.currentExpires = response.session_expires;
- session_expires_refresher = response.session_expires_refresher || 'uac';
- }
- else {
- this.sessionTimers.currentExpires = this.sessionTimers.defaultExpires;
- session_expires_refresher = 'uac';
- }
- this.sessionTimers.refresher = (session_expires_refresher === 'uac');
- runSessionTimer.call(this);
- }
- function runSessionTimer() {
- var self = this;
- var expires = this.sessionTimers.currentExpires;
- this.sessionTimers.running = true;
- clearTimeout(this.sessionTimers.timer);
- // I'm the refresher.
- if (this.sessionTimers.refresher) {
- this.sessionTimers.timer = setTimeout(function() {
- if (self.status === C.STATUS_TERMINATED) { return; }
- debug('runSessionTimer() | sending session refresh request');
- sendUpdate.call(self, {
- eventHandlers: {
- succeeded: function(response) {
- handleSessionTimersInIncomingResponse.call(self, response);
- }
- }
- });
- }, expires * 500); // Half the given interval (as the RFC states).
- }
- // I'm not the refresher.
- else {
- this.sessionTimers.timer = setTimeout(function() {
- if (self.status === C.STATUS_TERMINATED) { return; }
- debugerror('runSessionTimer() | timer expired, terminating the session');
- self.terminate({
- cause: JsSIP_C.causes.REQUEST_TIMEOUT,
- status_code: 408,
- reason_phrase: 'Session Timer Expired'
- });
- }, expires * 1100);
- }
- }
- function toogleMuteAudio(mute) {
- var streamIdx, trackIdx, streamsLength, tracksLength, tracks,
- localStreams = this.connection.getLocalStreams();
- streamsLength = localStreams.length;
- for (streamIdx = 0; streamIdx < streamsLength; streamIdx++) {
- tracks = localStreams[streamIdx].getAudioTracks();
- tracksLength = tracks.length;
- for (trackIdx = 0; trackIdx < tracksLength; trackIdx++) {
- tracks[trackIdx].enabled = !mute;
- }
- }
- }
- function toogleMuteVideo(mute) {
- var streamIdx, trackIdx, streamsLength, tracksLength, tracks,
- localStreams = this.connection.getLocalStreams();
- streamsLength = localStreams.length;
- for (streamIdx = 0; streamIdx < streamsLength; streamIdx++) {
- tracks = localStreams[streamIdx].getVideoTracks();
- tracksLength = tracks.length;
- for (trackIdx = 0; trackIdx < tracksLength; trackIdx++) {
- tracks[trackIdx].enabled = !mute;
- }
- }
- }
- function newRTCSession(originator, request) {
- debug('newRTCSession()');
- this.ua.newRTCSession({
- originator: originator,
- session: this,
- request: request
- });
- }
- function connecting(request) {
- debug('session connecting');
- debug('emit "connecting"');
- this.emit('connecting', {
- request: request
- });
- }
- function progress(originator, response) {
- debug('session progress');
- debug('emit "progress"');
- this.emit('progress', {
- originator: originator,
- response: response || null
- });
- }
- function accepted(originator, message) {
- debug('session accepted');
- this.start_time = new Date();
- debug('emit "accepted"');
- this.emit('accepted', {
- originator: originator,
- response: message || null
- });
- }
- function confirmed(originator, ack) {
- debug('session confirmed');
- this.is_confirmed = true;
- debug('emit "confirmed"');
- this.emit('confirmed', {
- originator: originator,
- ack: ack || null
- });
- }
- function ended(originator, message, cause) {
- debug('session ended');
- this.end_time = new Date();
- this.close();
- debug('emit "ended"');
- this.emit('ended', {
- originator: originator,
- message: message || null,
- cause: cause
- });
- }
- function failed(originator, message, cause) {
- debug('session failed');
- this.close();
- debug('emit "failed"');
- this.emit('failed', {
- originator: originator,
- message: message || null,
- cause: cause
- });
- }
- function onhold(originator) {
- debug('session onhold');
- setLocalMediaStatus.call(this);
- debug('emit "hold"');
- this.emit('hold', {
- originator: originator
- });
- }
- function onunhold(originator) {
- debug('session onunhold');
- setLocalMediaStatus.call(this);
- debug('emit "unhold"');
- this.emit('unhold', {
- originator: originator
- });
- }
- function onmute(options) {
- debug('session onmute');
- setLocalMediaStatus.call(this);
- debug('emit "muted"');
- this.emit('muted', {
- audio: options.audio,
- video: options.video
- });
- }
- function onunmute(options) {
- debug('session onunmute');
- setLocalMediaStatus.call(this);
- debug('emit "unmuted"');
- this.emit('unmuted', {
- audio: options.audio,
- video: options.video
- });
- }
- },{"./Constants":1,"./Dialog":2,"./Exceptions":5,"./RTCSession/DTMF":12,"./RTCSession/Info":13,"./RTCSession/ReferNotifier":14,"./RTCSession/ReferSubscriber":15,"./RTCSession/Request":16,"./RequestSender":18,"./SIPMessage":19,"./Timers":21,"./Transactions":22,"./Utils":26,"debug":35,"events":29,"sdp-transform":38,"util":33}],12:[function(require,module,exports){
- module.exports = DTMF;
- var C = {
- MIN_DURATION: 70,
- MAX_DURATION: 6000,
- DEFAULT_DURATION: 100,
- MIN_INTER_TONE_GAP: 50,
- DEFAULT_INTER_TONE_GAP: 500
- };
- /**
- * Expose C object.
- */
- DTMF.C = C;
- /**
- * Dependencies.
- */
- var util = require('util');
- var events = require('events');
- var debug = require('debug')('JsSIP:RTCSession:DTMF');
- var debugerror = require('debug')('JsSIP:ERROR:RTCSession:DTMF');
- debugerror.log = console.warn.bind(console);
- var JsSIP_C = require('../Constants');
- var Exceptions = require('../Exceptions');
- var RTCSession = require('../RTCSession');
- function DTMF(session) {
- this.owner = session;
- this.direction = null;
- this.tone = null;
- this.duration = null;
- events.EventEmitter.call(this);
- }
- util.inherits(DTMF, events.EventEmitter);
- DTMF.prototype.send = function(tone, options) {
- var extraHeaders, body;
- if (tone === undefined) {
- throw new TypeError('Not enough arguments');
- }
- this.direction = 'outgoing';
- // Check RTCSession Status
- if (this.owner.status !== RTCSession.C.STATUS_CONFIRMED &&
- this.owner.status !== RTCSession.C.STATUS_WAITING_FOR_ACK) {
- throw new Exceptions.InvalidStateError(this.owner.status);
- }
- // Get DTMF options
- options = options || {};
- extraHeaders = options.extraHeaders ? options.extraHeaders.slice() : [];
- this.eventHandlers = options.eventHandlers || {};
- // Check tone type
- if (typeof tone === 'string' ) {
- tone = tone.toUpperCase();
- } else if (typeof tone === 'number') {
- tone = tone.toString();
- } else {
- throw new TypeError('Invalid tone: '+ tone);
- }
- // Check tone value
- if (!tone.match(/^[0-9A-DR#*]$/)) {
- throw new TypeError('Invalid tone: '+ tone);
- } else {
- this.tone = tone;
- }
- // Duration is checked/corrected in RTCSession
- this.duration = options.duration;
- extraHeaders.push('Content-Type: application/dtmf-relay');
- body = 'Signal=' + this.tone + '\r\n';
- body += 'Duration=' + this.duration;
- this.owner.newDTMF({
- originator: 'local',
- dtmf: this,
- request: this.request
- });
- this.owner.dialog.sendRequest(this, JsSIP_C.INFO, {
- extraHeaders: extraHeaders,
- body: body
- });
- };
- DTMF.prototype.receiveResponse = function(response) {
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- this.emit('succeeded', {
- originator: 'remote',
- response: response
- });
- break;
- default:
- if (this.eventHandlers.onFailed) {
- this.eventHandlers.onFailed();
- }
- this.emit('failed', {
- originator: 'remote',
- response: response
- });
- break;
- }
- };
- DTMF.prototype.onRequestTimeout = function() {
- debugerror('onRequestTimeout');
- this.owner.onRequestTimeout();
- };
- DTMF.prototype.onTransportError = function() {
- debugerror('onTransportError');
- this.owner.onTransportError();
- };
- DTMF.prototype.onDialogError = function() {
- debugerror('onDialogError');
- this.owner.onDialogError();
- };
- DTMF.prototype.init_incoming = function(request) {
- var body,
- reg_tone = /^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*/,
- reg_duration = /^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*/;
- this.direction = 'incoming';
- this.request = request;
- request.reply(200);
- if (request.body) {
- body = request.body.split('\n');
- if (body.length >= 1) {
- if (reg_tone.test(body[0])) {
- this.tone = body[0].replace(reg_tone,'$2');
- }
- }
- if (body.length >=2) {
- if (reg_duration.test(body[1])) {
- this.duration = parseInt(body[1].replace(reg_duration,'$2'), 10);
- }
- }
- }
- if (!this.duration) {
- this.duration = C.DEFAULT_DURATION;
- }
- if (!this.tone) {
- debug('invalid INFO DTMF received, discarded');
- } else {
- this.owner.newDTMF({
- originator: 'remote',
- dtmf: this,
- request: request
- });
- }
- };
- },{"../Constants":1,"../Exceptions":5,"../RTCSession":11,"debug":35,"events":29,"util":33}],13:[function(require,module,exports){
- module.exports = Info;
- /**
- * Dependencies.
- */
- var util = require('util');
- var events = require('events');
- var debugerror = require('debug')('JsSIP:ERROR:RTCSession:Info');
- debugerror.log = console.warn.bind(console);
- var JsSIP_C = require('../Constants');
- var Exceptions = require('../Exceptions');
- var RTCSession = require('../RTCSession');
- function Info(session) {
- this.owner = session;
- this.direction = null;
- this.contentType = null;
- this.body = null;
- events.EventEmitter.call(this);
- }
- util.inherits(Info, events.EventEmitter);
- Info.prototype.send = function(contentType, body, options) {
- var extraHeaders;
- this.direction = 'outgoing';
- if (contentType === undefined) {
- throw new TypeError('Not enough arguments');
- }
- // Check RTCSession Status
- if (this.owner.status !== RTCSession.C.STATUS_CONFIRMED &&
- this.owner.status !== RTCSession.C.STATUS_WAITING_FOR_ACK) {
- throw new Exceptions.InvalidStateError(this.owner.status);
- }
- this.contentType = contentType;
- this.body = body;
- // Get Info options
- options = options || {};
- extraHeaders = options.extraHeaders ? options.extraHeaders.slice() : [];
- extraHeaders.push('Content-Type: '+ contentType);
- this.owner.newInfo({
- originator: 'local',
- info: this,
- request: this.request
- });
- this.owner.dialog.sendRequest(this, JsSIP_C.INFO, {
- extraHeaders: extraHeaders,
- body: body
- });
- };
- Info.prototype.receiveResponse = function(response) {
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- this.emit('succeeded', {
- originator: 'remote',
- response: response
- });
- break;
- default:
- this.emit('failed', {
- originator: 'remote',
- response: response
- });
- break;
- }
- };
- Info.prototype.onRequestTimeout = function() {
- debugerror('onRequestTimeout');
- this.owner.onRequestTimeout();
- };
- Info.prototype.onTransportError = function() {
- debugerror('onTransportError');
- this.owner.onTransportError();
- };
- Info.prototype.onDialogError = function() {
- debugerror('onDialogError');
- this.owner.onDialogError();
- };
- Info.prototype.init_incoming = function(request) {
- this.direction = 'incoming';
- this.request = request;
- request.reply(200);
- this.contentType = request.getHeader('content-type');
- this.body = request.body;
- this.owner.newInfo({
- originator: 'remote',
- info: this,
- request: request
- });
- };
- },{"../Constants":1,"../Exceptions":5,"../RTCSession":11,"debug":35,"events":29,"util":33}],14:[function(require,module,exports){
- module.exports = ReferNotifier;
- var C = {
- event_type: 'refer',
- body_type: 'message/sipfrag;version=2.0',
- expires: 300
- };
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP:RTCSession:ReferNotifier');
- var JsSIP_C = require('../Constants');
- var RTCSession_Request = require('./Request');
- function ReferNotifier(session, id, expires) {
- this.session = session;
- this.id = id;
- this.expires = expires || C.expires;
- this.active = true;
- // The creation of a Notifier results in an immediate NOTIFY
- this.notify(100);
- }
- ReferNotifier.prototype.notify = function(code, reason) {
- debug('notify()');
- var state,
- self = this;
- if (this.active === false) {
- return;
- }
- reason = reason || JsSIP_C.REASON_PHRASE[code] || '';
- if (code >= 200) {
- state = 'terminated;reason=noresource';
- } else {
- state = 'active;expires='+ this.expires;
- }
- // put this in a try/catch block
- var request = new RTCSession_Request(this.session, JsSIP_C.NOTIFY);
- request.send({
- extraHeaders: [
- 'Event: '+ C.event_type +';id='+ self.id,
- 'Subscription-State: '+ state,
- 'Content-Type: '+ C.body_type
- ],
- body: 'SIP/2.0 ' + code + ' ' + reason,
- eventHandlers: {
- // if a negative response is received, subscription is canceled
- onErrorResponse: function() { self.active = false; }
- }
- });
- };
- },{"../Constants":1,"./Request":16,"debug":35}],15:[function(require,module,exports){
- module.exports = ReferSubscriber;
- var C = {
- expires: 120
- };
- /**
- * Dependencies.
- */
- var util = require('util');
- var events = require('events');
- var debug = require('debug')('JsSIP:RTCSession:ReferSubscriber');
- var JsSIP_C = require('../Constants');
- var Grammar = require('../Grammar');
- var RTCSession_Request = require('./Request');
- function ReferSubscriber(session) {
- this.session = session;
- this.timer = null;
- // Instance of REFER OutgoingRequest
- this.outgoingRequest = null;
- events.EventEmitter.call(this);
- }
- util.inherits(ReferSubscriber, events.EventEmitter);
- ReferSubscriber.prototype.sendRefer = function(target, options) {
- debug('sendRefer()');
- var extraHeaders, eventHandlers, referTo,
- replaces = null,
- self = this;
- // Get REFER options
- options = options || {};
- extraHeaders = options.extraHeaders ? options.extraHeaders.slice() : [];
- eventHandlers = options.eventHandlers || {};
- // Set event handlers
- for (var event in eventHandlers) {
- this.on(event, eventHandlers[event]);
- }
- // Replaces URI header field
- if (options.replaces) {
- replaces = options.replaces.request.call_id;
- replaces += ';to-tag='+ options.replaces.to_tag;
- replaces += ';from-tag='+ options.replaces.from_tag;
- replaces = encodeURIComponent(replaces);
- }
- // Refer-To header field
- referTo = 'Refer-To: <'+ target + (replaces?'?Replaces='+ replaces:'') +'>';
- extraHeaders.push(referTo);
- var request = new RTCSession_Request(this.session, JsSIP_C.REFER);
- this.timer = setTimeout(function() {
- removeSubscriber.call(self);
- }, C.expires * 1000);
- request.send({
- extraHeaders: extraHeaders,
- eventHandlers: {
- onSuccessResponse: function(response) {
- self.emit('requestSucceeded', {
- response: response
- });
- },
- onErrorResponse: function(response) {
- self.emit('requestFailed', {
- response: response,
- cause: JsSIP_C.causes.REJECTED
- });
- },
- onTransportError: function() {
- removeSubscriber.call(self);
- self.emit('requestFailed', {
- response: null,
- cause: JsSIP_C.causes.CONNECTION_ERROR
- });
- },
- onRequestTimeout: function() {
- removeSubscriber.call(self);
- self.emit('requestFailed', {
- response: null,
- cause: JsSIP_C.causes.REQUEST_TIMEOUT
- });
- },
- onDialogError: function() {
- removeSubscriber.call(self);
- self.emit('requestFailed', {
- response: null,
- cause: JsSIP_C.causes.DIALOG_ERROR
- });
- }
- }
- });
- this.outgoingRequest = request.outgoingRequest;
- };
- ReferSubscriber.prototype.receiveNotify = function(request) {
- debug('receiveNotify()');
- var status_line;
- if (!request.body) {
- return;
- }
- status_line = Grammar.parse(request.body, 'Status_Line');
- if(status_line === -1) {
- debug('receiveNotify() | error parsing NOTIFY body: "' + request.body + '"');
- return;
- }
- switch(true) {
- case /^100$/.test(status_line.status_code):
- this.emit('trying', {
- request: request,
- status_line: status_line
- });
- break;
- case /^1[0-9]{2}$/.test(status_line.status_code):
- this.emit('progress', {
- request: request,
- status_line: status_line
- });
- break;
- case /^2[0-9]{2}$/.test(status_line.status_code):
- removeSubscriber.call(this);
- this.emit('accepted', {
- request: request,
- status_line: status_line
- });
- break;
- default:
- removeSubscriber.call(this);
- this.emit('failed', {
- request: request,
- status_line: status_line
- });
- break;
- }
- };
- // remove refer subscriber from the session
- function removeSubscriber() {
- console.log('removeSubscriber()');
- clearTimeout(this.timer);
- this.session.referSubscriber = null;
- }
- },{"../Constants":1,"../Grammar":6,"./Request":16,"debug":35,"events":29,"util":33}],16:[function(require,module,exports){
- module.exports = Request;
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP:RTCSession:Request');
- var debugerror = require('debug')('JsSIP:ERROR:RTCSession:Request');
- debugerror.log = console.warn.bind(console);
- var JsSIP_C = require('../Constants');
- var Exceptions = require('../Exceptions');
- var RTCSession = require('../RTCSession');
- function Request(session, method) {
- debug('new | %s', method);
- this.session = session;
- this.method = method;
- // Instance of OutgoingRequest
- this.outgoingRequest = null;
- // Check RTCSession Status
- if (this.session.status !== RTCSession.C.STATUS_1XX_RECEIVED &&
- this.session.status !== RTCSession.C.STATUS_WAITING_FOR_ANSWER &&
- this.session.status !== RTCSession.C.STATUS_WAITING_FOR_ACK &&
- this.session.status !== RTCSession.C.STATUS_CONFIRMED &&
- this.session.status !== RTCSession.C.STATUS_TERMINATED) {
- throw new Exceptions.InvalidStateError(this.session.status);
- }
- /*
- * Allow sending BYE in TERMINATED status since the RTCSession
- * could had been terminated before the ACK had arrived.
- * RFC3261 Section 15, Paragraph 2
- */
- else if (this.session.status === RTCSession.C.STATUS_TERMINATED && method !== JsSIP_C.BYE) {
- throw new Exceptions.InvalidStateError(this.session.status);
- }
- }
- Request.prototype.send = function(options) {
- options = options || {};
- var
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body || null;
- this.eventHandlers = options.eventHandlers || {};
- this.outgoingRequest = this.session.dialog.sendRequest(this, this.method, {
- extraHeaders: extraHeaders,
- body: body
- });
- };
- Request.prototype.receiveResponse = function(response) {
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- debug('onProgressResponse');
- if (this.eventHandlers.onProgressResponse) { this.eventHandlers.onProgressResponse(response); }
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- debug('onSuccessResponse');
- if (this.eventHandlers.onSuccessResponse) { this.eventHandlers.onSuccessResponse(response); }
- break;
- default:
- debug('onErrorResponse');
- if (this.eventHandlers.onErrorResponse) { this.eventHandlers.onErrorResponse(response); }
- break;
- }
- };
- Request.prototype.onRequestTimeout = function() {
- debugerror('onRequestTimeout');
- if (this.eventHandlers.onRequestTimeout) { this.eventHandlers.onRequestTimeout(); }
- };
- Request.prototype.onTransportError = function() {
- debugerror('onTransportError');
- if (this.eventHandlers.onTransportError) { this.eventHandlers.onTransportError(); }
- };
- Request.prototype.onDialogError = function() {
- debugerror('onDialogError');
- if (this.eventHandlers.onDialogError) { this.eventHandlers.onDialogError(); }
- };
- },{"../Constants":1,"../Exceptions":5,"../RTCSession":11,"debug":35}],17:[function(require,module,exports){
- module.exports = Registrator;
- /**
- * Dependecies
- */
- var debug = require('debug')('JsSIP:Registrator');
- var Utils = require('./Utils');
- var JsSIP_C = require('./Constants');
- var SIPMessage = require('./SIPMessage');
- var RequestSender = require('./RequestSender');
- function Registrator(ua, transport) {
- var reg_id=1; //Force reg_id to 1.
- this.ua = ua;
- this.transport = transport;
- this.registrar = ua.configuration.registrar_server;
- this.expires = ua.configuration.register_expires;
- // Call-ID and CSeq values RFC3261 10.2
- this.call_id = Utils.createRandomToken(22);
- this.cseq = 0;
- // this.to_uri
- this.to_uri = ua.configuration.uri;
- this.registrationTimer = null;
- // Ongoing Register request
- this.registering = false;
- // Set status
- this.registered = false;
- // Contact header
- this.contact = this.ua.contact.toString();
- // sip.ice media feature tag (RFC 5768)
- this.contact += ';+sip.ice';
- // Custom headers for REGISTER and un-REGISTER.
- this.extraHeaders = [];
- // Custom Contact header params for REGISTER and un-REGISTER.
- this.extraContactParams = '';
- if(reg_id) {
- this.contact += ';reg-id='+ reg_id;
- this.contact += ';+sip.instance="<urn:uuid:'+ this.ua.configuration.instance_id+'>"';
- }
- }
- Registrator.prototype = {
- setExtraHeaders: function(extraHeaders) {
- if (! Array.isArray(extraHeaders)) {
- extraHeaders = [];
- }
- this.extraHeaders = extraHeaders.slice();
- },
- setExtraContactParams: function(extraContactParams) {
- if (! (extraContactParams instanceof Object)) {
- extraContactParams = {};
- }
- // Reset it.
- this.extraContactParams = '';
- for(var param_key in extraContactParams) {
- var param_value = extraContactParams[param_key];
- this.extraContactParams += (';' + param_key);
- if (param_value) {
- this.extraContactParams += ('=' + param_value);
- }
- }
- },
- register: function() {
- var request_sender, cause, extraHeaders,
- self = this;
- if (this.registering) {
- debug('Register request in progress...');
- return;
- }
- extraHeaders = this.extraHeaders.slice();
- extraHeaders.push('Contact: ' + this.contact + ';expires=' + this.expires + this.extraContactParams);
- extraHeaders.push('Expires: '+ this.expires);
- this.request = new SIPMessage.OutgoingRequest(JsSIP_C.REGISTER, this.registrar, this.ua, {
- 'to_uri': this.to_uri,
- 'call_id': this.call_id,
- 'cseq': (this.cseq += 1)
- }, extraHeaders);
- request_sender = new RequestSender(this, this.ua);
- this.receiveResponse = function(response) {
- var contact, expires,
- contacts = response.getHeaders('contact').length;
- // Discard responses to older REGISTER/un-REGISTER requests.
- if(response.cseq !== this.cseq) {
- return;
- }
- // Clear registration timer
- if (this.registrationTimer !== null) {
- clearTimeout(this.registrationTimer);
- this.registrationTimer = null;
- }
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- this.registering = false;
- if(response.hasHeader('expires')) {
- expires = response.getHeader('expires');
- }
- // Search the Contact pointing to us and update the expires value accordingly.
- if (!contacts) {
- debug('no Contact header in response to REGISTER, response ignored');
- break;
- }
- while(contacts--) {
- contact = response.parseHeader('contact', contacts);
- if(contact.uri.user === this.ua.contact.uri.user) {
- expires = contact.getParam('expires');
- break;
- } else {
- contact = null;
- }
- }
- if (!contact) {
- debug('no Contact header pointing to us, response ignored');
- break;
- }
- if(!expires) {
- expires = this.expires;
- }
- // Re-Register or emit an event before the expiration interval has elapsed.
- // For that, decrease the expires value. ie: 3 seconds
- this.registrationTimer = setTimeout(function() {
- self.registrationTimer = null;
- // If there are no listeners for registrationExpiring, renew registration
- // If there are listeners, let the function listening do the register call
- if (self.ua.listeners('registrationExpiring').length === 0) {
- self.register();
- } else {
- self.ua.emit('registrationExpiring');
- }
- }, (expires * 1000) - 5000);
- //Save gruu values
- if (contact.hasParam('temp-gruu')) {
- this.ua.contact.temp_gruu = contact.getParam('temp-gruu').replace(/"/g,'');
- }
- if (contact.hasParam('pub-gruu')) {
- this.ua.contact.pub_gruu = contact.getParam('pub-gruu').replace(/"/g,'');
- }
- if (! this.registered) {
- this.registered = true;
- this.ua.registered({
- response: response
- });
- }
- break;
- // Interval too brief RFC3261 10.2.8
- case /^423$/.test(response.status_code):
- if(response.hasHeader('min-expires')) {
- // Increase our registration interval to the suggested minimum
- this.expires = response.getHeader('min-expires');
- // Attempt the registration again immediately
- this.register();
- } else { //This response MUST contain a Min-Expires header field
- debug('423 response received for REGISTER without Min-Expires');
- this.registrationFailure(response, JsSIP_C.causes.SIP_FAILURE_CODE);
- }
- break;
- default:
- cause = Utils.sipErrorCause(response.status_code);
- this.registrationFailure(response, cause);
- }
- };
- this.onRequestTimeout = function() {
- this.registrationFailure(null, JsSIP_C.causes.REQUEST_TIMEOUT);
- };
- this.onTransportError = function() {
- this.registrationFailure(null, JsSIP_C.causes.CONNECTION_ERROR);
- };
- this.registering = true;
- request_sender.send();
- },
- unregister: function(options) {
- var extraHeaders;
- if(!this.registered) {
- debug('already unregistered');
- return;
- }
- options = options || {};
- this.registered = false;
- // Clear the registration timer.
- if (this.registrationTimer !== null) {
- clearTimeout(this.registrationTimer);
- this.registrationTimer = null;
- }
- extraHeaders = this.extraHeaders.slice();
- if(options.all) {
- extraHeaders.push('Contact: *' + this.extraContactParams);
- extraHeaders.push('Expires: 0');
- this.request = new SIPMessage.OutgoingRequest(JsSIP_C.REGISTER, this.registrar, this.ua, {
- 'to_uri': this.to_uri,
- 'call_id': this.call_id,
- 'cseq': (this.cseq += 1)
- }, extraHeaders);
- } else {
- extraHeaders.push('Contact: '+ this.contact + ';expires=0' + this.extraContactParams);
- extraHeaders.push('Expires: 0');
- this.request = new SIPMessage.OutgoingRequest(JsSIP_C.REGISTER, this.registrar, this.ua, {
- 'to_uri': this.to_uri,
- 'call_id': this.call_id,
- 'cseq': (this.cseq += 1)
- }, extraHeaders);
- }
- var request_sender = new RequestSender(this, this.ua);
- this.receiveResponse = function(response) {
- var cause;
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- this.unregistered(response);
- break;
- default:
- cause = Utils.sipErrorCause(response.status_code);
- this.unregistered(response, cause);
- }
- };
- this.onRequestTimeout = function() {
- this.unregistered(null, JsSIP_C.causes.REQUEST_TIMEOUT);
- };
- this.onTransportError = function() {
- this.unregistered(null, JsSIP_C.causes.CONNECTION_ERROR);
- };
- request_sender.send();
- },
- registrationFailure: function(response, cause) {
- this.registering = false;
- this.ua.registrationFailed({
- response: response || null,
- cause: cause
- });
- if (this.registered) {
- this.registered = false;
- this.ua.unregistered({
- response: response || null,
- cause: cause
- });
- }
- },
- unregistered: function(response, cause) {
- this.registering = false;
- this.registered = false;
- this.ua.unregistered({
- response: response || null,
- cause: cause || null
- });
- },
- onTransportClosed: function() {
- this.registering = false;
- if (this.registrationTimer !== null) {
- clearTimeout(this.registrationTimer);
- this.registrationTimer = null;
- }
- if(this.registered) {
- this.registered = false;
- this.ua.unregistered({});
- }
- },
- close: function() {
- if (this.registered) {
- this.unregister();
- }
- }
- };
- },{"./Constants":1,"./RequestSender":18,"./SIPMessage":19,"./Utils":26,"debug":35}],18:[function(require,module,exports){
- module.exports = RequestSender;
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP:RequestSender');
- var JsSIP_C = require('./Constants');
- var UA = require('./UA');
- var DigestAuthentication = require('./DigestAuthentication');
- var Transactions = require('./Transactions');
- function RequestSender(applicant, ua) {
- this.ua = ua;
- this.applicant = applicant;
- this.method = applicant.request.method;
- this.request = applicant.request;
- this.auth = null;
- this.challenged = false;
- this.staled = false;
- // If ua is in closing process or even closed just allow sending Bye and ACK
- if (ua.status === UA.C.STATUS_USER_CLOSED && (this.method !== JsSIP_C.BYE || this.method !== JsSIP_C.ACK)) {
- this.onTransportError();
- }
- }
- /**
- * Create the client transaction and send the message.
- */
- RequestSender.prototype = {
- send: function() {
- switch(this.method) {
- case 'INVITE':
- this.clientTransaction = new Transactions.InviteClientTransaction(this, this.request, this.ua.transport);
- break;
- case 'ACK':
- this.clientTransaction = new Transactions.AckClientTransaction(this, this.request, this.ua.transport);
- break;
- default:
- this.clientTransaction = new Transactions.NonInviteClientTransaction(this, this.request, this.ua.transport);
- }
- this.clientTransaction.send();
- },
- /**
- * Callback fired when receiving a request timeout error from the client transaction.
- * To be re-defined by the applicant.
- */
- onRequestTimeout: function() {
- this.applicant.onRequestTimeout();
- },
- /**
- * Callback fired when receiving a transport error from the client transaction.
- * To be re-defined by the applicant.
- */
- onTransportError: function() {
- this.applicant.onTransportError();
- },
- /**
- * Called from client transaction when receiving a correct response to the request.
- * Authenticate request if needed or pass the response back to the applicant.
- */
- receiveResponse: function(response) {
- var
- cseq, challenge, authorization_header_name,
- status_code = response.status_code;
- /*
- * Authentication
- * Authenticate once. _challenged_ flag used to avoid infinite authentications.
- */
- if ((status_code === 401 || status_code === 407) &&
- (this.ua.configuration.password !== null || this.ua.configuration.ha1 !== null)) {
- // Get and parse the appropriate WWW-Authenticate or Proxy-Authenticate header.
- if (response.status_code === 401) {
- challenge = response.parseHeader('www-authenticate');
- authorization_header_name = 'authorization';
- } else {
- challenge = response.parseHeader('proxy-authenticate');
- authorization_header_name = 'proxy-authorization';
- }
- // Verify it seems a valid challenge.
- if (!challenge) {
- debug(response.status_code + ' with wrong or missing challenge, cannot authenticate');
- this.applicant.receiveResponse(response);
- return;
- }
- if (!this.challenged || (!this.staled && challenge.stale === true)) {
- if (!this.auth) {
- this.auth = new DigestAuthentication({
- username : this.ua.configuration.authorization_user,
- password : this.ua.configuration.password,
- realm : this.ua.configuration.realm,
- ha1 : this.ua.configuration.ha1
- });
- }
- // Verify that the challenge is really valid.
- if (!this.auth.authenticate(this.request, challenge)) {
- this.applicant.receiveResponse(response);
- return;
- }
- this.challenged = true;
- // Update ha1 and realm in the UA.
- this.ua.set('realm', this.auth.get('realm'));
- this.ua.set('ha1', this.auth.get('ha1'));
- if (challenge.stale) {
- this.staled = true;
- }
- if (response.method === JsSIP_C.REGISTER) {
- cseq = this.applicant.cseq += 1;
- } else if (this.request.dialog) {
- cseq = this.request.dialog.local_seqnum += 1;
- } else {
- cseq = this.request.cseq + 1;
- }
- this.request = this.applicant.request = this.request.clone();
- this.request.cseq = cseq;
- this.request.setHeader('cseq', cseq +' '+ this.method);
- this.request.setHeader(authorization_header_name, this.auth.toString());
- this.send();
- } else {
- this.applicant.receiveResponse(response);
- }
- } else {
- this.applicant.receiveResponse(response);
- }
- }
- };
- },{"./Constants":1,"./DigestAuthentication":4,"./Transactions":22,"./UA":24,"debug":35}],19:[function(require,module,exports){
- module.exports = {
- OutgoingRequest: OutgoingRequest,
- IncomingRequest: IncomingRequest,
- IncomingResponse: IncomingResponse
- };
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP:SIPMessage');
- var sdp_transform = require('sdp-transform');
- var JsSIP_C = require('./Constants');
- var Utils = require('./Utils');
- var NameAddrHeader = require('./NameAddrHeader');
- var Grammar = require('./Grammar');
- /**
- * -param {String} method request method
- * -param {String} ruri request uri
- * -param {UA} ua
- * -param {Object} params parameters that will have priority over ua.configuration parameters:
- * <br>
- * - cseq, call_id, from_tag, from_uri, from_display_name, to_uri, to_tag, route_set
- * -param {Object} [headers] extra headers
- * -param {String} [body]
- */
- function OutgoingRequest(method, ruri, ua, params, extraHeaders, body) {
- var
- to,
- from,
- call_id,
- cseq;
- params = params || {};
- // Mandatory parameters check
- if(!method || !ruri || !ua) {
- return null;
- }
- this.ua = ua;
- this.headers = {};
- this.method = method;
- this.ruri = ruri;
- this.body = body;
- this.extraHeaders = extraHeaders && extraHeaders.slice() || [];
- // Fill the Common SIP Request Headers
- // Route
- if (params.route_set) {
- this.setHeader('route', params.route_set);
- } else if (ua.configuration.use_preloaded_route) {
- this.setHeader('route', '<' + ua.transport.sip_uri + ';lr>');
- }
- // Via
- // Empty Via header. Will be filled by the client transaction.
- this.setHeader('via', '');
- // Max-Forwards
- this.setHeader('max-forwards', JsSIP_C.MAX_FORWARDS);
- // To
- to = (params.to_display_name || params.to_display_name === 0) ? '"' + params.to_display_name + '" ' : '';
- to += '<' + (params.to_uri || ruri) + '>';
- to += params.to_tag ? ';tag=' + params.to_tag : '';
- this.to = new NameAddrHeader.parse(to);
- this.setHeader('to', to);
- // From
- if (params.from_display_name || params.from_display_name === 0) {
- from = '"' + params.from_display_name + '" ';
- } else if (ua.configuration.display_name) {
- from = '"' + ua.configuration.display_name + '" ';
- } else {
- from = '';
- }
- from += '<' + (params.from_uri || ua.configuration.uri) + '>;tag=';
- from += params.from_tag || Utils.newTag();
- this.from = new NameAddrHeader.parse(from);
- this.setHeader('from', from);
- // Call-ID
- call_id = params.call_id || (ua.configuration.jssip_id + Utils.createRandomToken(15));
- this.call_id = call_id;
- this.setHeader('call-id', call_id);
- // CSeq
- cseq = params.cseq || Math.floor(Math.random() * 10000);
- this.cseq = cseq;
- this.setHeader('cseq', cseq + ' ' + method);
- }
- OutgoingRequest.prototype = {
- /**
- * Replace the the given header by the given value.
- * -param {String} name header name
- * -param {String | Array} value header value
- */
- setHeader: function(name, value) {
- var regexp, idx;
- // Remove the header from extraHeaders if present.
- regexp = new RegExp('^\\s*'+ name +'\\s*:','i');
- for (idx=0; idx<this.extraHeaders.length; idx++) {
- if (regexp.test(this.extraHeaders[idx])) {
- this.extraHeaders.splice(idx, 1);
- }
- }
- this.headers[Utils.headerize(name)] = (Array.isArray(value)) ? value : [value];
- },
- /**
- * Get the value of the given header name at the given position.
- * -param {String} name header name
- * -returns {String|undefined} Returns the specified header, null if header doesn't exist.
- */
- getHeader: function(name) {
- var regexp, idx,
- length = this.extraHeaders.length,
- header = this.headers[Utils.headerize(name)];
- if(header) {
- if(header[0]) {
- return header[0];
- }
- } else {
- regexp = new RegExp('^\\s*'+ name +'\\s*:','i');
- for (idx=0; idx<length; idx++) {
- header = this.extraHeaders[idx];
- if (regexp.test(header)) {
- return header.substring(header.indexOf(':')+1).trim();
- }
- }
- }
- return;
- },
- /**
- * Get the header/s of the given name.
- * -param {String} name header name
- * -returns {Array} Array with all the headers of the specified name.
- */
- getHeaders: function(name) {
- var idx, length, regexp,
- header = this.headers[Utils.headerize(name)],
- result = [];
- if (header) {
- length = header.length;
- for (idx = 0; idx < length; idx++) {
- result.push(header[idx]);
- }
- return result;
- } else {
- length = this.extraHeaders.length;
- regexp = new RegExp('^\\s*'+ name +'\\s*:','i');
- for (idx=0; idx<length; idx++) {
- header = this.extraHeaders[idx];
- if (regexp.test(header)) {
- result.push(header.substring(header.indexOf(':')+1).trim());
- }
- }
- return result;
- }
- },
- /**
- * Verify the existence of the given header.
- * -param {String} name header name
- * -returns {boolean} true if header with given name exists, false otherwise
- */
- hasHeader: function(name) {
- var regexp, idx,
- length = this.extraHeaders.length;
- if (this.headers[Utils.headerize(name)]) {
- return true;
- } else {
- regexp = new RegExp('^\\s*'+ name +'\\s*:','i');
- for (idx=0; idx<length; idx++) {
- if (regexp.test(this.extraHeaders[idx])) {
- return true;
- }
- }
- }
- return false;
- },
- /**
- * Parse the current body as a SDP and store the resulting object
- * into this.sdp.
- * -param {Boolean} force: Parse even if this.sdp already exists.
- *
- * Returns this.sdp.
- */
- parseSDP: function(force) {
- if (!force && this.sdp) {
- return this.sdp;
- } else {
- this.sdp = sdp_transform.parse(this.body || '');
- return this.sdp;
- }
- },
- toString: function() {
- var msg = '', header, length, idx,
- supported = [];
- msg += this.method + ' ' + this.ruri + ' SIP/2.0\r\n';
- for (header in this.headers) {
- length = this.headers[header].length;
- for (idx = 0; idx < length; idx++) {
- msg += header + ': ' + this.headers[header][idx] + '\r\n';
- }
- }
- length = this.extraHeaders.length;
- for (idx = 0; idx < length; idx++) {
- msg += this.extraHeaders[idx].trim() +'\r\n';
- }
- // Supported
- switch (this.method) {
- case JsSIP_C.REGISTER:
- supported.push('path', 'gruu');
- break;
- case JsSIP_C.INVITE:
- if (this.ua.configuration.session_timers) {
- supported.push('timer');
- }
- if (this.ua.contact.pub_gruu || this.ua.contact.temp_gruu) {
- supported.push('gruu');
- }
- supported.push('ice','replaces');
- break;
- case JsSIP_C.UPDATE:
- if (this.ua.configuration.session_timers) {
- supported.push('timer');
- }
- supported.push('ice');
- break;
- }
- supported.push('outbound');
- // Allow
- msg += 'Allow: '+ JsSIP_C.ALLOWED_METHODS +'\r\n';
- msg += 'Supported: ' + supported +'\r\n';
- msg += 'User-Agent: ' + JsSIP_C.USER_AGENT +'\r\n';
- if (this.body) {
- length = Utils.str_utf8_length(this.body);
- msg += 'Content-Length: ' + length + '\r\n\r\n';
- msg += this.body;
- } else {
- msg += 'Content-Length: 0\r\n\r\n';
- }
- return msg;
- },
- clone: function() {
- var request = new OutgoingRequest(this.method, this.ruri, this.ua);
- Object.keys(this.headers).forEach(function(name) {
- request.headers[name] = this.headers[name].slice();
- }, this);
- request.body = this.body;
- request.extraHeaders = this.extraHeaders && this.extraHeaders.slice() || [];
- request.to = this.to;
- request.from = this.from;
- request.call_id = this.call_id;
- request.cseq = this.cseq;
- return request;
- }
- };
- function IncomingMessage(){
- this.data = null;
- this.headers = null;
- this.method = null;
- this.via = null;
- this.via_branch = null;
- this.call_id = null;
- this.cseq = null;
- this.from = null;
- this.from_tag = null;
- this.to = null;
- this.to_tag = null;
- this.body = null;
- this.sdp = null;
- }
- IncomingMessage.prototype = {
- /**
- * Insert a header of the given name and value into the last position of the
- * header array.
- */
- addHeader: function(name, value) {
- var header = { raw: value };
- name = Utils.headerize(name);
- if(this.headers[name]) {
- this.headers[name].push(header);
- } else {
- this.headers[name] = [header];
- }
- },
- /**
- * Get the value of the given header name at the given position.
- */
- getHeader: function(name) {
- var header = this.headers[Utils.headerize(name)];
- if(header) {
- if(header[0]) {
- return header[0].raw;
- }
- } else {
- return;
- }
- },
- /**
- * Get the header/s of the given name.
- */
- getHeaders: function(name) {
- var idx, length,
- header = this.headers[Utils.headerize(name)],
- result = [];
- if(!header) {
- return [];
- }
- length = header.length;
- for (idx = 0; idx < length; idx++) {
- result.push(header[idx].raw);
- }
- return result;
- },
- /**
- * Verify the existence of the given header.
- */
- hasHeader: function(name) {
- return(this.headers[Utils.headerize(name)]) ? true : false;
- },
- /**
- * Parse the given header on the given index.
- * -param {String} name header name
- * -param {Number} [idx=0] header index
- * -returns {Object|undefined} Parsed header object, undefined if the header is not present or in case of a parsing error.
- */
- parseHeader: function(name, idx) {
- var header, value, parsed;
- name = Utils.headerize(name);
- idx = idx || 0;
- if(!this.headers[name]) {
- debug('header "' + name + '" not present');
- return;
- } else if(idx >= this.headers[name].length) {
- debug('not so many "' + name + '" headers present');
- return;
- }
- header = this.headers[name][idx];
- value = header.raw;
- if(header.parsed) {
- return header.parsed;
- }
- //substitute '-' by '_' for grammar rule matching.
- parsed = Grammar.parse(value, name.replace(/-/g, '_'));
- if(parsed === -1) {
- this.headers[name].splice(idx, 1); //delete from headers
- debug('error parsing "' + name + '" header field with value "' + value + '"');
- return;
- } else {
- header.parsed = parsed;
- return parsed;
- }
- },
- /**
- * Message Header attribute selector. Alias of parseHeader.
- * -param {String} name header name
- * -param {Number} [idx=0] header index
- * -returns {Object|undefined} Parsed header object, undefined if the header is not present or in case of a parsing error.
- *
- * -example
- * message.s('via',3).port
- */
- s: function(name, idx) {
- return this.parseHeader(name, idx);
- },
- /**
- * Replace the value of the given header by the value.
- * -param {String} name header name
- * -param {String} value header value
- */
- setHeader: function(name, value) {
- var header = { raw: value };
- this.headers[Utils.headerize(name)] = [header];
- },
- /**
- * Parse the current body as a SDP and store the resulting object
- * into this.sdp.
- * -param {Boolean} force: Parse even if this.sdp already exists.
- *
- * Returns this.sdp.
- */
- parseSDP: function(force) {
- if (!force && this.sdp) {
- return this.sdp;
- } else {
- this.sdp = sdp_transform.parse(this.body || '');
- return this.sdp;
- }
- },
- toString: function() {
- return this.data;
- }
- };
- function IncomingRequest(ua) {
- this.ua = ua;
- this.headers = {};
- this.ruri = null;
- this.transport = null;
- this.server_transaction = null;
- }
- IncomingRequest.prototype = new IncomingMessage();
- /**
- * Stateful reply.
- * -param {Number} code status code
- * -param {String} reason reason phrase
- * -param {Object} headers extra headers
- * -param {String} body body
- * -param {Function} [onSuccess] onSuccess callback
- * -param {Function} [onFailure] onFailure callback
- */
- IncomingRequest.prototype.reply = function(code, reason, extraHeaders, body, onSuccess, onFailure) {
- var rr, vias, length, idx, response,
- supported = [],
- to = this.getHeader('To'),
- r = 0,
- v = 0;
- code = code || null;
- reason = reason || null;
- // Validate code and reason values
- if (!code || (code < 100 || code > 699)) {
- throw new TypeError('Invalid status_code: '+ code);
- } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
- throw new TypeError('Invalid reason_phrase: '+ reason);
- }
- reason = reason || JsSIP_C.REASON_PHRASE[code] || '';
- extraHeaders = extraHeaders && extraHeaders.slice() || [];
- response = 'SIP/2.0 ' + code + ' ' + reason + '\r\n';
- if(this.method === JsSIP_C.INVITE && code > 100 && code <= 200) {
- rr = this.getHeaders('record-route');
- length = rr.length;
- for(r; r < length; r++) {
- response += 'Record-Route: ' + rr[r] + '\r\n';
- }
- }
- vias = this.getHeaders('via');
- length = vias.length;
- for(v; v < length; v++) {
- response += 'Via: ' + vias[v] + '\r\n';
- }
- if(!this.to_tag && code > 100) {
- to += ';tag=' + Utils.newTag();
- } else if(this.to_tag && !this.s('to').hasParam('tag')) {
- to += ';tag=' + this.to_tag;
- }
- response += 'To: ' + to + '\r\n';
- response += 'From: ' + this.getHeader('From') + '\r\n';
- response += 'Call-ID: ' + this.call_id + '\r\n';
- response += 'CSeq: ' + this.cseq + ' ' + this.method + '\r\n';
- length = extraHeaders.length;
- for (idx = 0; idx < length; idx++) {
- response += extraHeaders[idx].trim() +'\r\n';
- }
- // Supported
- switch (this.method) {
- case JsSIP_C.INVITE:
- if (this.ua.configuration.session_timers) {
- supported.push('timer');
- }
- if (this.ua.contact.pub_gruu || this.ua.contact.temp_gruu) {
- supported.push('gruu');
- }
- supported.push('ice','replaces');
- break;
- case JsSIP_C.UPDATE:
- if (this.ua.configuration.session_timers) {
- supported.push('timer');
- }
- if (body) {
- supported.push('ice');
- }
- supported.push('replaces');
- }
- supported.push('outbound');
- // Allow and Accept
- if (this.method === JsSIP_C.OPTIONS) {
- response += 'Allow: '+ JsSIP_C.ALLOWED_METHODS +'\r\n';
- response += 'Accept: '+ JsSIP_C.ACCEPTED_BODY_TYPES +'\r\n';
- } else if (code === 405) {
- response += 'Allow: '+ JsSIP_C.ALLOWED_METHODS +'\r\n';
- } else if (code === 415 ) {
- response += 'Accept: '+ JsSIP_C.ACCEPTED_BODY_TYPES +'\r\n';
- }
- response += 'Supported: ' + supported +'\r\n';
- if(body) {
- length = Utils.str_utf8_length(body);
- response += 'Content-Type: application/sdp\r\n';
- response += 'Content-Length: ' + length + '\r\n\r\n';
- response += body;
- } else {
- response += 'Content-Length: ' + 0 + '\r\n\r\n';
- }
- this.server_transaction.receiveResponse(code, response, onSuccess, onFailure);
- };
- /**
- * Stateless reply.
- * -param {Number} code status code
- * -param {String} reason reason phrase
- */
- IncomingRequest.prototype.reply_sl = function(code, reason) {
- var to, response,
- v = 0,
- vias = this.getHeaders('via'),
- length = vias.length;
- code = code || null;
- reason = reason || null;
- // Validate code and reason values
- if (!code || (code < 100 || code > 699)) {
- throw new TypeError('Invalid status_code: '+ code);
- } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
- throw new TypeError('Invalid reason_phrase: '+ reason);
- }
- reason = reason || JsSIP_C.REASON_PHRASE[code] || '';
- response = 'SIP/2.0 ' + code + ' ' + reason + '\r\n';
- for(v; v < length; v++) {
- response += 'Via: ' + vias[v] + '\r\n';
- }
- to = this.getHeader('To');
- if(!this.to_tag && code > 100) {
- to += ';tag=' + Utils.newTag();
- } else if(this.to_tag && !this.s('to').hasParam('tag')) {
- to += ';tag=' + this.to_tag;
- }
- response += 'To: ' + to + '\r\n';
- response += 'From: ' + this.getHeader('From') + '\r\n';
- response += 'Call-ID: ' + this.call_id + '\r\n';
- response += 'CSeq: ' + this.cseq + ' ' + this.method + '\r\n';
- response += 'Content-Length: ' + 0 + '\r\n\r\n';
- this.transport.send(response);
- };
- function IncomingResponse() {
- this.headers = {};
- this.status_code = null;
- this.reason_phrase = null;
- }
- IncomingResponse.prototype = new IncomingMessage();
- },{"./Constants":1,"./Grammar":6,"./NameAddrHeader":9,"./Utils":26,"debug":35,"sdp-transform":38}],20:[function(require,module,exports){
- module.exports = Socket;
- /**
- * Interface documentation: http://jssip.net/documentation/$last_version/api/socket/
- *
- * interface Socket {
- * attribute String via_transport
- * attribute String url
- * attribute String sip_uri
- *
- * method connect();
- * method disconnect();
- * method send(data);
- *
- * attribute EventHandler onconnect
- * attribute EventHandler ondisconnect
- * attribute EventHandler ondata
- * }
- *
- */
- /**
- * Dependencies.
- */
- var Utils = require('./Utils');
- var Grammar = require('./Grammar');
- var debugerror = require('debug')('JsSIP:ERROR:Socket');
- debugerror.log = console.warn.bind(console);
- function Socket() {}
- Socket.isSocket = function(socket) {
- // Ignore if an array is given
- if (Array.isArray(socket)) {
- return false;
- }
- if (typeof socket === 'undefined') {
- debugerror('undefined JsSIP.Socket instance');
- return false;
- }
- // Check Properties
- try {
- if (!Utils.isString(socket.url)) {
- debugerror('missing or invalid JsSIP.Socket url property');
- throw new Error();
- }
- if (!Utils.isString(socket.via_transport)) {
- debugerror('missing or invalid JsSIP.Socket via_transport property');
- throw new Error();
- }
- if (Grammar.parse(socket.sip_uri, 'SIP_URI') === -1) {
- debugerror('missing or invalid JsSIP.Socket sip_uri property');
- throw new Error();
- }
- } catch(e) {
- return false;
- }
- // Check Methods
- try {
- ['connect', 'disconnect', 'send'].forEach(function(method) {
- if (!Utils.isFunction(socket[method])) {
- debugerror('missing or invalid JsSIP.Socket method: ' + method);
- throw new Error();
- }
- });
- } catch(e) {
- return false;
- }
- return true;
- };
- },{"./Grammar":6,"./Utils":26,"debug":35}],21:[function(require,module,exports){
- var T1 = 500,
- T2 = 4000,
- T4 = 5000;
- var Timers = {
- T1: T1,
- T2: T2,
- T4: T4,
- TIMER_B: 64 * T1,
- TIMER_D: 0 * T1,
- TIMER_F: 64 * T1,
- TIMER_H: 64 * T1,
- TIMER_I: 0 * T1,
- TIMER_J: 0 * T1,
- TIMER_K: 0 * T4,
- TIMER_L: 64 * T1,
- TIMER_M: 64 * T1,
- PROVISIONAL_RESPONSE_INTERVAL: 60000 // See RFC 3261 Section 13.3.1.1
- };
- module.exports = Timers;
- },{}],22:[function(require,module,exports){
- module.exports = {
- C: null,
- NonInviteClientTransaction: NonInviteClientTransaction,
- InviteClientTransaction: InviteClientTransaction,
- AckClientTransaction: AckClientTransaction,
- NonInviteServerTransaction: NonInviteServerTransaction,
- InviteServerTransaction: InviteServerTransaction,
- checkTransaction: checkTransaction
- };
- var C = {
- // Transaction states
- STATUS_TRYING: 1,
- STATUS_PROCEEDING: 2,
- STATUS_CALLING: 3,
- STATUS_ACCEPTED: 4,
- STATUS_COMPLETED: 5,
- STATUS_TERMINATED: 6,
- STATUS_CONFIRMED: 7,
- // Transaction types
- NON_INVITE_CLIENT: 'nict',
- NON_INVITE_SERVER: 'nist',
- INVITE_CLIENT: 'ict',
- INVITE_SERVER: 'ist'
- };
- /**
- * Expose C object.
- */
- module.exports.C = C;
- /**
- * Dependencies.
- */
- var util = require('util');
- var events = require('events');
- var debugnict = require('debug')('JsSIP:NonInviteClientTransaction');
- var debugict = require('debug')('JsSIP:InviteClientTransaction');
- var debugact = require('debug')('JsSIP:AckClientTransaction');
- var debugnist = require('debug')('JsSIP:NonInviteServerTransaction');
- var debugist = require('debug')('JsSIP:InviteServerTransaction');
- var JsSIP_C = require('./Constants');
- var Timers = require('./Timers');
- function NonInviteClientTransaction(request_sender, request, transport) {
- var via;
- this.type = C.NON_INVITE_CLIENT;
- this.transport = transport;
- this.id = 'z9hG4bK' + Math.floor(Math.random() * 10000000);
- this.request_sender = request_sender;
- this.request = request;
- via = 'SIP/2.0/' + transport.via_transport;
- via += ' ' + request_sender.ua.configuration.via_host + ';branch=' + this.id;
- this.request.setHeader('via', via);
- this.request_sender.ua.newTransaction(this);
- events.EventEmitter.call(this);
- }
- util.inherits(NonInviteClientTransaction, events.EventEmitter);
- NonInviteClientTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged');
- };
- NonInviteClientTransaction.prototype.send = function() {
- var tr = this;
- this.stateChanged(C.STATUS_TRYING);
- this.F = setTimeout(function() {tr.timer_F();}, Timers.TIMER_F);
- if(!this.transport.send(this.request)) {
- this.onTransportError();
- }
- };
- NonInviteClientTransaction.prototype.onTransportError = function() {
- debugnict('transport error occurred, deleting transaction ' + this.id);
- clearTimeout(this.F);
- clearTimeout(this.K);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- this.request_sender.onTransportError();
- };
- NonInviteClientTransaction.prototype.timer_F = function() {
- debugnict('Timer F expired for transaction ' + this.id);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- this.request_sender.onRequestTimeout();
- };
- NonInviteClientTransaction.prototype.timer_K = function() {
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- };
- NonInviteClientTransaction.prototype.receiveResponse = function(response) {
- var
- tr = this,
- status_code = response.status_code;
- if(status_code < 200) {
- switch(this.state) {
- case C.STATUS_TRYING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_PROCEEDING);
- this.request_sender.receiveResponse(response);
- break;
- }
- } else {
- switch(this.state) {
- case C.STATUS_TRYING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_COMPLETED);
- clearTimeout(this.F);
- if(status_code === 408) {
- this.request_sender.onRequestTimeout();
- } else {
- this.request_sender.receiveResponse(response);
- }
- this.K = setTimeout(function() {tr.timer_K();}, Timers.TIMER_K);
- break;
- case C.STATUS_COMPLETED:
- break;
- }
- }
- };
- function InviteClientTransaction(request_sender, request, transport) {
- var via,
- tr = this;
- this.type = C.INVITE_CLIENT;
- this.transport = transport;
- this.id = 'z9hG4bK' + Math.floor(Math.random() * 10000000);
- this.request_sender = request_sender;
- this.request = request;
- via = 'SIP/2.0/' + transport.via_transport;
- via += ' ' + request_sender.ua.configuration.via_host + ';branch=' + this.id;
- this.request.setHeader('via', via);
- this.request_sender.ua.newTransaction(this);
- // TODO: Adding here the cancel() method is a hack that must be fixed.
- // Add the cancel property to the request.
- //Will be called from the request instance, not the transaction itself.
- this.request.cancel = function(reason) {
- tr.cancel_request(tr, reason);
- };
- events.EventEmitter.call(this);
- }
- util.inherits(InviteClientTransaction, events.EventEmitter);
- InviteClientTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged');
- };
- InviteClientTransaction.prototype.send = function() {
- var tr = this;
- this.stateChanged(C.STATUS_CALLING);
- this.B = setTimeout(function() {
- tr.timer_B();
- }, Timers.TIMER_B);
- if(!this.transport.send(this.request)) {
- this.onTransportError();
- }
- };
- InviteClientTransaction.prototype.onTransportError = function() {
- clearTimeout(this.B);
- clearTimeout(this.D);
- clearTimeout(this.M);
- if (this.state !== C.STATUS_ACCEPTED) {
- debugict('transport error occurred, deleting transaction ' + this.id);
- this.request_sender.onTransportError();
- }
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- };
- // RFC 6026 7.2
- InviteClientTransaction.prototype.timer_M = function() {
- debugict('Timer M expired for transaction ' + this.id);
- if(this.state === C.STATUS_ACCEPTED) {
- clearTimeout(this.B);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- }
- };
- // RFC 3261 17.1.1
- InviteClientTransaction.prototype.timer_B = function() {
- debugict('Timer B expired for transaction ' + this.id);
- if(this.state === C.STATUS_CALLING) {
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- this.request_sender.onRequestTimeout();
- }
- };
- InviteClientTransaction.prototype.timer_D = function() {
- debugict('Timer D expired for transaction ' + this.id);
- clearTimeout(this.B);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- };
- InviteClientTransaction.prototype.sendACK = function(response) {
- var tr = this;
- this.ack = 'ACK ' + this.request.ruri + ' SIP/2.0\r\n';
- this.ack += 'Via: ' + this.request.headers.Via.toString() + '\r\n';
- if(this.request.headers.Route) {
- this.ack += 'Route: ' + this.request.headers.Route.toString() + '\r\n';
- }
- this.ack += 'To: ' + response.getHeader('to') + '\r\n';
- this.ack += 'From: ' + this.request.headers.From.toString() + '\r\n';
- this.ack += 'Call-ID: ' + this.request.headers['Call-ID'].toString() + '\r\n';
- this.ack += 'CSeq: ' + this.request.headers.CSeq.toString().split(' ')[0];
- this.ack += ' ACK\r\n';
- this.ack += 'Content-Length: 0\r\n\r\n';
- this.D = setTimeout(function() {tr.timer_D();}, Timers.TIMER_D);
- this.transport.send(this.ack);
- };
- InviteClientTransaction.prototype.cancel_request = function(tr, reason) {
- var request = tr.request;
- this.cancel = JsSIP_C.CANCEL + ' ' + request.ruri + ' SIP/2.0\r\n';
- this.cancel += 'Via: ' + request.headers.Via.toString() + '\r\n';
- if(this.request.headers.Route) {
- this.cancel += 'Route: ' + request.headers.Route.toString() + '\r\n';
- }
- this.cancel += 'To: ' + request.headers.To.toString() + '\r\n';
- this.cancel += 'From: ' + request.headers.From.toString() + '\r\n';
- this.cancel += 'Call-ID: ' + request.headers['Call-ID'].toString() + '\r\n';
- this.cancel += 'CSeq: ' + request.headers.CSeq.toString().split(' ')[0] +
- ' CANCEL\r\n';
- if(reason) {
- this.cancel += 'Reason: ' + reason + '\r\n';
- }
- this.cancel += 'Content-Length: 0\r\n\r\n';
- // Send only if a provisional response (>100) has been received.
- if(this.state === C.STATUS_PROCEEDING) {
- this.transport.send(this.cancel);
- }
- };
- InviteClientTransaction.prototype.receiveResponse = function(response) {
- var
- tr = this,
- status_code = response.status_code;
- if(status_code >= 100 && status_code <= 199) {
- switch(this.state) {
- case C.STATUS_CALLING:
- this.stateChanged(C.STATUS_PROCEEDING);
- this.request_sender.receiveResponse(response);
- break;
- case C.STATUS_PROCEEDING:
- this.request_sender.receiveResponse(response);
- break;
- }
- } else if(status_code >= 200 && status_code <= 299) {
- switch(this.state) {
- case C.STATUS_CALLING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_ACCEPTED);
- this.M = setTimeout(function() {
- tr.timer_M();
- }, Timers.TIMER_M);
- this.request_sender.receiveResponse(response);
- break;
- case C.STATUS_ACCEPTED:
- this.request_sender.receiveResponse(response);
- break;
- }
- } else if(status_code >= 300 && status_code <= 699) {
- switch(this.state) {
- case C.STATUS_CALLING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_COMPLETED);
- this.sendACK(response);
- this.request_sender.receiveResponse(response);
- break;
- case C.STATUS_COMPLETED:
- this.sendACK(response);
- break;
- }
- }
- };
- function AckClientTransaction(request_sender, request, transport) {
- var via;
- this.transport = transport;
- this.id = 'z9hG4bK' + Math.floor(Math.random() * 10000000);
- this.request_sender = request_sender;
- this.request = request;
- via = 'SIP/2.0/' + transport.via_transport;
- via += ' ' + request_sender.ua.configuration.via_host + ';branch=' + this.id;
- this.request.setHeader('via', via);
- events.EventEmitter.call(this);
- }
- util.inherits(AckClientTransaction, events.EventEmitter);
- AckClientTransaction.prototype.send = function() {
- if(!this.transport.send(this.request)) {
- this.onTransportError();
- }
- };
- AckClientTransaction.prototype.onTransportError = function() {
- debugact('transport error occurred for transaction ' + this.id);
- this.request_sender.onTransportError();
- };
- function NonInviteServerTransaction(request, ua) {
- this.type = C.NON_INVITE_SERVER;
- this.id = request.via_branch;
- this.request = request;
- this.transport = request.transport;
- this.ua = ua;
- this.last_response = '';
- request.server_transaction = this;
- this.state = C.STATUS_TRYING;
- ua.newTransaction(this);
- events.EventEmitter.call(this);
- }
- util.inherits(NonInviteServerTransaction, events.EventEmitter);
- NonInviteServerTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged');
- };
- NonInviteServerTransaction.prototype.timer_J = function() {
- debugnist('Timer J expired for transaction ' + this.id);
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- };
- NonInviteServerTransaction.prototype.onTransportError = function() {
- if (!this.transportError) {
- this.transportError = true;
- debugnist('transport error occurred, deleting transaction ' + this.id);
- clearTimeout(this.J);
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- }
- };
- NonInviteServerTransaction.prototype.receiveResponse = function(status_code, response, onSuccess, onFailure) {
- var tr = this;
- if(status_code === 100) {
- /* RFC 4320 4.1
- * 'A SIP element MUST NOT
- * send any provisional response with a
- * Status-Code other than 100 to a non-INVITE request.'
- */
- switch(this.state) {
- case C.STATUS_TRYING:
- this.stateChanged(C.STATUS_PROCEEDING);
- if(!this.transport.send(response)) {
- this.onTransportError();
- }
- break;
- case C.STATUS_PROCEEDING:
- this.last_response = response;
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else if (onSuccess) {
- onSuccess();
- }
- break;
- }
- } else if(status_code >= 200 && status_code <= 699) {
- switch(this.state) {
- case C.STATUS_TRYING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_COMPLETED);
- this.last_response = response;
- this.J = setTimeout(function() {
- tr.timer_J();
- }, Timers.TIMER_J);
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else if (onSuccess) {
- onSuccess();
- }
- break;
- case C.STATUS_COMPLETED:
- break;
- }
- }
- };
- function InviteServerTransaction(request, ua) {
- this.type = C.INVITE_SERVER;
- this.id = request.via_branch;
- this.request = request;
- this.transport = request.transport;
- this.ua = ua;
- this.last_response = '';
- request.server_transaction = this;
- this.state = C.STATUS_PROCEEDING;
- ua.newTransaction(this);
- this.resendProvisionalTimer = null;
- request.reply(100);
- events.EventEmitter.call(this);
- }
- util.inherits(InviteServerTransaction, events.EventEmitter);
- InviteServerTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged');
- };
- InviteServerTransaction.prototype.timer_H = function() {
- debugist('Timer H expired for transaction ' + this.id);
- if(this.state === C.STATUS_COMPLETED) {
- debugist('ACK not received, dialog will be terminated');
- }
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- };
- InviteServerTransaction.prototype.timer_I = function() {
- this.stateChanged(C.STATUS_TERMINATED);
- };
- // RFC 6026 7.1
- InviteServerTransaction.prototype.timer_L = function() {
- debugist('Timer L expired for transaction ' + this.id);
- if(this.state === C.STATUS_ACCEPTED) {
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- }
- };
- InviteServerTransaction.prototype.onTransportError = function() {
- if (!this.transportError) {
- this.transportError = true;
- debugist('transport error occurred, deleting transaction ' + this.id);
- if (this.resendProvisionalTimer !== null) {
- clearInterval(this.resendProvisionalTimer);
- this.resendProvisionalTimer = null;
- }
- clearTimeout(this.L);
- clearTimeout(this.H);
- clearTimeout(this.I);
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- }
- };
- InviteServerTransaction.prototype.resend_provisional = function() {
- if(!this.transport.send(this.last_response)) {
- this.onTransportError();
- }
- };
- // INVITE Server Transaction RFC 3261 17.2.1
- InviteServerTransaction.prototype.receiveResponse = function(status_code, response, onSuccess, onFailure) {
- var tr = this;
- if(status_code >= 100 && status_code <= 199) {
- switch(this.state) {
- case C.STATUS_PROCEEDING:
- if(!this.transport.send(response)) {
- this.onTransportError();
- }
- this.last_response = response;
- break;
- }
- }
- if(status_code > 100 && status_code <= 199 && this.state === C.STATUS_PROCEEDING) {
- // Trigger the resendProvisionalTimer only for the first non 100 provisional response.
- if(this.resendProvisionalTimer === null) {
- this.resendProvisionalTimer = setInterval(function() {
- tr.resend_provisional();}, Timers.PROVISIONAL_RESPONSE_INTERVAL);
- }
- } else if(status_code >= 200 && status_code <= 299) {
- switch(this.state) {
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_ACCEPTED);
- this.last_response = response;
- this.L = setTimeout(function() {
- tr.timer_L();
- }, Timers.TIMER_L);
- if (this.resendProvisionalTimer !== null) {
- clearInterval(this.resendProvisionalTimer);
- this.resendProvisionalTimer = null;
- }
- /* falls through */
- case C.STATUS_ACCEPTED:
- // Note that this point will be reached for proceeding tr.state also.
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else if (onSuccess) {
- onSuccess();
- }
- break;
- }
- } else if(status_code >= 300 && status_code <= 699) {
- switch(this.state) {
- case C.STATUS_PROCEEDING:
- if (this.resendProvisionalTimer !== null) {
- clearInterval(this.resendProvisionalTimer);
- this.resendProvisionalTimer = null;
- }
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else {
- this.stateChanged(C.STATUS_COMPLETED);
- this.H = setTimeout(function() {
- tr.timer_H();
- }, Timers.TIMER_H);
- if (onSuccess) {
- onSuccess();
- }
- }
- break;
- }
- }
- };
- /**
- * INVITE:
- * _true_ if retransmission
- * _false_ new request
- *
- * ACK:
- * _true_ ACK to non2xx response
- * _false_ ACK must be passed to TU (accepted state)
- * ACK to 2xx response
- *
- * CANCEL:
- * _true_ no matching invite transaction
- * _false_ matching invite transaction and no final response sent
- *
- * OTHER:
- * _true_ retransmission
- * _false_ new request
- */
- function checkTransaction(ua, request) {
- var tr;
- switch(request.method) {
- case JsSIP_C.INVITE:
- tr = ua.transactions.ist[request.via_branch];
- if(tr) {
- switch(tr.state) {
- case C.STATUS_PROCEEDING:
- tr.transport.send(tr.last_response);
- break;
- // RFC 6026 7.1 Invite retransmission
- //received while in C.STATUS_ACCEPTED state. Absorb it.
- case C.STATUS_ACCEPTED:
- break;
- }
- return true;
- }
- break;
- case JsSIP_C.ACK:
- tr = ua.transactions.ist[request.via_branch];
- // RFC 6026 7.1
- if(tr) {
- if(tr.state === C.STATUS_ACCEPTED) {
- return false;
- } else if(tr.state === C.STATUS_COMPLETED) {
- tr.state = C.STATUS_CONFIRMED;
- tr.I = setTimeout(function() {tr.timer_I();}, Timers.TIMER_I);
- return true;
- }
- }
- // ACK to 2XX Response.
- else {
- return false;
- }
- break;
- case JsSIP_C.CANCEL:
- tr = ua.transactions.ist[request.via_branch];
- if(tr) {
- request.reply_sl(200);
- if(tr.state === C.STATUS_PROCEEDING) {
- return false;
- } else {
- return true;
- }
- } else {
- request.reply_sl(481);
- return true;
- }
- break;
- default:
- // Non-INVITE Server Transaction RFC 3261 17.2.2
- tr = ua.transactions.nist[request.via_branch];
- if(tr) {
- switch(tr.state) {
- case C.STATUS_TRYING:
- break;
- case C.STATUS_PROCEEDING:
- case C.STATUS_COMPLETED:
- tr.transport.send(tr.last_response);
- break;
- }
- return true;
- }
- break;
- }
- }
- },{"./Constants":1,"./Timers":21,"debug":35,"events":29,"util":33}],23:[function(require,module,exports){
- module.exports = Transport;
- /**
- * Dependencies.
- */
- var Socket = require('./Socket');
- var debug = require('debug')('JsSIP:Transport');
- var debugerror = require('debug')('JsSIP:ERROR:Transport');
- /**
- * Constants
- */
- var C = {
- // Transport status
- STATUS_CONNECTED: 0,
- STATUS_CONNECTING: 1,
- STATUS_DISCONNECTED: 2,
- // Socket status
- SOCKET_STATUS_READY: 0,
- SOCKET_STATUS_ERROR: 1,
- // Recovery options
- recovery_options: {
- min_interval: 2, // minimum interval in seconds between recover attempts
- max_interval: 30 // maximum interval in seconds between recover attempts
- }
- };
- /*
- * Manages one or multiple JsSIP.Socket instances.
- * Is reponsible for transport recovery logic among all socket instances.
- *
- * @socket JsSIP::Socket instance
- */
- function Transport(sockets, recovery_options) {
- debug('new()');
- this.status = C.STATUS_DISCONNECTED;
- // current socket
- this.socket = null;
- // socket collection
- this.sockets = [];
- this.recovery_options = recovery_options || C.recovery_options;
- this.recover_attempts = 0;
- this.recovery_timer = null;
- this.close_requested = false;
- if (typeof sockets === 'undefined') {
- throw new TypeError('Invalid argument.' +
- ' undefined \'sockets\' argument');
- }
- if (!(sockets instanceof Array)) {
- sockets = [ sockets ];
- }
- sockets.forEach(function(socket) {
- if (!Socket.isSocket(socket.socket)) {
- throw new TypeError('Invalid argument.' +
- ' invalid \'JsSIP.Socket\' instance');
- }
- if (socket.weight && !Number(socket.weight)) {
- throw new TypeError('Invalid argument.' +
- ' \'weight\' attribute is not a number');
- }
- this.sockets.push({
- socket: socket.socket,
- weight: socket.weight || 0,
- status: C.SOCKET_STATUS_READY
- });
- }, this);
- // read only properties
- Object.defineProperties(this, {
- via_transport: { get: function() { return this.socket.via_transport; } },
- url: { get: function() { return this.socket.url; } },
- sip_uri: { get: function() { return this.socket.sip_uri; } }
- });
- // get the socket with higher weight
- getSocket.call(this);
- }
- /**
- * Instance Methods
- */
- Transport.prototype.connect = function() {
- debug('connect()');
- if (this.isConnected()) {
- debug('Transport is already connected');
- return;
- } else if (this.isConnecting()) {
- debug('Transport is connecting');
- return;
- }
- this.close_requested = false;
- this.status = C.STATUS_CONNECTING;
- this.onconnecting({ socket:this.socket, attempts:this.recover_attempts });
- if (!this.close_requested) {
- // bind socket event callbacks
- this.socket.onconnect = onConnect.bind(this);
- this.socket.ondisconnect = onDisconnect.bind(this);
- this.socket.ondata = onData.bind(this);
- this.socket.connect();
- }
- return;
- };
- Transport.prototype.disconnect = function() {
- debug('close()');
- this.close_requested = true;
- this.recover_attempts = 0;
- this.status = C.STATUS_DISCONNECTED;
- // clear recovery_timer
- if (this.recovery_timer !== null) {
- clearTimeout(this.recovery_timer);
- this.recovery_timer = null;
- }
- // unbind socket event callbacks
- this.socket.onconnect = function() {};
- this.socket.ondisconnect = function() {};
- this.socket.ondata = function() {};
- this.socket.disconnect();
- this.ondisconnect();
- };
- Transport.prototype.send = function(data) {
- debug('send()');
- if (!this.isConnected()) {
- debugerror('unable to send message, transport is not connected');
- return false;
- }
- var message = data.toString();
- debug('sending message:\n\n' + message + '\n');
- return this.socket.send(message);
- };
- Transport.prototype.isConnected = function() {
- return this.status === C.STATUS_CONNECTED;
- };
- Transport.prototype.isConnecting = function() {
- return this.status === C.STATUS_CONNECTING;
- };
- /**
- * Socket Event Handlers
- */
- function onConnect() {
- this.recover_attempts = 0;
- this.status = C.STATUS_CONNECTED;
- // clear recovery_timer
- if (this.recovery_timer !== null) {
- clearTimeout(this.recovery_timer);
- this.recovery_timer = null;
- }
- this.onconnect( {socket:this} );
- }
- function onDisconnect(error, code, reason) {
- this.status = C.STATUS_DISCONNECTED;
- this.ondisconnect({ socket:this.socket, error:error, code:code, reason:reason });
- if (this.close_requested) {
- return;
- }
- // update socket status
- else {
- this.sockets.forEach(function(socket) {
- if (this.socket === socket.socket) {
- socket.status = C.SOCKET_STATUS_ERROR;
- }
- }, this);
- }
- reconnect.call(this, error);
- }
- function onData(data) {
- // CRLF Keep Alive response from server. Ignore it.
- if(data === '\r\n') {
- debug('received message with CRLF Keep Alive response');
- return;
- }
- // binary message.
- else if (typeof data !== 'string') {
- try {
- data = String.fromCharCode.apply(null, new Uint8Array(data));
- } catch(evt) {
- debug('received binary message failed to be converted into string,' +
- ' message discarded');
- return;
- }
- debug('received binary message:\n\n' + data + '\n');
- }
- // text message.
- else {
- debug('received text message:\n\n' + data + '\n');
- }
- this.ondata({ transport:this, message:data });
- }
- function reconnect() {
- var k,
- self = this;
- this.recover_attempts+=1;
- k = Math.floor((Math.random() * Math.pow(2,this.recover_attempts)) +1);
- if (k < this.recovery_options.min_interval) {
- k = this.recovery_options.min_interval;
- }
- else if (k > this.recovery_options.max_interval) {
- k = this.recovery_options.max_interval;
- }
- debug('reconnection attempt: '+ this.recover_attempts +
- '. next connection attempt in '+ k +' seconds');
- this.recovery_timer = setTimeout(function() {
- if (!self.close_requested && !(self.isConnected() || self.isConnecting())) {
- // get the next available socket with higher weight
- getSocket.call(self);
- // connect the socket
- self.connect();
- }
- }, k * 1000);
- }
- /**
- * get the next available socket with higher weight
- */
- function getSocket() {
- var candidates = [];
- this.sockets.forEach(function(socket) {
- if (socket.status === C.SOCKET_STATUS_ERROR) {
- return; // continue the array iteration
- } else if (candidates.length === 0) {
- candidates.push(socket);
- } else if (socket.weight > candidates[0].weight) {
- candidates = [socket];
- } else if (socket.weight === candidates[0].weight) {
- candidates.push(socket);
- }
- });
- if (candidates.length === 0) {
- // all sockets have failed. reset sockets status
- this.sockets.forEach(function(socket) {
- socket.status = C.SOCKET_STATUS_READY;
- });
- // get next available socket
- getSocket.call(this);
- return;
- }
- var idx = Math.floor((Math.random()* candidates.length));
- this.socket = candidates[idx].socket;
- }
- },{"./Socket":20,"debug":35}],24:[function(require,module,exports){
- module.exports = UA;
- var C = {
- // UA status codes
- STATUS_INIT : 0,
- STATUS_READY: 1,
- STATUS_USER_CLOSED: 2,
- STATUS_NOT_READY: 3,
- // UA error codes
- CONFIGURATION_ERROR: 1,
- NETWORK_ERROR: 2
- };
- /**
- * Expose C object.
- */
- UA.C = C;
- /**
- * Dependencies.
- */
- var util = require('util');
- var events = require('events');
- var debug = require('debug')('JsSIP:UA');
- var debugerror = require('debug')('JsSIP:ERROR:UA');
- debugerror.log = console.warn.bind(console);
- var JsSIP_C = require('./Constants');
- var Registrator = require('./Registrator');
- var RTCSession = require('./RTCSession');
- var Message = require('./Message');
- var Transactions = require('./Transactions');
- var Transport = require('./Transport');
- var Socket = require('./Socket');
- var Utils = require('./Utils');
- var Exceptions = require('./Exceptions');
- var URI = require('./URI');
- var Grammar = require('./Grammar');
- var Parser = require('./Parser');
- var SIPMessage = require('./SIPMessage');
- var sanityCheck = require('./sanityCheck');
- /**
- * The User-Agent class.
- * @class JsSIP.UA
- * @param {Object} configuration Configuration parameters.
- * @throws {JsSIP.Exceptions.ConfigurationError} If a configuration parameter is invalid.
- * @throws {TypeError} If no configuration is given.
- */
- function UA(configuration) {
- debug('new() [configuration:%o]', configuration);
- this.cache = {
- credentials: {}
- };
- this.configuration = {};
- this.dynConfiguration = {};
- this.dialogs = {};
- //User actions outside any session/dialog (MESSAGE)
- this.applicants = {};
- this.sessions = {};
- this.transport = null;
- this.contact = null;
- this.status = C.STATUS_INIT;
- this.error = null;
- this.transactions = {
- nist: {},
- nict: {},
- ist: {},
- ict: {}
- };
- // Custom UA empty object for high level use
- this.data = {};
- this.closeTimer = null;
- Object.defineProperties(this, {
- transactionsCount: {
- get: function() {
- var type,
- transactions = ['nist','nict','ist','ict'],
- count = 0;
- for (type in transactions) {
- count += Object.keys(this.transactions[transactions[type]]).length;
- }
- return count;
- }
- },
- nictTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions.nict).length;
- }
- },
- nistTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions.nist).length;
- }
- },
- ictTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions.ict).length;
- }
- },
- istTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions.ist).length;
- }
- }
- });
- /**
- * Load configuration
- */
- if(configuration === undefined) {
- throw new TypeError('Not enough arguments');
- }
- try {
- this.loadConfig(configuration);
- } catch(e) {
- this.status = C.STATUS_NOT_READY;
- this.error = C.CONFIGURATION_ERROR;
- throw e;
- }
- // Initialize registrator
- this._registrator = new Registrator(this);
- events.EventEmitter.call(this);
- }
- util.inherits(UA, events.EventEmitter);
- //=================
- // High Level API
- //=================
- /**
- * Connect to the server if status = STATUS_INIT.
- * Resume UA after being closed.
- */
- UA.prototype.start = function() {
- debug('start()');
- if (this.status === C.STATUS_INIT) {
- this.transport.connect();
- } else if(this.status === C.STATUS_USER_CLOSED) {
- debug('restarting UA');
- // disconnect
- if (this.closeTimer !== null) {
- clearTimeout(this.closeTimer);
- this.closeTimer = null;
- this.transport.disconnect();
- }
- // reconnect
- this.status = C.STATUS_INIT;
- this.transport.connect();
- } else if (this.status === C.STATUS_READY) {
- debug('UA is in READY status, not restarted');
- } else {
- debug('ERROR: connection is down, Auto-Recovery system is trying to reconnect');
- }
- // Set dynamic configuration.
- this.dynConfiguration.register = this.configuration.register;
- };
- /**
- * Register.
- */
- UA.prototype.register = function() {
- debug('register()');
- this.dynConfiguration.register = true;
- this._registrator.register();
- };
- /**
- * Unregister.
- */
- UA.prototype.unregister = function(options) {
- debug('unregister()');
- this.dynConfiguration.register = false;
- this._registrator.unregister(options);
- };
- /**
- * Get the Registrator instance.
- */
- UA.prototype.registrator = function() {
- return this._registrator;
- };
- /**
- * Registration state.
- */
- UA.prototype.isRegistered = function() {
- if(this._registrator.registered) {
- return true;
- } else {
- return false;
- }
- };
- /**
- * Connection state.
- */
- UA.prototype.isConnected = function() {
- return this.transport.isConnected();
- };
- /**
- * Make an outgoing call.
- *
- * -param {String} target
- * -param {Object} views
- * -param {Object} [options]
- *
- * -throws {TypeError}
- *
- */
- UA.prototype.call = function(target, options) {
- debug('call()');
- var session;
- session = new RTCSession(this);
- session.connect(target, options);
- return session;
- };
- /**
- * Send a message.
- *
- * -param {String} target
- * -param {String} body
- * -param {Object} [options]
- *
- * -throws {TypeError}
- *
- */
- UA.prototype.sendMessage = function(target, body, options) {
- debug('sendMessage()');
- var message;
- message = new Message(this);
- message.send(target, body, options);
- return message;
- };
- /**
- * Terminate ongoing sessions.
- */
- UA.prototype.terminateSessions = function(options) {
- debug('terminateSessions()');
- for(var idx in this.sessions) {
- if (!this.sessions[idx].isEnded()) {
- this.sessions[idx].terminate(options);
- }
- }
- };
- /**
- * Gracefully close.
- *
- */
- UA.prototype.stop = function() {
- debug('stop()');
- var session;
- var applicant;
- var num_sessions;
- var ua = this;
- // Remove dynamic settings.
- this.dynConfiguration = {};
- if(this.status === C.STATUS_USER_CLOSED) {
- debug('UA already closed');
- return;
- }
- // Close registrator
- this._registrator.close();
- // If there are session wait a bit so CANCEL/BYE can be sent and their responses received.
- num_sessions = Object.keys(this.sessions).length;
- // Run _terminate_ on every Session
- for(session in this.sessions) {
- debug('closing session ' + session);
- try { this.sessions[session].terminate(); } catch(error) {}
- }
- // Run _close_ on every applicant
- for(applicant in this.applicants) {
- try { this.applicants[applicant].close(); } catch(error) {}
- }
- this.status = C.STATUS_USER_CLOSED;
- if (this.nistTransactionsCount === 0 &&
- this.nictTransactionsCount === 0 &&
- this.ictTransactionsCount === 0 &&
- this.istTransactionsCount === 0 &&
- num_sessions === 0) {
- ua.transport.disconnect();
- }
- else {
- this.closeTimer = setTimeout(function() {
- ua.closeTimer = null;
- ua.transport.disconnect();
- }, 2000);
- }
- };
- /**
- * Normalice a string into a valid SIP request URI
- * -param {String} target
- * -returns {JsSIP.URI|undefined}
- */
- UA.prototype.normalizeTarget = function(target) {
- return Utils.normalizeTarget(target, this.configuration.hostport_params);
- };
- /**
- * Allow retrieving configuration and autogenerated fields in runtime.
- */
- UA.prototype.get = function(parameter) {
- switch(parameter) {
- case 'realm':
- return this.configuration.realm;
- case 'ha1':
- return this.configuration.ha1;
- default:
- debugerror('get() | cannot get "%s" parameter in runtime', parameter);
- return undefined;
- }
- return true;
- };
- /**
- * Allow configuration changes in runtime.
- * Returns true if the parameter could be set.
- */
- UA.prototype.set = function(parameter, value) {
- switch(parameter) {
- case 'password': {
- this.configuration.password = String(value);
- break;
- }
- case 'realm': {
- this.configuration.realm = String(value);
- break;
- }
- case 'ha1': {
- this.configuration.ha1 = String(value);
- // Delete the plain SIP password.
- this.configuration.password = null;
- break;
- }
- case 'display_name': {
- if (Grammar.parse('"' + value + '"', 'display_name') === -1) {
- debugerror('set() | wrong "display_name"');
- return false;
- }
- this.configuration.display_name = value;
- break;
- }
- default:
- debugerror('set() | cannot set "%s" parameter in runtime', parameter);
- return false;
- }
- return true;
- };
- //===============================
- // Private (For internal use)
- //===============================
- // UA.prototype.saveCredentials = function(credentials) {
- // this.cache.credentials[credentials.realm] = this.cache.credentials[credentials.realm] || {};
- // this.cache.credentials[credentials.realm][credentials.uri] = credentials;
- // };
- // UA.prototype.getCredentials = function(request) {
- // var realm, credentials;
- // realm = request.ruri.host;
- // if (this.cache.credentials[realm] && this.cache.credentials[realm][request.ruri]) {
- // credentials = this.cache.credentials[realm][request.ruri];
- // credentials.method = request.method;
- // }
- // return credentials;
- // };
- //==========================
- // Event Handlers
- //==========================
- /**
- * new Transaction
- */
- UA.prototype.newTransaction = function(transaction) {
- this.transactions[transaction.type][transaction.id] = transaction;
- this.emit('newTransaction', {
- transaction: transaction
- });
- };
- /**
- * Transaction destroyed.
- */
- UA.prototype.destroyTransaction = function(transaction) {
- delete this.transactions[transaction.type][transaction.id];
- this.emit('transactionDestroyed', {
- transaction: transaction
- });
- };
- /**
- * new Message
- */
- UA.prototype.newMessage = function(data) {
- this.emit('newMessage', data);
- };
- /**
- * new RTCSession
- */
- UA.prototype.newRTCSession = function(data) {
- this.emit('newRTCSession', data);
- };
- /**
- * Registered
- */
- UA.prototype.registered = function(data) {
- this.emit('registered', data);
- };
- /**
- * Unregistered
- */
- UA.prototype.unregistered = function(data) {
- this.emit('unregistered', data);
- };
- /**
- * Registration Failed
- */
- UA.prototype.registrationFailed = function(data) {
- this.emit('registrationFailed', data);
- };
- //=========================
- // receiveRequest
- //=========================
- /**
- * Request reception
- */
- UA.prototype.receiveRequest = function(request) {
- var dialog, session, message, replaces,
- method = request.method;
- // Check that request URI points to us
- if(request.ruri.user !== this.configuration.uri.user && request.ruri.user !== this.contact.uri.user) {
- debug('Request-URI does not point to us');
- if (request.method !== JsSIP_C.ACK) {
- request.reply_sl(404);
- }
- return;
- }
- // Check request URI scheme
- if(request.ruri.scheme === JsSIP_C.SIPS) {
- request.reply_sl(416);
- return;
- }
- // Check transaction
- if(Transactions.checkTransaction(this, request)) {
- return;
- }
- // Create the server transaction
- if(method === JsSIP_C.INVITE) {
- new Transactions.InviteServerTransaction(request, this);
- } else if(method !== JsSIP_C.ACK && method !== JsSIP_C.CANCEL) {
- new Transactions.NonInviteServerTransaction(request, this);
- }
- /* RFC3261 12.2.2
- * Requests that do not change in any way the state of a dialog may be
- * received within a dialog (for example, an OPTIONS request).
- * They are processed as if they had been received outside the dialog.
- */
- if(method === JsSIP_C.OPTIONS) {
- request.reply(200);
- } else if (method === JsSIP_C.MESSAGE) {
- if (this.listeners('newMessage').length === 0) {
- request.reply(405);
- return;
- }
- message = new Message(this);
- message.init_incoming(request);
- } else if (method === JsSIP_C.INVITE) {
- // Initial INVITE
- if(!request.to_tag && this.listeners('newRTCSession').length === 0) {
- request.reply(405);
- return;
- }
- }
- // Initial Request
- if(!request.to_tag) {
- switch(method) {
- case JsSIP_C.INVITE:
- if (window.RTCPeerConnection) { // TODO
- if (request.hasHeader('replaces')) {
- replaces = request.replaces;
- dialog = this.findDialog(replaces.call_id, replaces.from_tag, replaces.to_tag);
- if (dialog) {
- session = dialog.owner;
- if (!session.isEnded()) {
- session.receiveRequest(request);
- } else {
- request.reply(603);
- }
- } else {
- request.reply(481);
- }
- } else {
- session = new RTCSession(this);
- session.init_incoming(request);
- }
- } else {
- debugerror('INVITE received but WebRTC is not supported');
- request.reply(488);
- }
- break;
- case JsSIP_C.BYE:
- // Out of dialog BYE received
- request.reply(481);
- break;
- case JsSIP_C.CANCEL:
- session = this.findSession(request);
- if (session) {
- session.receiveRequest(request);
- } else {
- debug('received CANCEL request for a non existent session');
- }
- break;
- case JsSIP_C.ACK:
- /* Absorb it.
- * ACK request without a corresponding Invite Transaction
- * and without To tag.
- */
- break;
- default:
- request.reply(405);
- break;
- }
- }
- // In-dialog request
- else {
- dialog = this.findDialog(request.call_id, request.from_tag, request.to_tag);
- if(dialog) {
- dialog.receiveRequest(request);
- } else if (method === JsSIP_C.NOTIFY) {
- session = this.findSession(request);
- if(session) {
- session.receiveRequest(request);
- } else {
- debug('received NOTIFY request for a non existent subscription');
- request.reply(481, 'Subscription does not exist');
- }
- }
- /* RFC3261 12.2.2
- * Request with to tag, but no matching dialog found.
- * Exception: ACK for an Invite request for which a dialog has not
- * been created.
- */
- else {
- if(method !== JsSIP_C.ACK) {
- request.reply(481);
- }
- }
- }
- };
- //=================
- // Utils
- //=================
- /**
- * Get the session to which the request belongs to, if any.
- */
- UA.prototype.findSession = function(request) {
- var
- sessionIDa = request.call_id + request.from_tag,
- sessionA = this.sessions[sessionIDa],
- sessionIDb = request.call_id + request.to_tag,
- sessionB = this.sessions[sessionIDb];
- if(sessionA) {
- return sessionA;
- } else if(sessionB) {
- return sessionB;
- } else {
- return null;
- }
- };
- /**
- * Get the dialog to which the request belongs to, if any.
- */
- UA.prototype.findDialog = function(call_id, from_tag, to_tag) {
- var
- id = call_id + from_tag + to_tag,
- dialog = this.dialogs[id];
- if(dialog) {
- return dialog;
- } else {
- id = call_id + to_tag + from_tag;
- dialog = this.dialogs[id];
- if(dialog) {
- return dialog;
- } else {
- return null;
- }
- }
- };
- UA.prototype.loadConfig = function(configuration) {
- // Settings and default values
- var parameter, value, checked_value, hostport_params, registrar_server,
- settings = {
- /* Host address
- * Value to be set in Via sent_by and host part of Contact FQDN
- */
- via_host: Utils.createRandomToken(12) + '.invalid',
- // SIP Contact URI
- contact_uri: null,
- // SIP authentication password
- password: null,
- // SIP authentication realm
- realm: null,
- // SIP authentication HA1 hash
- ha1: null,
- // Registration parameters
- register_expires: 600,
- register: true,
- registrar_server: null,
- use_preloaded_route: false,
- // Session parameters
- no_answer_timeout: 60,
- session_timers: true,
- };
- // Pre-Configuration
- // Check Mandatory parameters
- for(parameter in UA.configuration_check.mandatory) {
- if(!configuration.hasOwnProperty(parameter)) {
- throw new Exceptions.ConfigurationError(parameter);
- } else {
- value = configuration[parameter];
- checked_value = UA.configuration_check.mandatory[parameter].call(this, value);
- if (checked_value !== undefined) {
- settings[parameter] = checked_value;
- } else {
- throw new Exceptions.ConfigurationError(parameter, value);
- }
- }
- }
- // Check Optional parameters
- for(parameter in UA.configuration_check.optional) {
- if(configuration.hasOwnProperty(parameter)) {
- value = configuration[parameter];
- /* If the parameter value is null, empty string, undefined, empty array
- * or it's a number with NaN value, then apply its default value.
- */
- if (Utils.isEmpty(value)) {
- continue;
- }
- checked_value = UA.configuration_check.optional[parameter].call(this, value, configuration);
- if (checked_value !== undefined) {
- settings[parameter] = checked_value;
- } else {
- throw new Exceptions.ConfigurationError(parameter, value);
- }
- }
- }
- // Post Configuration Process
- // Allow passing 0 number as display_name.
- if (settings.display_name === 0) {
- settings.display_name = '0';
- }
- // Instance-id for GRUU.
- if (!settings.instance_id) {
- settings.instance_id = Utils.newUUID();
- }
- // jssip_id instance parameter. Static random tag of length 5.
- settings.jssip_id = Utils.createRandomToken(5);
- // String containing settings.uri without scheme and user.
- hostport_params = settings.uri.clone();
- hostport_params.user = null;
- settings.hostport_params = hostport_params.toString().replace(/^sip:/i, '');
- // Transport
- var sockets = [];
- if (settings.sockets && Array.isArray(settings.sockets)) {
- sockets = sockets.concat(settings.sockets);
- }
- if (sockets.length === 0) {
- throw new Exceptions.ConfigurationError('sockets');
- }
- try {
- this.transport = new Transport(sockets, { /* recovery options */
- max_interval: settings.connection_recovery_max_interval,
- min_interval: settings.connection_recovery_min_interval
- });
- // Transport event callbacks
- this.transport.onconnecting = onTransportConnecting.bind(this);
- this.transport.onconnect = onTransportConnect.bind(this);
- this.transport.ondisconnect = onTransportDisconnect.bind(this);
- this.transport.ondata = onTransportData.bind(this);
- // transport options not needed here anymore
- delete settings.connection_recovery_max_interval;
- delete settings.connection_recovery_min_interval;
- delete settings.sockets;
- } catch (e) {
- debugerror(e);
- throw new Exceptions.ConfigurationError('sockets', sockets);
- }
- // Check whether authorization_user is explicitly defined.
- // Take 'settings.uri.user' value if not.
- if (!settings.authorization_user) {
- settings.authorization_user = settings.uri.user;
- }
- // If no 'registrar_server' is set use the 'uri' value without user portion and
- // without URI params/headers.
- if (!settings.registrar_server) {
- registrar_server = settings.uri.clone();
- registrar_server.user = null;
- registrar_server.clearParams();
- registrar_server.clearHeaders();
- settings.registrar_server = registrar_server;
- }
- // User no_answer_timeout.
- settings.no_answer_timeout = settings.no_answer_timeout * 1000;
- // Via Host
- if (settings.contact_uri) {
- settings.via_host = settings.contact_uri.host;
- }
- // Contact URI
- else {
- settings.contact_uri = new URI('sip', Utils.createRandomToken(8), settings.via_host, null, {transport: 'ws'});
- }
- this.contact = {
- pub_gruu: null,
- temp_gruu: null,
- uri: settings.contact_uri,
- toString: function(options) {
- options = options || {};
- var
- anonymous = options.anonymous || null,
- outbound = options.outbound || null,
- contact = '<';
- if (anonymous) {
- contact += this.temp_gruu || 'sip:anonymous@anonymous.invalid;transport=ws';
- } else {
- contact += this.pub_gruu || this.uri.toString();
- }
- if (outbound && (anonymous ? !this.temp_gruu : !this.pub_gruu)) {
- contact += ';ob';
- }
- contact += '>';
- return contact;
- }
- };
- // Fill the value of the configuration_skeleton
- for(parameter in settings) {
- UA.configuration_skeleton[parameter].value = settings[parameter];
- }
- Object.defineProperties(this.configuration, UA.configuration_skeleton);
- // Clean UA.configuration_skeleton
- for(parameter in settings) {
- UA.configuration_skeleton[parameter].value = '';
- }
- debug('configuration parameters after validation:');
- for(parameter in settings) {
- switch(parameter) {
- case 'uri':
- case 'registrar_server':
- debug('- ' + parameter + ': ' + settings[parameter]);
- break;
- case 'password':
- case 'ha1':
- debug('- ' + parameter + ': ' + 'NOT SHOWN');
- break;
- default:
- debug('- ' + parameter + ': ' + JSON.stringify(settings[parameter]));
- }
- }
- return;
- };
- /**
- * Configuration Object skeleton.
- */
- UA.configuration_skeleton = (function() {
- var
- idx, parameter, writable,
- skeleton = {},
- parameters = [
- // Internal parameters
- 'jssip_id',
- 'hostport_params',
- // Mandatory user configurable parameters
- 'uri',
- // Optional user configurable parameters
- 'authorization_user',
- 'contact_uri',
- 'display_name',
- 'instance_id',
- 'no_answer_timeout', // 30 seconds
- 'session_timers', // true
- 'password',
- 'realm',
- 'ha1',
- 'register_expires', // 600 seconds
- 'registrar_server',
- 'sockets',
- 'use_preloaded_route',
- // Post-configuration generated parameters
- 'via_core_value',
- 'via_host'
- ];
- var writable_parameters = [
- 'password', 'realm', 'ha1', 'display_name'
- ];
- for(idx in parameters) {
- parameter = parameters[idx];
- if (writable_parameters.indexOf(parameter) !== -1) {
- writable = true;
- } else {
- writable = false;
- }
- skeleton[parameter] = {
- value: '',
- writable: writable,
- configurable: false
- };
- }
- skeleton.register = {
- value: '',
- writable: true,
- configurable: false
- };
- return skeleton;
- }());
- /**
- * Configuration checker.
- */
- UA.configuration_check = {
- mandatory: {
- uri: function(uri) {
- var parsed;
- if (!/^sip:/i.test(uri)) {
- uri = JsSIP_C.SIP + ':' + uri;
- }
- parsed = URI.parse(uri);
- if(!parsed) {
- return;
- } else if(!parsed.user) {
- return;
- } else {
- return parsed;
- }
- }
- },
- optional: {
- authorization_user: function(authorization_user) {
- if(Grammar.parse('"'+ authorization_user +'"', 'quoted_string') === -1) {
- return;
- } else {
- return authorization_user;
- }
- },
- connection_recovery_max_interval: function(connection_recovery_max_interval) {
- var value;
- if(Utils.isDecimal(connection_recovery_max_interval)) {
- value = Number(connection_recovery_max_interval);
- if(value > 0) {
- return value;
- }
- }
- },
- connection_recovery_min_interval: function(connection_recovery_min_interval) {
- var value;
- if(Utils.isDecimal(connection_recovery_min_interval)) {
- value = Number(connection_recovery_min_interval);
- if(value > 0) {
- return value;
- }
- }
- },
- contact_uri: function(contact_uri) {
- if (typeof contact_uri === 'string') {
- var uri = Grammar.parse(contact_uri,'SIP_URI');
- if (uri !== -1) {
- return uri;
- }
- }
- },
- display_name: function(display_name) {
- if (Grammar.parse('"' + display_name + '"', 'display_name') === -1) {
- return;
- } else {
- return display_name;
- }
- },
- instance_id: function(instance_id) {
- if ((/^uuid:/i.test(instance_id))) {
- instance_id = instance_id.substr(5);
- }
- if(Grammar.parse(instance_id, 'uuid') === -1) {
- return;
- } else {
- return instance_id;
- }
- },
- no_answer_timeout: function(no_answer_timeout) {
- var value;
- if (Utils.isDecimal(no_answer_timeout)) {
- value = Number(no_answer_timeout);
- if (value > 0) {
- return value;
- }
- }
- },
- session_timers: function(session_timers) {
- if (typeof session_timers === 'boolean') {
- return session_timers;
- }
- },
- password: function(password) {
- return String(password);
- },
- realm: function(realm) {
- return String(realm);
- },
- ha1: function(ha1) {
- return String(ha1);
- },
- register: function(register) {
- if (typeof register === 'boolean') {
- return register;
- }
- },
- register_expires: function(register_expires) {
- var value;
- if (Utils.isDecimal(register_expires)) {
- value = Number(register_expires);
- if (value > 0) {
- return value;
- }
- }
- },
- registrar_server: function(registrar_server) {
- var parsed;
- if (!/^sip:/i.test(registrar_server)) {
- registrar_server = JsSIP_C.SIP + ':' + registrar_server;
- }
- parsed = URI.parse(registrar_server);
- if(!parsed) {
- return;
- } else if(parsed.user) {
- return;
- } else {
- return parsed;
- }
- },
- sockets: function(sockets) {
- var idx, length;
- /* Allow defining sockets parameter as:
- * Socket: socket
- * Array of Socket: [socket1, socket2]
- * Array of Objects: [{socket: socket1, weight:1}, {socket: Socket2, weight:0}]
- * Array of Objects and Socket: [{socket: socket1}, socket2]
- */
- if (Socket.isSocket(sockets)) {
- sockets = [{socket: sockets}];
- } else if (Array.isArray(sockets) && sockets.length) {
- length = sockets.length;
- for (idx = 0; idx < length; idx++) {
- if (Socket.isSocket(sockets[idx])) {
- sockets[idx] = {socket: sockets[idx]};
- }
- }
- } else {
- return;
- }
- return sockets;
- },
- use_preloaded_route: function(use_preloaded_route) {
- if (typeof use_preloaded_route === 'boolean') {
- return use_preloaded_route;
- }
- }
- }
- };
- /**
- * Transport event handlers
- */
- // Transport connecting event
- function onTransportConnecting(data) {
- this.emit('connecting', data);
- }
- // Transport connected event.
- function onTransportConnect(data) {
- if(this.status === C.STATUS_USER_CLOSED) {
- return;
- }
- this.status = C.STATUS_READY;
- this.error = null;
- this.emit('connected', data);
- if(this.dynConfiguration.register) {
- this._registrator.register();
- }
- }
- // Transport disconnected event.
- function onTransportDisconnect(data) {
- // Run _onTransportError_ callback on every client transaction using _transport_
- var type, idx, length,
- client_transactions = ['nict', 'ict', 'nist', 'ist'];
- length = client_transactions.length;
- for (type = 0; type < length; type++) {
- for(idx in this.transactions[client_transactions[type]]) {
- this.transactions[client_transactions[type]][idx].onTransportError();
- }
- }
- this.emit('disconnected', data);
- // Call registrator _onTransportClosed_
- this._registrator.onTransportClosed();
- if (this.status !== C.STATUS_USER_CLOSED) {
- this.status = C.STATUS_NOT_READY;
- this.error = C.NETWORK_ERROR;
- }
- }
- // Transport data event
- function onTransportData(data) {
- var transaction,
- transport = data.transport,
- message = data.message;
- message = Parser.parseMessage(message, this);
- if (! message) {
- return;
- }
- if (this.status === UA.C.STATUS_USER_CLOSED &&
- message instanceof SIPMessage.IncomingRequest) {
- return;
- }
- // Do some sanity check
- if(! sanityCheck(message, this, transport)) {
- return;
- }
- if(message instanceof SIPMessage.IncomingRequest) {
- message.transport = transport;
- this.receiveRequest(message);
- } else if(message instanceof SIPMessage.IncomingResponse) {
- /* Unike stated in 18.1.2, if a response does not match
- * any transaction, it is discarded here and no passed to the core
- * in order to be discarded there.
- */
- switch(message.method) {
- case JsSIP_C.INVITE:
- transaction = this.transactions.ict[message.via_branch];
- if(transaction) {
- transaction.receiveResponse(message);
- }
- break;
- case JsSIP_C.ACK:
- // Just in case ;-)
- break;
- default:
- transaction = this.transactions.nict[message.via_branch];
- if(transaction) {
- transaction.receiveResponse(message);
- }
- break;
- }
- }
- }
- },{"./Constants":1,"./Exceptions":5,"./Grammar":6,"./Message":8,"./Parser":10,"./RTCSession":11,"./Registrator":17,"./SIPMessage":19,"./Socket":20,"./Transactions":22,"./Transport":23,"./URI":25,"./Utils":26,"./sanityCheck":28,"debug":35,"events":29,"util":33}],25:[function(require,module,exports){
- module.exports = URI;
- /**
- * Dependencies.
- */
- var JsSIP_C = require('./Constants');
- var Utils = require('./Utils');
- var Grammar = require('./Grammar');
- /**
- * -param {String} [scheme]
- * -param {String} [user]
- * -param {String} host
- * -param {String} [port]
- * -param {Object} [parameters]
- * -param {Object} [headers]
- *
- */
- function URI(scheme, user, host, port, parameters, headers) {
- var param, header;
- // Checks
- if(!host) {
- throw new TypeError('missing or invalid "host" parameter');
- }
- // Initialize parameters
- scheme = scheme || JsSIP_C.SIP;
- this.parameters = {};
- this.headers = {};
- for (param in parameters) {
- this.setParam(param, parameters[param]);
- }
- for (header in headers) {
- this.setHeader(header, headers[header]);
- }
- Object.defineProperties(this, {
- scheme: {
- get: function(){ return scheme; },
- set: function(value){
- scheme = value.toLowerCase();
- }
- },
- user: {
- get: function(){ return user; },
- set: function(value){
- user = value;
- }
- },
- host: {
- get: function(){ return host; },
- set: function(value){
- host = value.toLowerCase();
- }
- },
- port: {
- get: function(){ return port; },
- set: function(value){
- port = value === 0 ? value : (parseInt(value,10) || null);
- }
- }
- });
- }
- URI.prototype = {
- setParam: function(key, value) {
- if(key) {
- this.parameters[key.toLowerCase()] = (typeof value === 'undefined' || value === null) ? null : value.toString();
- }
- },
- getParam: function(key) {
- if(key) {
- return this.parameters[key.toLowerCase()];
- }
- },
- hasParam: function(key) {
- if(key) {
- return (this.parameters.hasOwnProperty(key.toLowerCase()) && true) || false;
- }
- },
- deleteParam: function(parameter) {
- var value;
- parameter = parameter.toLowerCase();
- if (this.parameters.hasOwnProperty(parameter)) {
- value = this.parameters[parameter];
- delete this.parameters[parameter];
- return value;
- }
- },
- clearParams: function() {
- this.parameters = {};
- },
- setHeader: function(name, value) {
- this.headers[Utils.headerize(name)] = (Array.isArray(value)) ? value : [value];
- },
- getHeader: function(name) {
- if(name) {
- return this.headers[Utils.headerize(name)];
- }
- },
- hasHeader: function(name) {
- if(name) {
- return (this.headers.hasOwnProperty(Utils.headerize(name)) && true) || false;
- }
- },
- deleteHeader: function(header) {
- var value;
- header = Utils.headerize(header);
- if(this.headers.hasOwnProperty(header)) {
- value = this.headers[header];
- delete this.headers[header];
- return value;
- }
- },
- clearHeaders: function() {
- this.headers = {};
- },
- clone: function() {
- return new URI(
- this.scheme,
- this.user,
- this.host,
- this.port,
- JSON.parse(JSON.stringify(this.parameters)),
- JSON.parse(JSON.stringify(this.headers)));
- },
- toString: function(){
- var header, parameter, idx, uri,
- headers = [];
- uri = this.scheme + ':';
- if (this.user) {
- uri += Utils.escapeUser(this.user) + '@';
- }
- uri += this.host;
- if (this.port || this.port === 0) {
- uri += ':' + this.port;
- }
- for (parameter in this.parameters) {
- uri += ';' + parameter;
- if (this.parameters[parameter] !== null) {
- uri += '='+ this.parameters[parameter];
- }
- }
- for(header in this.headers) {
- for(idx = 0; idx < this.headers[header].length; idx++) {
- headers.push(header + '=' + this.headers[header][idx]);
- }
- }
- if (headers.length > 0) {
- uri += '?' + headers.join('&');
- }
- return uri;
- },
- toAor: function(show_port){
- var aor;
- aor = this.scheme + ':';
- if (this.user) {
- aor += Utils.escapeUser(this.user) + '@';
- }
- aor += this.host;
- if (show_port && (this.port || this.port === 0)) {
- aor += ':' + this.port;
- }
- return aor;
- }
- };
- /**
- * Parse the given string and returns a JsSIP.URI instance or undefined if
- * it is an invalid URI.
- */
- URI.parse = function(uri) {
- uri = Grammar.parse(uri,'SIP_URI');
- if (uri !== -1) {
- return uri;
- } else {
- return undefined;
- }
- };
- },{"./Constants":1,"./Grammar":6,"./Utils":26}],26:[function(require,module,exports){
- var Utils = {};
- module.exports = Utils;
- /**
- * Dependencies.
- */
- var JsSIP_C = require('./Constants');
- var URI = require('./URI');
- var Grammar = require('./Grammar');
- Utils.str_utf8_length = function(string) {
- return unescape(encodeURIComponent(string)).length;
- };
- Utils.isFunction = function(fn) {
- if (fn !== undefined) {
- return (Object.prototype.toString.call(fn) === '[object Function]')? true : false;
- } else {
- return false;
- }
- };
- Utils.isString = function(str) {
- if (str !== undefined) {
- return (Object.prototype.toString.call(str) === '[object String]')? true : false;
- } else {
- return false;
- }
- };
- Utils.isDecimal = function(num) {
- return !isNaN(num) && (parseFloat(num) === parseInt(num,10));
- };
- Utils.isEmpty = function(value) {
- if (value === null || value === '' || value === undefined || (Array.isArray(value) && value.length === 0) || (typeof(value) === 'number' && isNaN(value))) {
- return true;
- }
- };
- Utils.hasMethods = function(obj /*, method list as strings */){
- var i = 1, methodName;
- while((methodName = arguments[i++])){
- if(this.isFunction(obj[methodName])) {
- return false;
- }
- }
- return true;
- };
- Utils.createRandomToken = function(size, base) {
- var i, r,
- token = '';
- base = base || 32;
- for( i=0; i < size; i++ ) {
- r = Math.random() * base|0;
- token += r.toString(base);
- }
- return token;
- };
- Utils.newTag = function() {
- return Utils.createRandomToken(10);
- };
- // http://stackoverflow.com/users/109538/broofa
- Utils.newUUID = function() {
- var UUID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
- return v.toString(16);
- });
- return UUID;
- };
- Utils.hostType = function(host) {
- if (!host) {
- return;
- } else {
- host = Grammar.parse(host,'host');
- if (host !== -1) {
- return host.host_type;
- }
- }
- };
- /**
- * Normalize SIP URI.
- * NOTE: It does not allow a SIP URI without username.
- * Accepts 'sip', 'sips' and 'tel' URIs and convert them into 'sip'.
- * Detects the domain part (if given) and properly hex-escapes the user portion.
- * If the user portion has only 'tel' number symbols the user portion is clean of 'tel' visual separators.
- */
- Utils.normalizeTarget = function(target, domain) {
- var uri, target_array, target_user, target_domain;
- // If no target is given then raise an error.
- if (!target) {
- return;
- // If a URI instance is given then return it.
- } else if (target instanceof URI) {
- return target;
- // If a string is given split it by '@':
- // - Last fragment is the desired domain.
- // - Otherwise append the given domain argument.
- } else if (typeof target === 'string') {
- target_array = target.split('@');
- switch(target_array.length) {
- case 1:
- if (!domain) {
- return;
- }
- target_user = target;
- target_domain = domain;
- break;
- case 2:
- target_user = target_array[0];
- target_domain = target_array[1];
- break;
- default:
- target_user = target_array.slice(0, target_array.length-1).join('@');
- target_domain = target_array[target_array.length-1];
- }
- // Remove the URI scheme (if present).
- target_user = target_user.replace(/^(sips?|tel):/i, '');
- // Remove 'tel' visual separators if the user portion just contains 'tel' number symbols.
- if (/^[\-\.\(\)]*\+?[0-9\-\.\(\)]+$/.test(target_user)) {
- target_user = target_user.replace(/[\-\.\(\)]/g, '');
- }
- // Build the complete SIP URI.
- target = JsSIP_C.SIP + ':' + Utils.escapeUser(target_user) + '@' + target_domain;
- // Finally parse the resulting URI.
- if ((uri = URI.parse(target))) {
- return uri;
- } else {
- return;
- }
- } else {
- return;
- }
- };
- /**
- * Hex-escape a SIP URI user.
- */
- Utils.escapeUser = function(user) {
- // Don't hex-escape ':' (%3A), '+' (%2B), '?' (%3F"), '/' (%2F).
- return encodeURIComponent(decodeURIComponent(user)).replace(/%3A/ig, ':').replace(/%2B/ig, '+').replace(/%3F/ig, '?').replace(/%2F/ig, '/');
- };
- Utils.headerize = function(string) {
- var exceptions = {
- 'Call-Id': 'Call-ID',
- 'Cseq': 'CSeq',
- 'Www-Authenticate': 'WWW-Authenticate'
- },
- name = string.toLowerCase().replace(/_/g,'-').split('-'),
- hname = '',
- parts = name.length, part;
- for (part = 0; part < parts; part++) {
- if (part !== 0) {
- hname +='-';
- }
- hname += name[part].charAt(0).toUpperCase()+name[part].substring(1);
- }
- if (exceptions[hname]) {
- hname = exceptions[hname];
- }
- return hname;
- };
- Utils.sipErrorCause = function(status_code) {
- var cause;
- for (cause in JsSIP_C.SIP_ERROR_CAUSES) {
- if (JsSIP_C.SIP_ERROR_CAUSES[cause].indexOf(status_code) !== -1) {
- return JsSIP_C.causes[cause];
- }
- }
- return JsSIP_C.causes.SIP_FAILURE_CODE;
- };
- /**
- * Generate a random Test-Net IP (http://tools.ietf.org/html/rfc5735)
- */
- Utils.getRandomTestNetIP = function() {
- function getOctet(from,to) {
- return Math.floor(Math.random()*(to-from+1)+from);
- }
- return '192.0.2.' + getOctet(1, 254);
- };
- // MD5 (Message-Digest Algorithm) http://www.webtoolkit.info
- Utils.calculateMD5 = function(string) {
- function rotateLeft(lValue, iShiftBits) {
- return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
- }
- function addUnsigned(lX,lY) {
- var lX4,lY4,lX8,lY8,lResult;
- lX8 = (lX & 0x80000000);
- lY8 = (lY & 0x80000000);
- lX4 = (lX & 0x40000000);
- lY4 = (lY & 0x40000000);
- lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
- if (lX4 & lY4) {
- return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
- }
- if (lX4 | lY4) {
- if (lResult & 0x40000000) {
- return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
- } else {
- return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
- }
- } else {
- return (lResult ^ lX8 ^ lY8);
- }
- }
- function doF(x,y,z) {
- return (x & y) | ((~x) & z);
- }
- function doG(x,y,z) {
- return (x & z) | (y & (~z));
- }
- function doH(x,y,z) {
- return (x ^ y ^ z);
- }
- function doI(x,y,z) {
- return (y ^ (x | (~z)));
- }
- function doFF(a,b,c,d,x,s,ac) {
- a = addUnsigned(a, addUnsigned(addUnsigned(doF(b, c, d), x), ac));
- return addUnsigned(rotateLeft(a, s), b);
- }
- function doGG(a,b,c,d,x,s,ac) {
- a = addUnsigned(a, addUnsigned(addUnsigned(doG(b, c, d), x), ac));
- return addUnsigned(rotateLeft(a, s), b);
- }
- function doHH(a,b,c,d,x,s,ac) {
- a = addUnsigned(a, addUnsigned(addUnsigned(doH(b, c, d), x), ac));
- return addUnsigned(rotateLeft(a, s), b);
- }
- function doII(a,b,c,d,x,s,ac) {
- a = addUnsigned(a, addUnsigned(addUnsigned(doI(b, c, d), x), ac));
- return addUnsigned(rotateLeft(a, s), b);
- }
- function convertToWordArray(string) {
- var lWordCount;
- var lMessageLength = string.length;
- var lNumberOfWords_temp1=lMessageLength + 8;
- var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
- var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
- var lWordArray = new Array(lNumberOfWords-1);
- var lBytePosition = 0;
- var lByteCount = 0;
- while ( lByteCount < lMessageLength ) {
- lWordCount = (lByteCount-(lByteCount % 4))/4;
- lBytePosition = (lByteCount % 4)*8;
- lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
- lByteCount++;
- }
- lWordCount = (lByteCount-(lByteCount % 4))/4;
- lBytePosition = (lByteCount % 4)*8;
- lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
- lWordArray[lNumberOfWords-2] = lMessageLength<<3;
- lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
- return lWordArray;
- }
- function wordToHex(lValue) {
- var wordToHexValue='',wordToHexValue_temp='',lByte,lCount;
- for (lCount = 0;lCount<=3;lCount++) {
- lByte = (lValue>>>(lCount*8)) & 255;
- wordToHexValue_temp = '0' + lByte.toString(16);
- wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length-2,2);
- }
- return wordToHexValue;
- }
- function utf8Encode(string) {
- string = string.replace(/\r\n/g, '\n');
- var utftext = '';
- for (var n = 0; n < string.length; n++) {
- var c = string.charCodeAt(n);
- if (c < 128) {
- utftext += String.fromCharCode(c);
- }
- else if((c > 127) && (c < 2048)) {
- utftext += String.fromCharCode((c >> 6) | 192);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- else {
- utftext += String.fromCharCode((c >> 12) | 224);
- utftext += String.fromCharCode(((c >> 6) & 63) | 128);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- }
- return utftext;
- }
- var x=[];
- var k,AA,BB,CC,DD,a,b,c,d;
- var S11=7, S12=12, S13=17, S14=22;
- var S21=5, S22=9 , S23=14, S24=20;
- var S31=4, S32=11, S33=16, S34=23;
- var S41=6, S42=10, S43=15, S44=21;
- string = utf8Encode(string);
- x = convertToWordArray(string);
- a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
- for (k=0;k<x.length;k+=16) {
- AA=a; BB=b; CC=c; DD=d;
- a=doFF(a,b,c,d,x[k+0], S11,0xD76AA478);
- d=doFF(d,a,b,c,x[k+1], S12,0xE8C7B756);
- c=doFF(c,d,a,b,x[k+2], S13,0x242070DB);
- b=doFF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
- a=doFF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
- d=doFF(d,a,b,c,x[k+5], S12,0x4787C62A);
- c=doFF(c,d,a,b,x[k+6], S13,0xA8304613);
- b=doFF(b,c,d,a,x[k+7], S14,0xFD469501);
- a=doFF(a,b,c,d,x[k+8], S11,0x698098D8);
- d=doFF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
- c=doFF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
- b=doFF(b,c,d,a,x[k+11],S14,0x895CD7BE);
- a=doFF(a,b,c,d,x[k+12],S11,0x6B901122);
- d=doFF(d,a,b,c,x[k+13],S12,0xFD987193);
- c=doFF(c,d,a,b,x[k+14],S13,0xA679438E);
- b=doFF(b,c,d,a,x[k+15],S14,0x49B40821);
- a=doGG(a,b,c,d,x[k+1], S21,0xF61E2562);
- d=doGG(d,a,b,c,x[k+6], S22,0xC040B340);
- c=doGG(c,d,a,b,x[k+11],S23,0x265E5A51);
- b=doGG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
- a=doGG(a,b,c,d,x[k+5], S21,0xD62F105D);
- d=doGG(d,a,b,c,x[k+10],S22,0x2441453);
- c=doGG(c,d,a,b,x[k+15],S23,0xD8A1E681);
- b=doGG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
- a=doGG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
- d=doGG(d,a,b,c,x[k+14],S22,0xC33707D6);
- c=doGG(c,d,a,b,x[k+3], S23,0xF4D50D87);
- b=doGG(b,c,d,a,x[k+8], S24,0x455A14ED);
- a=doGG(a,b,c,d,x[k+13],S21,0xA9E3E905);
- d=doGG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
- c=doGG(c,d,a,b,x[k+7], S23,0x676F02D9);
- b=doGG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
- a=doHH(a,b,c,d,x[k+5], S31,0xFFFA3942);
- d=doHH(d,a,b,c,x[k+8], S32,0x8771F681);
- c=doHH(c,d,a,b,x[k+11],S33,0x6D9D6122);
- b=doHH(b,c,d,a,x[k+14],S34,0xFDE5380C);
- a=doHH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
- d=doHH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
- c=doHH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
- b=doHH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
- a=doHH(a,b,c,d,x[k+13],S31,0x289B7EC6);
- d=doHH(d,a,b,c,x[k+0], S32,0xEAA127FA);
- c=doHH(c,d,a,b,x[k+3], S33,0xD4EF3085);
- b=doHH(b,c,d,a,x[k+6], S34,0x4881D05);
- a=doHH(a,b,c,d,x[k+9], S31,0xD9D4D039);
- d=doHH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
- c=doHH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
- b=doHH(b,c,d,a,x[k+2], S34,0xC4AC5665);
- a=doII(a,b,c,d,x[k+0], S41,0xF4292244);
- d=doII(d,a,b,c,x[k+7], S42,0x432AFF97);
- c=doII(c,d,a,b,x[k+14],S43,0xAB9423A7);
- b=doII(b,c,d,a,x[k+5], S44,0xFC93A039);
- a=doII(a,b,c,d,x[k+12],S41,0x655B59C3);
- d=doII(d,a,b,c,x[k+3], S42,0x8F0CCC92);
- c=doII(c,d,a,b,x[k+10],S43,0xFFEFF47D);
- b=doII(b,c,d,a,x[k+1], S44,0x85845DD1);
- a=doII(a,b,c,d,x[k+8], S41,0x6FA87E4F);
- d=doII(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
- c=doII(c,d,a,b,x[k+6], S43,0xA3014314);
- b=doII(b,c,d,a,x[k+13],S44,0x4E0811A1);
- a=doII(a,b,c,d,x[k+4], S41,0xF7537E82);
- d=doII(d,a,b,c,x[k+11],S42,0xBD3AF235);
- c=doII(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
- b=doII(b,c,d,a,x[k+9], S44,0xEB86D391);
- a=addUnsigned(a,AA);
- b=addUnsigned(b,BB);
- c=addUnsigned(c,CC);
- d=addUnsigned(d,DD);
- }
- var temp = wordToHex(a)+wordToHex(b)+wordToHex(c)+wordToHex(d);
- return temp.toLowerCase();
- };
- Utils.closeMediaStream = function(stream) {
- if (!stream) {
- return;
- }
- // Latest spec states that MediaStream has no stop() method and instead must
- // call stop() on every MediaStreamTrack.
- try {
- var tracks, i, len;
- if (stream.getTracks) {
- tracks = stream.getTracks();
- for (i = 0, len = tracks.length; i < len; i += 1) {
- tracks[i].stop();
- }
- } else {
- tracks = stream.getAudioTracks();
- for (i = 0, len = tracks.length; i < len; i += 1) {
- tracks[i].stop();
- }
- tracks = stream.getVideoTracks();
- for (i = 0, len = tracks.length; i < len; i += 1) {
- tracks[i].stop();
- }
- }
- } catch (error) {
- // Deprecated by the spec, but still in use.
- // NOTE: In Temasys IE plugin stream.stop is a callable 'object'.
- if (typeof stream.stop === 'function' || typeof stream.stop === 'object') {
- stream.stop();
- }
- }
- };
- },{"./Constants":1,"./Grammar":6,"./URI":25}],27:[function(require,module,exports){
- module.exports = WebSocketInterface;
- /**
- * Dependencies.
- */
- var Grammar = require('./Grammar');
- var debug = require('debug')('JsSIP:WebSocketInterface');
- var debugerror = require('debug')('JsSIP:ERROR:WebSocketInterface');
- debugerror.log = console.warn.bind(console);
- function WebSocketInterface(url) {
- debug('new() [url:"%s"]', url);
- var sip_uri = null;
- var via_transport = null;
- this.ws = null;
- // setting the 'scheme' alters the sip_uri too (used in SIP Route header field)
- Object.defineProperties(this, {
- via_transport: {
- get: function() { return via_transport; },
- set: function(transport) {
- via_transport = transport.toUpperCase();
- }
- },
- sip_uri: { get: function() { return sip_uri; }},
- url: { get: function() { return url; }}
- });
- var parsed_url = Grammar.parse(url, 'absoluteURI');
- if (parsed_url === -1) {
- debugerror('invalid WebSocket URI: ' + url);
- throw new TypeError('Invalid argument: ' + url);
- } else if(parsed_url.scheme !== 'wss' && parsed_url.scheme !== 'ws') {
- debugerror('invalid WebSocket URI scheme: ' + parsed_url.scheme);
- throw new TypeError('Invalid argument: ' + url);
- } else {
- sip_uri = 'sip:' + parsed_url.host +
- (parsed_url.port ? ':' + parsed_url.port : '') + ';transport=ws';
- this.via_transport = parsed_url.scheme;
- }
- }
- WebSocketInterface.prototype.connect = function () {
- debug('connect()');
- if (this.isConnected()) {
- debug('WebSocket ' + this.url + ' is already connected');
- return;
- } else if (this.isConnecting()) {
- debug('WebSocket ' + this.url + ' is connecting');
- return;
- }
- if (this.ws) {
- this.disconnect();
- }
- debug('connecting to WebSocket ' + this.url);
- try {
- this.ws = new WebSocket(this.url, 'sip');
- this.ws.binaryType = 'arraybuffer';
- this.ws.onopen = onOpen.bind(this);
- this.ws.onclose = onClose.bind(this);
- this.ws.onmessage = onMessage.bind(this);
- this.ws.onerror = onError.bind(this);
- } catch(e) {
- onError.call(this, e);
- }
- };
- WebSocketInterface.prototype.disconnect = function() {
- debug('disconnect()');
- if (this.ws) {
- // unbind websocket event callbacks
- this.ws.onopen = function() {};
- this.ws.onclose = function() {};
- this.ws.onmessage = function() {};
- this.ws.onerror = function() {};
- this.ws.close();
- this.ws = null;
- }
- };
- WebSocketInterface.prototype.send = function(message) {
- debug('send()');
- if (this.isConnected()) {
- this.ws.send(message);
- return true;
- } else {
- debugerror('unable to send message, WebSocket is not open');
- return false;
- }
- };
- WebSocketInterface.prototype.isConnected = function() {
- return this.ws && this.ws.readyState === this.ws.OPEN;
- };
- WebSocketInterface.prototype.isConnecting = function() {
- return this.ws && this.ws.readyState === this.ws.CONNECTING;
- };
- /**
- * WebSocket Event Handlers
- */
- function onOpen() {
- debug('WebSocket ' + this.url + ' connected');
- this.onconnect();
- }
- function onClose(e) {
- debug('WebSocket ' + this.url + ' closed');
- if (e.wasClean === false) {
- debug('WebSocket abrupt disconnection');
- }
- var data = {
- socket: this,
- error: !e.wasClean,
- code: e.code,
- reason: e.reason
- };
- this.ondisconnect(data);
- }
- function onMessage(e) {
- debug('received WebSocket message');
- this.ondata(e.data);
- }
- function onError(e) {
- debugerror('WebSocket ' + this.url + ' error: '+ e);
- }
- },{"./Grammar":6,"debug":35}],28:[function(require,module,exports){
- module.exports = sanityCheck;
- /**
- * Dependencies.
- */
- var debug = require('debug')('JsSIP:sanityCheck');
- var JsSIP_C = require('./Constants');
- var SIPMessage = require('./SIPMessage');
- var Utils = require('./Utils');
- var message, ua, transport,
- requests = [],
- responses = [],
- all = [];
- requests.push(rfc3261_8_2_2_1);
- requests.push(rfc3261_16_3_4);
- requests.push(rfc3261_18_3_request);
- requests.push(rfc3261_8_2_2_2);
- responses.push(rfc3261_8_1_3_3);
- responses.push(rfc3261_18_3_response);
- all.push(minimumHeaders);
- function sanityCheck(m, u, t) {
- var len, pass;
- message = m;
- ua = u;
- transport = t;
- len = all.length;
- while(len--) {
- pass = all[len](message);
- if(pass === false) {
- return false;
- }
- }
- if(message instanceof SIPMessage.IncomingRequest) {
- len = requests.length;
- while(len--) {
- pass = requests[len](message);
- if(pass === false) {
- return false;
- }
- }
- }
- else if(message instanceof SIPMessage.IncomingResponse) {
- len = responses.length;
- while(len--) {
- pass = responses[len](message);
- if(pass === false) {
- return false;
- }
- }
- }
- //Everything is OK
- return true;
- }
- /*
- * Sanity Check for incoming Messages
- *
- * Requests:
- * - _rfc3261_8_2_2_1_ Receive a Request with a non supported URI scheme
- * - _rfc3261_16_3_4_ Receive a Request already sent by us
- * Does not look at via sent-by but at jssip_id, which is inserted as
- * a prefix in all initial requests generated by the ua
- * - _rfc3261_18_3_request_ Body Content-Length
- * - _rfc3261_8_2_2_2_ Merged Requests
- *
- * Responses:
- * - _rfc3261_8_1_3_3_ Multiple Via headers
- * - _rfc3261_18_3_response_ Body Content-Length
- *
- * All:
- * - Minimum headers in a SIP message
- */
- // Sanity Check functions for requests
- function rfc3261_8_2_2_1() {
- if(message.s('to').uri.scheme !== 'sip') {
- reply(416);
- return false;
- }
- }
- function rfc3261_16_3_4() {
- if(!message.to_tag) {
- if(message.call_id.substr(0, 5) === ua.configuration.jssip_id) {
- reply(482);
- return false;
- }
- }
- }
- function rfc3261_18_3_request() {
- var len = Utils.str_utf8_length(message.body),
- contentLength = message.getHeader('content-length');
- if(len < contentLength) {
- reply(400);
- return false;
- }
- }
- function rfc3261_8_2_2_2() {
- var tr, idx,
- fromTag = message.from_tag,
- call_id = message.call_id,
- cseq = message.cseq;
- // Accept any in-dialog request.
- if(message.to_tag) {
- return;
- }
- // INVITE request.
- if (message.method === JsSIP_C.INVITE) {
- // If the branch matches the key of any IST then assume it is a retransmission
- // and ignore the INVITE.
- // TODO: we should reply the last response.
- if (ua.transactions.ist[message.via_branch]) {
- return false;
- }
- // Otherwise check whether it is a merged request.
- else {
- for(idx in ua.transactions.ist) {
- tr = ua.transactions.ist[idx];
- if(tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
- reply(482);
- return false;
- }
- }
- }
- }
- // Non INVITE request.
- else {
- // If the branch matches the key of any NIST then assume it is a retransmission
- // and ignore the request.
- // TODO: we should reply the last response.
- if (ua.transactions.nist[message.via_branch]) {
- return false;
- }
- // Otherwise check whether it is a merged request.
- else {
- for(idx in ua.transactions.nist) {
- tr = ua.transactions.nist[idx];
- if(tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
- reply(482);
- return false;
- }
- }
- }
- }
- }
- // Sanity Check functions for responses
- function rfc3261_8_1_3_3() {
- if(message.getHeaders('via').length > 1) {
- debug('more than one Via header field present in the response, dropping the response');
- return false;
- }
- }
- function rfc3261_18_3_response() {
- var
- len = Utils.str_utf8_length(message.body),
- contentLength = message.getHeader('content-length');
- if(len < contentLength) {
- debug('message body length is lower than the value in Content-Length header field, dropping the response');
- return false;
- }
- }
- // Sanity Check functions for requests and responses
- function minimumHeaders() {
- var
- mandatoryHeaders = ['from', 'to', 'call_id', 'cseq', 'via'],
- idx = mandatoryHeaders.length;
- while(idx--) {
- if(!message.hasHeader(mandatoryHeaders[idx])) {
- debug('missing mandatory header field : ' + mandatoryHeaders[idx] + ', dropping the response');
- return false;
- }
- }
- }
- // Reply
- function reply(status_code) {
- var to,
- response = 'SIP/2.0 ' + status_code + ' ' + JsSIP_C.REASON_PHRASE[status_code] + '\r\n',
- vias = message.getHeaders('via'),
- length = vias.length,
- idx = 0;
- for(idx; idx < length; idx++) {
- response += 'Via: ' + vias[idx] + '\r\n';
- }
- to = message.getHeader('To');
- if(!message.to_tag) {
- to += ';tag=' + Utils.newTag();
- }
- response += 'To: ' + to + '\r\n';
- response += 'From: ' + message.getHeader('From') + '\r\n';
- response += 'Call-ID: ' + message.call_id + '\r\n';
- response += 'CSeq: ' + message.cseq + ' ' + message.method + '\r\n';
- response += '\r\n';
- transport.send(response);
- }
- },{"./Constants":1,"./SIPMessage":19,"./Utils":26,"debug":35}],29:[function(require,module,exports){
- // Copyright Joyent, Inc. and other Node contributors.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to permit
- // persons to whom the Software is furnished to do so, subject to the
- // following conditions:
- //
- // The above copyright notice and this permission notice shall be included
- // in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
- function EventEmitter() {
- this._events = this._events || {};
- this._maxListeners = this._maxListeners || undefined;
- }
- module.exports = EventEmitter;
- // Backwards-compat with node 0.10.x
- EventEmitter.EventEmitter = EventEmitter;
- EventEmitter.prototype._events = undefined;
- EventEmitter.prototype._maxListeners = undefined;
- // By default EventEmitters will print a warning if more than 10 listeners are
- // added to it. This is a useful default which helps finding memory leaks.
- EventEmitter.defaultMaxListeners = 10;
- // Obviously not all Emitters should be limited to 10. This function allows
- // that to be increased. Set to zero for unlimited.
- EventEmitter.prototype.setMaxListeners = function(n) {
- if (!isNumber(n) || n < 0 || isNaN(n))
- throw TypeError('n must be a positive number');
- this._maxListeners = n;
- return this;
- };
- EventEmitter.prototype.emit = function(type) {
- var er, handler, len, args, i, listeners;
- if (!this._events)
- this._events = {};
- // If there is no 'error' event listener then throw.
- if (type === 'error') {
- if (!this._events.error ||
- (isObject(this._events.error) && !this._events.error.length)) {
- er = arguments[1];
- if (er instanceof Error) {
- throw er; // Unhandled 'error' event
- } else {
- // At least give some kind of context to the user
- var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
- err.context = er;
- throw err;
- }
- }
- }
- handler = this._events[type];
- if (isUndefined(handler))
- return false;
- if (isFunction(handler)) {
- switch (arguments.length) {
- // fast cases
- case 1:
- handler.call(this);
- break;
- case 2:
- handler.call(this, arguments[1]);
- break;
- case 3:
- handler.call(this, arguments[1], arguments[2]);
- break;
- // slower
- default:
- args = Array.prototype.slice.call(arguments, 1);
- handler.apply(this, args);
- }
- } else if (isObject(handler)) {
- args = Array.prototype.slice.call(arguments, 1);
- listeners = handler.slice();
- len = listeners.length;
- for (i = 0; i < len; i++)
- listeners[i].apply(this, args);
- }
- return true;
- };
- EventEmitter.prototype.addListener = function(type, listener) {
- var m;
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
- if (!this._events)
- this._events = {};
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (this._events.newListener)
- this.emit('newListener', type,
- isFunction(listener.listener) ?
- listener.listener : listener);
- if (!this._events[type])
- // Optimize the case of one listener. Don't need the extra array object.
- this._events[type] = listener;
- else if (isObject(this._events[type]))
- // If we've already got an array, just append.
- this._events[type].push(listener);
- else
- // Adding the second element, need to change to array.
- this._events[type] = [this._events[type], listener];
- // Check for listener leak
- if (isObject(this._events[type]) && !this._events[type].warned) {
- if (!isUndefined(this._maxListeners)) {
- m = this._maxListeners;
- } else {
- m = EventEmitter.defaultMaxListeners;
- }
- if (m && m > 0 && this._events[type].length > m) {
- this._events[type].warned = true;
- console.error('(node) warning: possible EventEmitter memory ' +
- 'leak detected. %d listeners added. ' +
- 'Use emitter.setMaxListeners() to increase limit.',
- this._events[type].length);
- if (typeof console.trace === 'function') {
- // not supported in IE 10
- console.trace();
- }
- }
- }
- return this;
- };
- EventEmitter.prototype.on = EventEmitter.prototype.addListener;
- EventEmitter.prototype.once = function(type, listener) {
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
- var fired = false;
- function g() {
- this.removeListener(type, g);
- if (!fired) {
- fired = true;
- listener.apply(this, arguments);
- }
- }
- g.listener = listener;
- this.on(type, g);
- return this;
- };
- // emits a 'removeListener' event iff the listener was removed
- EventEmitter.prototype.removeListener = function(type, listener) {
- var list, position, length, i;
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
- if (!this._events || !this._events[type])
- return this;
- list = this._events[type];
- length = list.length;
- position = -1;
- if (list === listener ||
- (isFunction(list.listener) && list.listener === listener)) {
- delete this._events[type];
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
- } else if (isObject(list)) {
- for (i = length; i-- > 0;) {
- if (list[i] === listener ||
- (list[i].listener && list[i].listener === listener)) {
- position = i;
- break;
- }
- }
- if (position < 0)
- return this;
- if (list.length === 1) {
- list.length = 0;
- delete this._events[type];
- } else {
- list.splice(position, 1);
- }
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
- }
- return this;
- };
- EventEmitter.prototype.removeAllListeners = function(type) {
- var key, listeners;
- if (!this._events)
- return this;
- // not listening for removeListener, no need to emit
- if (!this._events.removeListener) {
- if (arguments.length === 0)
- this._events = {};
- else if (this._events[type])
- delete this._events[type];
- return this;
- }
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- for (key in this._events) {
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = {};
- return this;
- }
- listeners = this._events[type];
- if (isFunction(listeners)) {
- this.removeListener(type, listeners);
- } else if (listeners) {
- // LIFO order
- while (listeners.length)
- this.removeListener(type, listeners[listeners.length - 1]);
- }
- delete this._events[type];
- return this;
- };
- EventEmitter.prototype.listeners = function(type) {
- var ret;
- if (!this._events || !this._events[type])
- ret = [];
- else if (isFunction(this._events[type]))
- ret = [this._events[type]];
- else
- ret = this._events[type].slice();
- return ret;
- };
- EventEmitter.prototype.listenerCount = function(type) {
- if (this._events) {
- var evlistener = this._events[type];
- if (isFunction(evlistener))
- return 1;
- else if (evlistener)
- return evlistener.length;
- }
- return 0;
- };
- EventEmitter.listenerCount = function(emitter, type) {
- return emitter.listenerCount(type);
- };
- function isFunction(arg) {
- return typeof arg === 'function';
- }
- function isNumber(arg) {
- return typeof arg === 'number';
- }
- function isObject(arg) {
- return typeof arg === 'object' && arg !== null;
- }
- function isUndefined(arg) {
- return arg === void 0;
- }
- },{}],30:[function(require,module,exports){
- // shim for using process in browser
- var process = module.exports = {};
- // cached from whatever global is present so that test runners that stub it
- // don't break things. But we need to wrap it in a try catch in case it is
- // wrapped in strict mode code which doesn't define any globals. It's inside a
- // function because try/catches deoptimize in certain engines.
- var cachedSetTimeout;
- var cachedClearTimeout;
- function defaultSetTimout() {
- throw new Error('setTimeout has not been defined');
- }
- function defaultClearTimeout () {
- throw new Error('clearTimeout has not been defined');
- }
- (function () {
- try {
- if (typeof setTimeout === 'function') {
- cachedSetTimeout = setTimeout;
- } else {
- cachedSetTimeout = defaultSetTimout;
- }
- } catch (e) {
- cachedSetTimeout = defaultSetTimout;
- }
- try {
- if (typeof clearTimeout === 'function') {
- cachedClearTimeout = clearTimeout;
- } else {
- cachedClearTimeout = defaultClearTimeout;
- }
- } catch (e) {
- cachedClearTimeout = defaultClearTimeout;
- }
- } ())
- function runTimeout(fun) {
- if (cachedSetTimeout === setTimeout) {
- //normal enviroments in sane situations
- return setTimeout(fun, 0);
- }
- // if setTimeout wasn't available but was latter defined
- if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
- cachedSetTimeout = setTimeout;
- return setTimeout(fun, 0);
- }
- try {
- // when when somebody has screwed with setTimeout but no I.E. maddness
- return cachedSetTimeout(fun, 0);
- } catch(e){
- try {
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
- return cachedSetTimeout.call(null, fun, 0);
- } catch(e){
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
- return cachedSetTimeout.call(this, fun, 0);
- }
- }
- }
- function runClearTimeout(marker) {
- if (cachedClearTimeout === clearTimeout) {
- //normal enviroments in sane situations
- return clearTimeout(marker);
- }
- // if clearTimeout wasn't available but was latter defined
- if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
- cachedClearTimeout = clearTimeout;
- return clearTimeout(marker);
- }
- try {
- // when when somebody has screwed with setTimeout but no I.E. maddness
- return cachedClearTimeout(marker);
- } catch (e){
- try {
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
- return cachedClearTimeout.call(null, marker);
- } catch (e){
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
- // Some versions of I.E. have different rules for clearTimeout vs setTimeout
- return cachedClearTimeout.call(this, marker);
- }
- }
- }
- var queue = [];
- var draining = false;
- var currentQueue;
- var queueIndex = -1;
- function cleanUpNextTick() {
- if (!draining || !currentQueue) {
- return;
- }
- draining = false;
- if (currentQueue.length) {
- queue = currentQueue.concat(queue);
- } else {
- queueIndex = -1;
- }
- if (queue.length) {
- drainQueue();
- }
- }
- function drainQueue() {
- if (draining) {
- return;
- }
- var timeout = runTimeout(cleanUpNextTick);
- draining = true;
- var len = queue.length;
- while(len) {
- currentQueue = queue;
- queue = [];
- while (++queueIndex < len) {
- if (currentQueue) {
- currentQueue[queueIndex].run();
- }
- }
- queueIndex = -1;
- len = queue.length;
- }
- currentQueue = null;
- draining = false;
- runClearTimeout(timeout);
- }
- process.nextTick = function (fun) {
- var args = new Array(arguments.length - 1);
- if (arguments.length > 1) {
- for (var i = 1; i < arguments.length; i++) {
- args[i - 1] = arguments[i];
- }
- }
- queue.push(new Item(fun, args));
- if (queue.length === 1 && !draining) {
- runTimeout(drainQueue);
- }
- };
- // v8 likes predictible objects
- function Item(fun, array) {
- this.fun = fun;
- this.array = array;
- }
- Item.prototype.run = function () {
- this.fun.apply(null, this.array);
- };
- process.title = 'browser';
- process.browser = true;
- process.env = {};
- process.argv = [];
- process.version = ''; // empty string to avoid regexp issues
- process.versions = {};
- function noop() {}
- process.on = noop;
- process.addListener = noop;
- process.once = noop;
- process.off = noop;
- process.removeListener = noop;
- process.removeAllListeners = noop;
- process.emit = noop;
- process.binding = function (name) {
- throw new Error('process.binding is not supported');
- };
- process.cwd = function () { return '/' };
- process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
- };
- process.umask = function() { return 0; };
- },{}],31:[function(require,module,exports){
- if (typeof Object.create === 'function') {
- // implementation from standard node.js 'util' module
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- };
- } else {
- // old school shim for old browsers
- module.exports = function inherits(ctor, superCtor) {
- ctor.super_ = superCtor
- var TempCtor = function () {}
- TempCtor.prototype = superCtor.prototype
- ctor.prototype = new TempCtor()
- ctor.prototype.constructor = ctor
- }
- }
- },{}],32:[function(require,module,exports){
- module.exports = function isBuffer(arg) {
- return arg && typeof arg === 'object'
- && typeof arg.copy === 'function'
- && typeof arg.fill === 'function'
- && typeof arg.readUInt8 === 'function';
- }
- },{}],33:[function(require,module,exports){
- (function (process,global){
- // Copyright Joyent, Inc. and other Node contributors.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to permit
- // persons to whom the Software is furnished to do so, subject to the
- // following conditions:
- //
- // The above copyright notice and this permission notice shall be included
- // in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
- var formatRegExp = /%[sdj%]/g;
- exports.format = function(f) {
- if (!isString(f)) {
- var objects = [];
- for (var i = 0; i < arguments.length; i++) {
- objects.push(inspect(arguments[i]));
- }
- return objects.join(' ');
- }
- var i = 1;
- var args = arguments;
- var len = args.length;
- var str = String(f).replace(formatRegExp, function(x) {
- if (x === '%%') return '%';
- if (i >= len) return x;
- switch (x) {
- case '%s': return String(args[i++]);
- case '%d': return Number(args[i++]);
- case '%j':
- try {
- return JSON.stringify(args[i++]);
- } catch (_) {
- return '[Circular]';
- }
- default:
- return x;
- }
- });
- for (var x = args[i]; i < len; x = args[++i]) {
- if (isNull(x) || !isObject(x)) {
- str += ' ' + x;
- } else {
- str += ' ' + inspect(x);
- }
- }
- return str;
- };
- // Mark that a method should not be used.
- // Returns a modified function which warns once by default.
- // If --no-deprecation is set, then it is a no-op.
- exports.deprecate = function(fn, msg) {
- // Allow for deprecating things in the process of starting up.
- if (isUndefined(global.process)) {
- return function() {
- return exports.deprecate(fn, msg).apply(this, arguments);
- };
- }
- if (process.noDeprecation === true) {
- return fn;
- }
- var warned = false;
- function deprecated() {
- if (!warned) {
- if (process.throwDeprecation) {
- throw new Error(msg);
- } else if (process.traceDeprecation) {
- console.trace(msg);
- } else {
- console.error(msg);
- }
- warned = true;
- }
- return fn.apply(this, arguments);
- }
- return deprecated;
- };
- var debugs = {};
- var debugEnviron;
- exports.debuglog = function(set) {
- if (isUndefined(debugEnviron))
- debugEnviron = process.env.NODE_DEBUG || '';
- set = set.toUpperCase();
- if (!debugs[set]) {
- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
- var pid = process.pid;
- debugs[set] = function() {
- var msg = exports.format.apply(exports, arguments);
- console.error('%s %d: %s', set, pid, msg);
- };
- } else {
- debugs[set] = function() {};
- }
- }
- return debugs[set];
- };
- /**
- * Echos the value of a value. Trys to print the value out
- * in the best way possible given the different types.
- *
- * @param {Object} obj The object to print out.
- * @param {Object} opts Optional options object that alters the output.
- */
- /* legacy: obj, showHidden, depth, colors*/
- function inspect(obj, opts) {
- // default options
- var ctx = {
- seen: [],
- stylize: stylizeNoColor
- };
- // legacy...
- if (arguments.length >= 3) ctx.depth = arguments[2];
- if (arguments.length >= 4) ctx.colors = arguments[3];
- if (isBoolean(opts)) {
- // legacy...
- ctx.showHidden = opts;
- } else if (opts) {
- // got an "options" object
- exports._extend(ctx, opts);
- }
- // set default options
- if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
- if (isUndefined(ctx.depth)) ctx.depth = 2;
- if (isUndefined(ctx.colors)) ctx.colors = false;
- if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
- if (ctx.colors) ctx.stylize = stylizeWithColor;
- return formatValue(ctx, obj, ctx.depth);
- }
- exports.inspect = inspect;
- // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
- inspect.colors = {
- 'bold' : [1, 22],
- 'italic' : [3, 23],
- 'underline' : [4, 24],
- 'inverse' : [7, 27],
- 'white' : [37, 39],
- 'grey' : [90, 39],
- 'black' : [30, 39],
- 'blue' : [34, 39],
- 'cyan' : [36, 39],
- 'green' : [32, 39],
- 'magenta' : [35, 39],
- 'red' : [31, 39],
- 'yellow' : [33, 39]
- };
- // Don't use 'blue' not visible on cmd.exe
- inspect.styles = {
- 'special': 'cyan',
- 'number': 'yellow',
- 'boolean': 'yellow',
- 'undefined': 'grey',
- 'null': 'bold',
- 'string': 'green',
- 'date': 'magenta',
- // "name": intentionally not styling
- 'regexp': 'red'
- };
- function stylizeWithColor(str, styleType) {
- var style = inspect.styles[styleType];
- if (style) {
- return '\u001b[' + inspect.colors[style][0] + 'm' + str +
- '\u001b[' + inspect.colors[style][1] + 'm';
- } else {
- return str;
- }
- }
- function stylizeNoColor(str, styleType) {
- return str;
- }
- function arrayToHash(array) {
- var hash = {};
- array.forEach(function(val, idx) {
- hash[val] = true;
- });
- return hash;
- }
- function formatValue(ctx, value, recurseTimes) {
- // Provide a hook for user-specified inspect functions.
- // Check that value is an object with an inspect function on it
- if (ctx.customInspect &&
- value &&
- isFunction(value.inspect) &&
- // Filter out the util module, it's inspect function is special
- value.inspect !== exports.inspect &&
- // Also filter out any prototype objects using the circular check.
- !(value.constructor && value.constructor.prototype === value)) {
- var ret = value.inspect(recurseTimes, ctx);
- if (!isString(ret)) {
- ret = formatValue(ctx, ret, recurseTimes);
- }
- return ret;
- }
- // Primitive types cannot have properties
- var primitive = formatPrimitive(ctx, value);
- if (primitive) {
- return primitive;
- }
- // Look up the keys of the object.
- var keys = Object.keys(value);
- var visibleKeys = arrayToHash(keys);
- if (ctx.showHidden) {
- keys = Object.getOwnPropertyNames(value);
- }
- // IE doesn't make error fields non-enumerable
- // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
- if (isError(value)
- && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
- return formatError(value);
- }
- // Some type of object without properties can be shortcutted.
- if (keys.length === 0) {
- if (isFunction(value)) {
- var name = value.name ? ': ' + value.name : '';
- return ctx.stylize('[Function' + name + ']', 'special');
- }
- if (isRegExp(value)) {
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
- }
- if (isDate(value)) {
- return ctx.stylize(Date.prototype.toString.call(value), 'date');
- }
- if (isError(value)) {
- return formatError(value);
- }
- }
- var base = '', array = false, braces = ['{', '}'];
- // Make Array say that they are Array
- if (isArray(value)) {
- array = true;
- braces = ['[', ']'];
- }
- // Make functions say that they are functions
- if (isFunction(value)) {
- var n = value.name ? ': ' + value.name : '';
- base = ' [Function' + n + ']';
- }
- // Make RegExps say that they are RegExps
- if (isRegExp(value)) {
- base = ' ' + RegExp.prototype.toString.call(value);
- }
- // Make dates with properties first say the date
- if (isDate(value)) {
- base = ' ' + Date.prototype.toUTCString.call(value);
- }
- // Make error with message first say the error
- if (isError(value)) {
- base = ' ' + formatError(value);
- }
- if (keys.length === 0 && (!array || value.length == 0)) {
- return braces[0] + base + braces[1];
- }
- if (recurseTimes < 0) {
- if (isRegExp(value)) {
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
- } else {
- return ctx.stylize('[Object]', 'special');
- }
- }
- ctx.seen.push(value);
- var output;
- if (array) {
- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
- } else {
- output = keys.map(function(key) {
- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
- });
- }
- ctx.seen.pop();
- return reduceToSingleString(output, base, braces);
- }
- function formatPrimitive(ctx, value) {
- if (isUndefined(value))
- return ctx.stylize('undefined', 'undefined');
- if (isString(value)) {
- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
- .replace(/'/g, "\\'")
- .replace(/\\"/g, '"') + '\'';
- return ctx.stylize(simple, 'string');
- }
- if (isNumber(value))
- return ctx.stylize('' + value, 'number');
- if (isBoolean(value))
- return ctx.stylize('' + value, 'boolean');
- // For some reason typeof null is "object", so special case here.
- if (isNull(value))
- return ctx.stylize('null', 'null');
- }
- function formatError(value) {
- return '[' + Error.prototype.toString.call(value) + ']';
- }
- function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
- var output = [];
- for (var i = 0, l = value.length; i < l; ++i) {
- if (hasOwnProperty(value, String(i))) {
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
- String(i), true));
- } else {
- output.push('');
- }
- }
- keys.forEach(function(key) {
- if (!key.match(/^\d+$/)) {
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
- key, true));
- }
- });
- return output;
- }
- function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
- var name, str, desc;
- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
- if (desc.get) {
- if (desc.set) {
- str = ctx.stylize('[Getter/Setter]', 'special');
- } else {
- str = ctx.stylize('[Getter]', 'special');
- }
- } else {
- if (desc.set) {
- str = ctx.stylize('[Setter]', 'special');
- }
- }
- if (!hasOwnProperty(visibleKeys, key)) {
- name = '[' + key + ']';
- }
- if (!str) {
- if (ctx.seen.indexOf(desc.value) < 0) {
- if (isNull(recurseTimes)) {
- str = formatValue(ctx, desc.value, null);
- } else {
- str = formatValue(ctx, desc.value, recurseTimes - 1);
- }
- if (str.indexOf('\n') > -1) {
- if (array) {
- str = str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n').substr(2);
- } else {
- str = '\n' + str.split('\n').map(function(line) {
- return ' ' + line;
- }).join('\n');
- }
- }
- } else {
- str = ctx.stylize('[Circular]', 'special');
- }
- }
- if (isUndefined(name)) {
- if (array && key.match(/^\d+$/)) {
- return str;
- }
- name = JSON.stringify('' + key);
- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
- name = name.substr(1, name.length - 2);
- name = ctx.stylize(name, 'name');
- } else {
- name = name.replace(/'/g, "\\'")
- .replace(/\\"/g, '"')
- .replace(/(^"|"$)/g, "'");
- name = ctx.stylize(name, 'string');
- }
- }
- return name + ': ' + str;
- }
- function reduceToSingleString(output, base, braces) {
- var numLinesEst = 0;
- var length = output.reduce(function(prev, cur) {
- numLinesEst++;
- if (cur.indexOf('\n') >= 0) numLinesEst++;
- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
- }, 0);
- if (length > 60) {
- return braces[0] +
- (base === '' ? '' : base + '\n ') +
- ' ' +
- output.join(',\n ') +
- ' ' +
- braces[1];
- }
- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
- }
- // NOTE: These type checking functions intentionally don't use `instanceof`
- // because it is fragile and can be easily faked with `Object.create()`.
- function isArray(ar) {
- return Array.isArray(ar);
- }
- exports.isArray = isArray;
- function isBoolean(arg) {
- return typeof arg === 'boolean';
- }
- exports.isBoolean = isBoolean;
- function isNull(arg) {
- return arg === null;
- }
- exports.isNull = isNull;
- function isNullOrUndefined(arg) {
- return arg == null;
- }
- exports.isNullOrUndefined = isNullOrUndefined;
- function isNumber(arg) {
- return typeof arg === 'number';
- }
- exports.isNumber = isNumber;
- function isString(arg) {
- return typeof arg === 'string';
- }
- exports.isString = isString;
- function isSymbol(arg) {
- return typeof arg === 'symbol';
- }
- exports.isSymbol = isSymbol;
- function isUndefined(arg) {
- return arg === void 0;
- }
- exports.isUndefined = isUndefined;
- function isRegExp(re) {
- return isObject(re) && objectToString(re) === '[object RegExp]';
- }
- exports.isRegExp = isRegExp;
- function isObject(arg) {
- return typeof arg === 'object' && arg !== null;
- }
- exports.isObject = isObject;
- function isDate(d) {
- return isObject(d) && objectToString(d) === '[object Date]';
- }
- exports.isDate = isDate;
- function isError(e) {
- return isObject(e) &&
- (objectToString(e) === '[object Error]' || e instanceof Error);
- }
- exports.isError = isError;
- function isFunction(arg) {
- return typeof arg === 'function';
- }
- exports.isFunction = isFunction;
- function isPrimitive(arg) {
- return arg === null ||
- typeof arg === 'boolean' ||
- typeof arg === 'number' ||
- typeof arg === 'string' ||
- typeof arg === 'symbol' || // ES6 symbol
- typeof arg === 'undefined';
- }
- exports.isPrimitive = isPrimitive;
- exports.isBuffer = require('./support/isBuffer');
- function objectToString(o) {
- return Object.prototype.toString.call(o);
- }
- function pad(n) {
- return n < 10 ? '0' + n.toString(10) : n.toString(10);
- }
- var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
- 'Oct', 'Nov', 'Dec'];
- // 26 Feb 16:19:34
- function timestamp() {
- var d = new Date();
- var time = [pad(d.getHours()),
- pad(d.getMinutes()),
- pad(d.getSeconds())].join(':');
- return [d.getDate(), months[d.getMonth()], time].join(' ');
- }
- // log is just a thin wrapper to console.log that prepends a timestamp
- exports.log = function() {
- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
- };
- /**
- * Inherit the prototype methods from one constructor into another.
- *
- * The Function.prototype.inherits from lang.js rewritten as a standalone
- * function (not on Function.prototype). NOTE: If this file is to be loaded
- * during bootstrapping this function needs to be rewritten using some native
- * functions as prototype setup using normal JavaScript does not work as
- * expected during bootstrapping (see mirror.js in r114903).
- *
- * @param {function} ctor Constructor function which needs to inherit the
- * prototype.
- * @param {function} superCtor Constructor function to inherit prototype from.
- */
- exports.inherits = require('inherits');
- exports._extend = function(origin, add) {
- // Don't do anything if add isn't an object
- if (!add || !isObject(add)) return origin;
- var keys = Object.keys(add);
- var i = keys.length;
- while (i--) {
- origin[keys[i]] = add[keys[i]];
- }
- return origin;
- };
- function hasOwnProperty(obj, prop) {
- return Object.prototype.hasOwnProperty.call(obj, prop);
- }
- }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
- },{"./support/isBuffer":32,"_process":30,"inherits":31}],34:[function(require,module,exports){
- /**
- * Helpers.
- */
- var s = 1000
- var m = s * 60
- var h = m * 60
- var d = h * 24
- var y = d * 365.25
- /**
- * Parse or format the given `val`.
- *
- * Options:
- *
- * - `long` verbose formatting [false]
- *
- * @param {String|Number} val
- * @param {Object} options
- * @throws {Error} throw an error if val is not a non-empty string or a number
- * @return {String|Number}
- * @api public
- */
- module.exports = function (val, options) {
- options = options || {}
- var type = typeof val
- if (type === 'string' && val.length > 0) {
- return parse(val)
- } else if (type === 'number' && isNaN(val) === false) {
- return options.long ?
- fmtLong(val) :
- fmtShort(val)
- }
- throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))
- }
- /**
- * Parse the given `str` and return milliseconds.
- *
- * @param {String} str
- * @return {Number}
- * @api private
- */
- function parse(str) {
- str = String(str)
- if (str.length > 10000) {
- return
- }
- var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)
- if (!match) {
- return
- }
- var n = parseFloat(match[1])
- var type = (match[2] || 'ms').toLowerCase()
- switch (type) {
- case 'years':
- case 'year':
- case 'yrs':
- case 'yr':
- case 'y':
- return n * y
- case 'days':
- case 'day':
- case 'd':
- return n * d
- case 'hours':
- case 'hour':
- case 'hrs':
- case 'hr':
- case 'h':
- return n * h
- case 'minutes':
- case 'minute':
- case 'mins':
- case 'min':
- case 'm':
- return n * m
- case 'seconds':
- case 'second':
- case 'secs':
- case 'sec':
- case 's':
- return n * s
- case 'milliseconds':
- case 'millisecond':
- case 'msecs':
- case 'msec':
- case 'ms':
- return n
- default:
- return undefined
- }
- }
- /**
- * Short format for `ms`.
- *
- * @param {Number} ms
- * @return {String}
- * @api private
- */
- function fmtShort(ms) {
- if (ms >= d) {
- return Math.round(ms / d) + 'd'
- }
- if (ms >= h) {
- return Math.round(ms / h) + 'h'
- }
- if (ms >= m) {
- return Math.round(ms / m) + 'm'
- }
- if (ms >= s) {
- return Math.round(ms / s) + 's'
- }
- return ms + 'ms'
- }
- /**
- * Long format for `ms`.
- *
- * @param {Number} ms
- * @return {String}
- * @api private
- */
- function fmtLong(ms) {
- return plural(ms, d, 'day') ||
- plural(ms, h, 'hour') ||
- plural(ms, m, 'minute') ||
- plural(ms, s, 'second') ||
- ms + ' ms'
- }
- /**
- * Pluralization helper.
- */
- function plural(ms, n, name) {
- if (ms < n) {
- return
- }
- if (ms < n * 1.5) {
- return Math.floor(ms / n) + ' ' + name
- }
- return Math.ceil(ms / n) + ' ' + name + 's'
- }
- },{}],35:[function(require,module,exports){
- (function (process){
- /**
- * This is the web browser implementation of `debug()`.
- *
- * Expose `debug()` as the module.
- */
- exports = module.exports = require('./debug');
- exports.log = log;
- exports.formatArgs = formatArgs;
- exports.save = save;
- exports.load = load;
- exports.useColors = useColors;
- exports.storage = 'undefined' != typeof chrome
- && 'undefined' != typeof chrome.storage
- ? chrome.storage.local
- : localstorage();
- /**
- * Colors.
- */
- exports.colors = [
- 'lightseagreen',
- 'forestgreen',
- 'goldenrod',
- 'dodgerblue',
- 'darkorchid',
- 'crimson'
- ];
- /**
- * Currently only WebKit-based Web Inspectors, Firefox >= v31,
- * and the Firebug extension (any Firefox version) are known
- * to support "%c" CSS customizations.
- *
- * TODO: add a `localStorage` variable to explicitly enable/disable colors
- */
- function useColors() {
- // NB: In an Electron preload script, document will be defined but not fully
- // initialized. Since we know we're in Chrome, we'll just detect this case
- // explicitly
- if (typeof window !== 'undefined' && window && typeof window.process !== 'undefined' && window.process.type === 'renderer') {
- return true;
- }
- // is webkit? http://stackoverflow.com/a/16459606/376773
- // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
- return (typeof document !== 'undefined' && document && 'WebkitAppearance' in document.documentElement.style) ||
- // is firebug? http://stackoverflow.com/a/398120/376773
- (typeof window !== 'undefined' && window && window.console && (console.firebug || (console.exception && console.table))) ||
- // is firefox >= v31?
- // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
- (typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
- // double check webkit in userAgent just in case we are in a worker
- (typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
- }
- /**
- * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
- */
- exports.formatters.j = function(v) {
- try {
- return JSON.stringify(v);
- } catch (err) {
- return '[UnexpectedJSONParseError]: ' + err.message;
- }
- };
- /**
- * Colorize log arguments if enabled.
- *
- * @api public
- */
- function formatArgs(args) {
- var useColors = this.useColors;
- args[0] = (useColors ? '%c' : '')
- + this.namespace
- + (useColors ? ' %c' : ' ')
- + args[0]
- + (useColors ? '%c ' : ' ')
- + '+' + exports.humanize(this.diff);
- if (!useColors) return;
- var c = 'color: ' + this.color;
- args.splice(1, 0, c, 'color: inherit')
- // the final "%c" is somewhat tricky, because there could be other
- // arguments passed either before or after the %c, so we need to
- // figure out the correct index to insert the CSS into
- var index = 0;
- var lastC = 0;
- args[0].replace(/%[a-zA-Z%]/g, function(match) {
- if ('%%' === match) return;
- index++;
- if ('%c' === match) {
- // we only are interested in the *last* %c
- // (the user may have provided their own)
- lastC = index;
- }
- });
- args.splice(lastC, 0, c);
- }
- /**
- * Invokes `console.log()` when available.
- * No-op when `console.log` is not a "function".
- *
- * @api public
- */
- function log() {
- // this hackery is required for IE8/9, where
- // the `console.log` function doesn't have 'apply'
- return 'object' === typeof console
- && console.log
- && Function.prototype.apply.call(console.log, console, arguments);
- }
- /**
- * Save `namespaces`.
- *
- * @param {String} namespaces
- * @api private
- */
- function save(namespaces) {
- try {
- if (null == namespaces) {
- exports.storage.removeItem('debug');
- } else {
- exports.storage.debug = namespaces;
- }
- } catch(e) {}
- }
- /**
- * Load `namespaces`.
- *
- * @return {String} returns the previously persisted debug modes
- * @api private
- */
- function load() {
- try {
- return exports.storage.debug;
- } catch(e) {}
- // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
- if (typeof process !== 'undefined' && 'env' in process) {
- return process.env.DEBUG;
- }
- }
- /**
- * Enable namespaces listed in `localStorage.debug` initially.
- */
- exports.enable(load());
- /**
- * Localstorage attempts to return the localstorage.
- *
- * This is necessary because safari throws
- * when a user disables cookies/localstorage
- * and you attempt to access it.
- *
- * @return {LocalStorage}
- * @api private
- */
- function localstorage() {
- try {
- return window.localStorage;
- } catch (e) {}
- }
- }).call(this,require('_process'))
- },{"./debug":36,"_process":30}],36:[function(require,module,exports){
- /**
- * This is the common logic for both the Node.js and web browser
- * implementations of `debug()`.
- *
- * Expose `debug()` as the module.
- */
- exports = module.exports = createDebug.debug = createDebug.default = createDebug;
- exports.coerce = coerce;
- exports.disable = disable;
- exports.enable = enable;
- exports.enabled = enabled;
- exports.humanize = require('ms');
- /**
- * The currently active debug mode names, and names to skip.
- */
- exports.names = [];
- exports.skips = [];
- /**
- * Map of special "%n" handling functions, for the debug "format" argument.
- *
- * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
- */
- exports.formatters = {};
- /**
- * Previous log timestamp.
- */
- var prevTime;
- /**
- * Select a color.
- * @param {String} namespace
- * @return {Number}
- * @api private
- */
- function selectColor(namespace) {
- var hash = 0, i;
- for (i in namespace) {
- hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
- hash |= 0; // Convert to 32bit integer
- }
- return exports.colors[Math.abs(hash) % exports.colors.length];
- }
- /**
- * Create a debugger with the given `namespace`.
- *
- * @param {String} namespace
- * @return {Function}
- * @api public
- */
- function createDebug(namespace) {
- function debug() {
- // disabled?
- if (!debug.enabled) return;
- var self = debug;
- // set `diff` timestamp
- var curr = +new Date();
- var ms = curr - (prevTime || curr);
- self.diff = ms;
- self.prev = prevTime;
- self.curr = curr;
- prevTime = curr;
- // turn the `arguments` into a proper Array
- var args = new Array(arguments.length);
- for (var i = 0; i < args.length; i++) {
- args[i] = arguments[i];
- }
- args[0] = exports.coerce(args[0]);
- if ('string' !== typeof args[0]) {
- // anything else let's inspect with %O
- args.unshift('%O');
- }
- // apply any `formatters` transformations
- var index = 0;
- args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
- // if we encounter an escaped % then don't increase the array index
- if (match === '%%') return match;
- index++;
- var formatter = exports.formatters[format];
- if ('function' === typeof formatter) {
- var val = args[index];
- match = formatter.call(self, val);
- // now we need to remove `args[index]` since it's inlined in the `format`
- args.splice(index, 1);
- index--;
- }
- return match;
- });
- // apply env-specific formatting (colors, etc.)
- exports.formatArgs.call(self, args);
- var logFn = debug.log || exports.log || console.log.bind(console);
- logFn.apply(self, args);
- }
- debug.namespace = namespace;
- debug.enabled = exports.enabled(namespace);
- debug.useColors = exports.useColors();
- debug.color = selectColor(namespace);
- // env-specific initialization logic for debug instances
- if ('function' === typeof exports.init) {
- exports.init(debug);
- }
- return debug;
- }
- /**
- * Enables a debug mode by namespaces. This can include modes
- * separated by a colon and wildcards.
- *
- * @param {String} namespaces
- * @api public
- */
- function enable(namespaces) {
- exports.save(namespaces);
- var split = (namespaces || '').split(/[\s,]+/);
- var len = split.length;
- for (var i = 0; i < len; i++) {
- if (!split[i]) continue; // ignore empty strings
- namespaces = split[i].replace(/\*/g, '.*?');
- if (namespaces[0] === '-') {
- exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
- } else {
- exports.names.push(new RegExp('^' + namespaces + '$'));
- }
- }
- }
- /**
- * Disable debug output.
- *
- * @api public
- */
- function disable() {
- exports.enable('');
- }
- /**
- * Returns true if the given mode name is enabled, false otherwise.
- *
- * @param {String} name
- * @return {Boolean}
- * @api public
- */
- function enabled(name) {
- var i, len;
- for (i = 0, len = exports.skips.length; i < len; i++) {
- if (exports.skips[i].test(name)) {
- return false;
- }
- }
- for (i = 0, len = exports.names.length; i < len; i++) {
- if (exports.names[i].test(name)) {
- return true;
- }
- }
- return false;
- }
- /**
- * Coerce `val`.
- *
- * @param {Mixed} val
- * @return {Mixed}
- * @api private
- */
- function coerce(val) {
- if (val instanceof Error) return val.stack || val.message;
- return val;
- }
- },{"ms":34}],37:[function(require,module,exports){
- var grammar = module.exports = {
- v: [{
- name: 'version',
- reg: /^(\d*)$/
- }],
- o: [{ //o=- 20518 0 IN IP4 203.0.113.1
- // NB: sessionId will be a String in most cases because it is huge
- name: 'origin',
- reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/,
- names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'],
- format: "%s %s %d %s IP%d %s"
- }],
- // default parsing of these only (though some of these feel outdated)
- s: [{ name: 'name' }],
- i: [{ name: 'description' }],
- u: [{ name: 'uri' }],
- e: [{ name: 'email' }],
- p: [{ name: 'phone' }],
- z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly..
- r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly
- //k: [{}], // outdated thing ignored
- t: [{ //t=0 0
- name: 'timing',
- reg: /^(\d*) (\d*)/,
- names: ['start', 'stop'],
- format: "%d %d"
- }],
- c: [{ //c=IN IP4 10.47.197.26
- name: 'connection',
- reg: /^IN IP(\d) (\S*)/,
- names: ['version', 'ip'],
- format: "IN IP%d %s"
- }],
- b: [{ //b=AS:4000
- push: 'bandwidth',
- reg: /^(TIAS|AS|CT|RR|RS):(\d*)/,
- names: ['type', 'limit'],
- format: "%s:%s"
- }],
- m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31
- // NB: special - pushes to session
- // TODO: rtp/fmtp should be filtered by the payloads found here?
- reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/,
- names: ['type', 'port', 'protocol', 'payloads'],
- format: "%s %d %s %s"
- }],
- a: [
- { //a=rtpmap:110 opus/48000/2
- push: 'rtp',
- reg: /^rtpmap:(\d*) ([\w\-\.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/,
- names: ['payload', 'codec', 'rate', 'encoding'],
- format: function (o) {
- return (o.encoding) ?
- "rtpmap:%d %s/%s/%s":
- o.rate ?
- "rtpmap:%d %s/%s":
- "rtpmap:%d %s";
- }
- },
- {
- //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000
- //a=fmtp:111 minptime=10; useinbandfec=1
- push: 'fmtp',
- reg: /^fmtp:(\d*) ([\S| ]*)/,
- names: ['payload', 'config'],
- format: "fmtp:%d %s"
- },
- { //a=control:streamid=0
- name: 'control',
- reg: /^control:(.*)/,
- format: "control:%s"
- },
- { //a=rtcp:65179 IN IP4 193.84.77.194
- name: 'rtcp',
- reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/,
- names: ['port', 'netType', 'ipVer', 'address'],
- format: function (o) {
- return (o.address != null) ?
- "rtcp:%d %s IP%d %s":
- "rtcp:%d";
- }
- },
- { //a=rtcp-fb:98 trr-int 100
- push: 'rtcpFbTrrInt',
- reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/,
- names: ['payload', 'value'],
- format: "rtcp-fb:%d trr-int %d"
- },
- { //a=rtcp-fb:98 nack rpsi
- push: 'rtcpFb',
- reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/,
- names: ['payload', 'type', 'subtype'],
- format: function (o) {
- return (o.subtype != null) ?
- "rtcp-fb:%s %s %s":
- "rtcp-fb:%s %s";
- }
- },
- { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
- //a=extmap:1/recvonly URI-gps-string
- push: 'ext',
- reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/,
- names: ['value', 'uri', 'config'], // value may include "/direction" suffix
- format: function (o) {
- return (o.config != null) ?
- "extmap:%s %s %s":
- "extmap:%s %s";
- }
- },
- {
- //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32
- push: 'crypto',
- reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/,
- names: ['id', 'suite', 'config', 'sessionConfig'],
- format: function (o) {
- return (o.sessionConfig != null) ?
- "crypto:%d %s %s %s":
- "crypto:%d %s %s";
- }
- },
- { //a=setup:actpass
- name: 'setup',
- reg: /^setup:(\w*)/,
- format: "setup:%s"
- },
- { //a=mid:1
- name: 'mid',
- reg: /^mid:([^\s]*)/,
- format: "mid:%s"
- },
- { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a
- name: 'msid',
- reg: /^msid:(.*)/,
- format: "msid:%s"
- },
- { //a=ptime:20
- name: 'ptime',
- reg: /^ptime:(\d*)/,
- format: "ptime:%d"
- },
- { //a=maxptime:60
- name: 'maxptime',
- reg: /^maxptime:(\d*)/,
- format: "maxptime:%d"
- },
- { //a=sendrecv
- name: 'direction',
- reg: /^(sendrecv|recvonly|sendonly|inactive)/
- },
- { //a=ice-lite
- name: 'icelite',
- reg: /^(ice-lite)/
- },
- { //a=ice-ufrag:F7gI
- name: 'iceUfrag',
- reg: /^ice-ufrag:(\S*)/,
- format: "ice-ufrag:%s"
- },
- { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g
- name: 'icePwd',
- reg: /^ice-pwd:(\S*)/,
- format: "ice-pwd:%s"
- },
- { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33
- name: 'fingerprint',
- reg: /^fingerprint:(\S*) (\S*)/,
- names: ['type', 'hash'],
- format: "fingerprint:%s %s"
- },
- {
- //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
- //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0
- //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0
- //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0
- //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0
- push:'candidates',
- reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/,
- names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'],
- format: function (o) {
- var str = "candidate:%s %d %s %d %s %d typ %s";
- str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v";
- // NB: candidate has three optional chunks, so %void middles one if it's missing
- str += (o.tcptype != null) ? " tcptype %s" : "%v";
- if (o.generation != null) {
- str += " generation %d";
- }
- return str;
- }
- },
- { //a=end-of-candidates (keep after the candidates line for readability)
- name: 'endOfCandidates',
- reg: /^(end-of-candidates)/
- },
- { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ...
- name: 'remoteCandidates',
- reg: /^remote-candidates:(.*)/,
- format: "remote-candidates:%s"
- },
- { //a=ice-options:google-ice
- name: 'iceOptions',
- reg: /^ice-options:(\S*)/,
- format: "ice-options:%s"
- },
- { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1
- push: "ssrcs",
- reg: /^ssrc:(\d*) ([\w_]*):(.*)/,
- names: ['id', 'attribute', 'value'],
- format: "ssrc:%d %s:%s"
- },
- { //a=ssrc-group:FEC 1 2
- push: "ssrcGroups",
- reg: /^ssrc-group:(\w*) (.*)/,
- names: ['semantics', 'ssrcs'],
- format: "ssrc-group:%s %s"
- },
- { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV
- name: "msidSemantic",
- reg: /^msid-semantic:\s?(\w*) (\S*)/,
- names: ['semantic', 'token'],
- format: "msid-semantic: %s %s" // space after ":" is not accidental
- },
- { //a=group:BUNDLE audio video
- push: 'groups',
- reg: /^group:(\w*) (.*)/,
- names: ['type', 'mids'],
- format: "group:%s %s"
- },
- { //a=rtcp-mux
- name: 'rtcpMux',
- reg: /^(rtcp-mux)/
- },
- { //a=rtcp-rsize
- name: 'rtcpRsize',
- reg: /^(rtcp-rsize)/
- },
- { //a=sctpmap:5000 webrtc-datachannel 1024
- name: 'sctpmap',
- reg: /^sctpmap:([\w_\/]*) (\S*)(?: (\S*))?/,
- names: ['sctpmapNumber', 'app', 'maxMessageSize'],
- format: function (o) {
- return (o.maxMessageSize != null) ?
- "sctpmap:%s %s %s" :
- "sctpmap:%s %s";
- }
- },
- { // any a= that we don't understand is kepts verbatim on media.invalid
- push: 'invalid',
- names: ["value"]
- }
- ]
- };
- // set sensible defaults to avoid polluting the grammar with boring details
- Object.keys(grammar).forEach(function (key) {
- var objs = grammar[key];
- objs.forEach(function (obj) {
- if (!obj.reg) {
- obj.reg = /(.*)/;
- }
- if (!obj.format) {
- obj.format = "%s";
- }
- });
- });
- },{}],38:[function(require,module,exports){
- var parser = require('./parser');
- var writer = require('./writer');
- exports.write = writer;
- exports.parse = parser.parse;
- exports.parseFmtpConfig = parser.parseFmtpConfig;
- exports.parsePayloads = parser.parsePayloads;
- exports.parseRemoteCandidates = parser.parseRemoteCandidates;
- },{"./parser":39,"./writer":40}],39:[function(require,module,exports){
- var toIntIfInt = function (v) {
- return String(Number(v)) === v ? Number(v) : v;
- };
- var attachProperties = function (match, location, names, rawName) {
- if (rawName && !names) {
- location[rawName] = toIntIfInt(match[1]);
- }
- else {
- for (var i = 0; i < names.length; i += 1) {
- if (match[i+1] != null) {
- location[names[i]] = toIntIfInt(match[i+1]);
- }
- }
- }
- };
- var parseReg = function (obj, location, content) {
- var needsBlank = obj.name && obj.names;
- if (obj.push && !location[obj.push]) {
- location[obj.push] = [];
- }
- else if (needsBlank && !location[obj.name]) {
- location[obj.name] = {};
- }
- var keyLocation = obj.push ?
- {} : // blank object that will be pushed
- needsBlank ? location[obj.name] : location; // otherwise, named location or root
- attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);
- if (obj.push) {
- location[obj.push].push(keyLocation);
- }
- };
- var grammar = require('./grammar');
- var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);
- exports.parse = function (sdp) {
- var session = {}
- , media = []
- , location = session; // points at where properties go under (one of the above)
- // parse lines we understand
- sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) {
- var type = l[0];
- var content = l.slice(2);
- if (type === 'm') {
- media.push({rtp: [], fmtp: []});
- location = media[media.length-1]; // point at latest media line
- }
- for (var j = 0; j < (grammar[type] || []).length; j += 1) {
- var obj = grammar[type][j];
- if (obj.reg.test(content)) {
- return parseReg(obj, location, content);
- }
- }
- });
- session.media = media; // link it up
- return session;
- };
- var fmtpReducer = function (acc, expr) {
- var s = expr.split(/=(.+)/, 2);
- if (s.length === 2) {
- acc[s[0]] = toIntIfInt(s[1]);
- }
- return acc;
- };
- exports.parseFmtpConfig = function (str) {
- return str.split(/\;\s?/).reduce(fmtpReducer, {});
- };
- exports.parsePayloads = function (str) {
- return str.split(' ').map(Number);
- };
- exports.parseRemoteCandidates = function (str) {
- var candidates = [];
- var parts = str.split(' ').map(toIntIfInt);
- for (var i = 0; i < parts.length; i += 3) {
- candidates.push({
- component: parts[i],
- ip: parts[i + 1],
- port: parts[i + 2]
- });
- }
- return candidates;
- };
- },{"./grammar":37}],40:[function(require,module,exports){
- var grammar = require('./grammar');
- // customized util.format - discards excess arguments and can void middle ones
- var formatRegExp = /%[sdv%]/g;
- var format = function (formatStr) {
- var i = 1;
- var args = arguments;
- var len = args.length;
- return formatStr.replace(formatRegExp, function (x) {
- if (i >= len) {
- return x; // missing argument
- }
- var arg = args[i];
- i += 1;
- switch (x) {
- case '%%':
- return '%';
- case '%s':
- return String(arg);
- case '%d':
- return Number(arg);
- case '%v':
- return '';
- }
- });
- // NB: we discard excess arguments - they are typically undefined from makeLine
- };
- var makeLine = function (type, obj, location) {
- var str = obj.format instanceof Function ?
- (obj.format(obj.push ? location : location[obj.name])) :
- obj.format;
- var args = [type + '=' + str];
- if (obj.names) {
- for (var i = 0; i < obj.names.length; i += 1) {
- var n = obj.names[i];
- if (obj.name) {
- args.push(location[obj.name][n]);
- }
- else { // for mLine and push attributes
- args.push(location[obj.names[i]]);
- }
- }
- }
- else {
- args.push(location[obj.name]);
- }
- return format.apply(null, args);
- };
- // RFC specified order
- // TODO: extend this with all the rest
- var defaultOuterOrder = [
- 'v', 'o', 's', 'i',
- 'u', 'e', 'p', 'c',
- 'b', 't', 'r', 'z', 'a'
- ];
- var defaultInnerOrder = ['i', 'c', 'b', 'a'];
- module.exports = function (session, opts) {
- opts = opts || {};
- // ensure certain properties exist
- if (session.version == null) {
- session.version = 0; // "v=0" must be there (only defined version atm)
- }
- if (session.name == null) {
- session.name = " "; // "s= " must be there if no meaningful name set
- }
- session.media.forEach(function (mLine) {
- if (mLine.payloads == null) {
- mLine.payloads = "";
- }
- });
- var outerOrder = opts.outerOrder || defaultOuterOrder;
- var innerOrder = opts.innerOrder || defaultInnerOrder;
- var sdp = [];
- // loop through outerOrder for matching properties on session
- outerOrder.forEach(function (type) {
- grammar[type].forEach(function (obj) {
- if (obj.name in session && session[obj.name] != null) {
- sdp.push(makeLine(type, obj, session));
- }
- else if (obj.push in session && session[obj.push] != null) {
- session[obj.push].forEach(function (el) {
- sdp.push(makeLine(type, obj, el));
- });
- }
- });
- });
- // then for each media line, follow the innerOrder
- session.media.forEach(function (mLine) {
- sdp.push(makeLine('m', grammar.m[0], mLine));
- innerOrder.forEach(function (type) {
- grammar[type].forEach(function (obj) {
- if (obj.name in mLine && mLine[obj.name] != null) {
- sdp.push(makeLine(type, obj, mLine));
- }
- else if (obj.push in mLine && mLine[obj.push] != null) {
- mLine[obj.push].forEach(function (el) {
- sdp.push(makeLine(type, obj, el));
- });
- }
- });
- });
- });
- return sdp.join('\r\n') + '\r\n';
- };
- },{"./grammar":37}],41:[function(require,module,exports){
- /* eslint-env node */
- 'use strict';
- // SDP helpers.
- var SDPUtils = {};
- // Generate an alphanumeric identifier for cname or mids.
- // TODO: use UUIDs instead? https://gist.github.com/jed/982883
- SDPUtils.generateIdentifier = function() {
- return Math.random().toString(36).substr(2, 10);
- };
- // The RTCP CNAME used by all peerconnections from the same JS.
- SDPUtils.localCName = SDPUtils.generateIdentifier();
- // Splits SDP into lines, dealing with both CRLF and LF.
- SDPUtils.splitLines = function(blob) {
- return blob.trim().split('\n').map(function(line) {
- return line.trim();
- });
- };
- // Splits SDP into sessionpart and mediasections. Ensures CRLF.
- SDPUtils.splitSections = function(blob) {
- var parts = blob.split('\nm=');
- return parts.map(function(part, index) {
- return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
- });
- };
- // Returns lines that start with a certain prefix.
- SDPUtils.matchPrefix = function(blob, prefix) {
- return SDPUtils.splitLines(blob).filter(function(line) {
- return line.indexOf(prefix) === 0;
- });
- };
- // Parses an ICE candidate line. Sample input:
- // candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
- // rport 55996"
- SDPUtils.parseCandidate = function(line) {
- var parts;
- // Parse both variants.
- if (line.indexOf('a=candidate:') === 0) {
- parts = line.substring(12).split(' ');
- } else {
- parts = line.substring(10).split(' ');
- }
- var candidate = {
- foundation: parts[0],
- component: parts[1],
- protocol: parts[2].toLowerCase(),
- priority: parseInt(parts[3], 10),
- ip: parts[4],
- port: parseInt(parts[5], 10),
- // skip parts[6] == 'typ'
- type: parts[7]
- };
- for (var i = 8; i < parts.length; i += 2) {
- switch (parts[i]) {
- case 'raddr':
- candidate.relatedAddress = parts[i + 1];
- break;
- case 'rport':
- candidate.relatedPort = parseInt(parts[i + 1], 10);
- break;
- case 'tcptype':
- candidate.tcpType = parts[i + 1];
- break;
- default: // Unknown extensions are silently ignored.
- break;
- }
- }
- return candidate;
- };
- // Translates a candidate object into SDP candidate attribute.
- SDPUtils.writeCandidate = function(candidate) {
- var sdp = [];
- sdp.push(candidate.foundation);
- sdp.push(candidate.component);
- sdp.push(candidate.protocol.toUpperCase());
- sdp.push(candidate.priority);
- sdp.push(candidate.ip);
- sdp.push(candidate.port);
- var type = candidate.type;
- sdp.push('typ');
- sdp.push(type);
- if (type !== 'host' && candidate.relatedAddress &&
- candidate.relatedPort) {
- sdp.push('raddr');
- sdp.push(candidate.relatedAddress); // was: relAddr
- sdp.push('rport');
- sdp.push(candidate.relatedPort); // was: relPort
- }
- if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
- sdp.push('tcptype');
- sdp.push(candidate.tcpType);
- }
- return 'candidate:' + sdp.join(' ');
- };
- // Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
- // a=rtpmap:111 opus/48000/2
- SDPUtils.parseRtpMap = function(line) {
- var parts = line.substr(9).split(' ');
- var parsed = {
- payloadType: parseInt(parts.shift(), 10) // was: id
- };
- parts = parts[0].split('/');
- parsed.name = parts[0];
- parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
- // was: channels
- parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
- return parsed;
- };
- // Generate an a=rtpmap line from RTCRtpCodecCapability or
- // RTCRtpCodecParameters.
- SDPUtils.writeRtpMap = function(codec) {
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
- (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
- };
- // Parses an a=extmap line (headerextension from RFC 5285). Sample input:
- // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
- SDPUtils.parseExtmap = function(line) {
- var parts = line.substr(9).split(' ');
- return {
- id: parseInt(parts[0], 10),
- uri: parts[1]
- };
- };
- // Generates a=extmap line from RTCRtpHeaderExtensionParameters or
- // RTCRtpHeaderExtension.
- SDPUtils.writeExtmap = function(headerExtension) {
- return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
- ' ' + headerExtension.uri + '\r\n';
- };
- // Parses an ftmp line, returns dictionary. Sample input:
- // a=fmtp:96 vbr=on;cng=on
- // Also deals with vbr=on; cng=on
- SDPUtils.parseFmtp = function(line) {
- var parsed = {};
- var kv;
- var parts = line.substr(line.indexOf(' ') + 1).split(';');
- for (var j = 0; j < parts.length; j++) {
- kv = parts[j].trim().split('=');
- parsed[kv[0].trim()] = kv[1];
- }
- return parsed;
- };
- // Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
- SDPUtils.writeFmtp = function(codec) {
- var line = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.parameters && Object.keys(codec.parameters).length) {
- var params = [];
- Object.keys(codec.parameters).forEach(function(param) {
- params.push(param + '=' + codec.parameters[param]);
- });
- line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
- }
- return line;
- };
- // Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
- // a=rtcp-fb:98 nack rpsi
- SDPUtils.parseRtcpFb = function(line) {
- var parts = line.substr(line.indexOf(' ') + 1).split(' ');
- return {
- type: parts.shift(),
- parameter: parts.join(' ')
- };
- };
- // Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
- SDPUtils.writeRtcpFb = function(codec) {
- var lines = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
- // FIXME: special handling for trr-int?
- codec.rtcpFeedback.forEach(function(fb) {
- lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
- (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
- '\r\n';
- });
- }
- return lines;
- };
- // Parses an RFC 5576 ssrc media attribute. Sample input:
- // a=ssrc:3735928559 cname:something
- SDPUtils.parseSsrcMedia = function(line) {
- var sp = line.indexOf(' ');
- var parts = {
- ssrc: parseInt(line.substr(7, sp - 7), 10)
- };
- var colon = line.indexOf(':', sp);
- if (colon > -1) {
- parts.attribute = line.substr(sp + 1, colon - sp - 1);
- parts.value = line.substr(colon + 1);
- } else {
- parts.attribute = line.substr(sp + 1);
- }
- return parts;
- };
- // Extracts DTLS parameters from SDP media section or sessionpart.
- // FIXME: for consistency with other functions this should only
- // get the fingerprint line as input. See also getIceParameters.
- SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.splitLines(mediaSection);
- // Search in session part, too.
- lines = lines.concat(SDPUtils.splitLines(sessionpart));
- var fpLine = lines.filter(function(line) {
- return line.indexOf('a=fingerprint:') === 0;
- })[0].substr(14);
- // Note: a=setup line is ignored since we use the 'auto' role.
- var dtlsParameters = {
- role: 'auto',
- fingerprints: [{
- algorithm: fpLine.split(' ')[0],
- value: fpLine.split(' ')[1]
- }]
- };
- return dtlsParameters;
- };
- // Serializes DTLS parameters to SDP.
- SDPUtils.writeDtlsParameters = function(params, setupType) {
- var sdp = 'a=setup:' + setupType + '\r\n';
- params.fingerprints.forEach(function(fp) {
- sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
- });
- return sdp;
- };
- // Parses ICE information from SDP media section or sessionpart.
- // FIXME: for consistency with other functions this should only
- // get the ice-ufrag and ice-pwd lines as input.
- SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.splitLines(mediaSection);
- // Search in session part, too.
- lines = lines.concat(SDPUtils.splitLines(sessionpart));
- var iceParameters = {
- usernameFragment: lines.filter(function(line) {
- return line.indexOf('a=ice-ufrag:') === 0;
- })[0].substr(12),
- password: lines.filter(function(line) {
- return line.indexOf('a=ice-pwd:') === 0;
- })[0].substr(10)
- };
- return iceParameters;
- };
- // Serializes ICE parameters to SDP.
- SDPUtils.writeIceParameters = function(params) {
- return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
- 'a=ice-pwd:' + params.password + '\r\n';
- };
- // Parses the SDP media section and returns RTCRtpParameters.
- SDPUtils.parseRtpParameters = function(mediaSection) {
- var description = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: [],
- rtcp: []
- };
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
- var pt = mline[i];
- var rtpmapline = SDPUtils.matchPrefix(
- mediaSection, 'a=rtpmap:' + pt + ' ')[0];
- if (rtpmapline) {
- var codec = SDPUtils.parseRtpMap(rtpmapline);
- var fmtps = SDPUtils.matchPrefix(
- mediaSection, 'a=fmtp:' + pt + ' ');
- // Only the first a=fmtp:<pt> is considered.
- codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
- codec.rtcpFeedback = SDPUtils.matchPrefix(
- mediaSection, 'a=rtcp-fb:' + pt + ' ')
- .map(SDPUtils.parseRtcpFb);
- description.codecs.push(codec);
- // parse FEC mechanisms from rtpmap lines.
- switch (codec.name.toUpperCase()) {
- case 'RED':
- case 'ULPFEC':
- description.fecMechanisms.push(codec.name.toUpperCase());
- break;
- default: // only RED and ULPFEC are recognized as FEC mechanisms.
- break;
- }
- }
- }
- SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
- description.headerExtensions.push(SDPUtils.parseExtmap(line));
- });
- // FIXME: parse rtcp.
- return description;
- };
- // Generates parts of the SDP media section describing the capabilities /
- // parameters.
- SDPUtils.writeRtpDescription = function(kind, caps) {
- var sdp = '';
- // Build the mline.
- sdp += 'm=' + kind + ' ';
- sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
- sdp += ' UDP/TLS/RTP/SAVPF ';
- sdp += caps.codecs.map(function(codec) {
- if (codec.preferredPayloadType !== undefined) {
- return codec.preferredPayloadType;
- }
- return codec.payloadType;
- }).join(' ') + '\r\n';
- sdp += 'c=IN IP4 0.0.0.0\r\n';
- sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
- // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
- caps.codecs.forEach(function(codec) {
- sdp += SDPUtils.writeRtpMap(codec);
- sdp += SDPUtils.writeFmtp(codec);
- sdp += SDPUtils.writeRtcpFb(codec);
- });
- sdp += 'a=rtcp-mux\r\n';
- caps.headerExtensions.forEach(function(extension) {
- sdp += SDPUtils.writeExtmap(extension);
- });
- // FIXME: write fecMechanisms.
- return sdp;
- };
- // Parses the SDP media section and returns an array of
- // RTCRtpEncodingParameters.
- SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
- var encodingParameters = [];
- var description = SDPUtils.parseRtpParameters(mediaSection);
- var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
- var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
- // filter a=ssrc:... cname:, ignore PlanB-msid
- var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(parts) {
- return parts.attribute === 'cname';
- });
- var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
- var secondarySsrc;
- var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
- .map(function(line) {
- var parts = line.split(' ');
- parts.shift();
- return parts.map(function(part) {
- return parseInt(part, 10);
- });
- });
- if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
- secondarySsrc = flows[0][1];
- }
- description.codecs.forEach(function(codec) {
- if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
- var encParam = {
- ssrc: primarySsrc,
- codecPayloadType: parseInt(codec.parameters.apt, 10),
- rtx: {
- payloadType: codec.payloadType,
- ssrc: secondarySsrc
- }
- };
- encodingParameters.push(encParam);
- if (hasRed) {
- encParam = JSON.parse(JSON.stringify(encParam));
- encParam.fec = {
- ssrc: secondarySsrc,
- mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
- };
- encodingParameters.push(encParam);
- }
- }
- });
- if (encodingParameters.length === 0 && primarySsrc) {
- encodingParameters.push({
- ssrc: primarySsrc
- });
- }
- // we support both b=AS and b=TIAS but interpret AS as TIAS.
- var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
- if (bandwidth.length) {
- if (bandwidth[0].indexOf('b=TIAS:') === 0) {
- bandwidth = parseInt(bandwidth[0].substr(7), 10);
- } else if (bandwidth[0].indexOf('b=AS:') === 0) {
- bandwidth = parseInt(bandwidth[0].substr(5), 10);
- }
- encodingParameters.forEach(function(params) {
- params.maxBitrate = bandwidth;
- });
- }
- return encodingParameters;
- };
- SDPUtils.writeSessionBoilerplate = function() {
- // FIXME: sess-id should be an NTP timestamp.
- return 'v=0\r\n' +
- 'o=thisisadapterortc 8169639915646943137 2 IN IP4 127.0.0.1\r\n' +
- 's=-\r\n' +
- 't=0 0\r\n';
- };
- SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
- var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
- // Map ICE parameters (ufrag, pwd) to SDP.
- sdp += SDPUtils.writeIceParameters(
- transceiver.iceGatherer.getLocalParameters());
- // Map DTLS parameters to SDP.
- sdp += SDPUtils.writeDtlsParameters(
- transceiver.dtlsTransport.getLocalParameters(),
- type === 'offer' ? 'actpass' : 'active');
- sdp += 'a=mid:' + transceiver.mid + '\r\n';
- if (transceiver.rtpSender && transceiver.rtpReceiver) {
- sdp += 'a=sendrecv\r\n';
- } else if (transceiver.rtpSender) {
- sdp += 'a=sendonly\r\n';
- } else if (transceiver.rtpReceiver) {
- sdp += 'a=recvonly\r\n';
- } else {
- sdp += 'a=inactive\r\n';
- }
- // FIXME: for RTX there might be multiple SSRCs. Not implemented in Edge yet.
- if (transceiver.rtpSender) {
- var msid = 'msid:' + stream.id + ' ' +
- transceiver.rtpSender.track.id + '\r\n';
- sdp += 'a=' + msid;
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' ' + msid;
- }
- // FIXME: this should be written by writeRtpDescription.
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' cname:' + SDPUtils.localCName + '\r\n';
- return sdp;
- };
- // Gets the direction from the mediaSection or the sessionpart.
- SDPUtils.getDirection = function(mediaSection, sessionpart) {
- // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
- var lines = SDPUtils.splitLines(mediaSection);
- for (var i = 0; i < lines.length; i++) {
- switch (lines[i]) {
- case 'a=sendrecv':
- case 'a=sendonly':
- case 'a=recvonly':
- case 'a=inactive':
- return lines[i].substr(2);
- default:
- // FIXME: What should happen here?
- }
- }
- if (sessionpart) {
- return SDPUtils.getDirection(sessionpart);
- }
- return 'sendrecv';
- };
- // Expose public methods.
- module.exports = SDPUtils;
- },{}],42:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- // Shimming starts here.
- (function() {
- // Utils.
- var logging = require('./utils').log;
- var browserDetails = require('./utils').browserDetails;
- // Export to the adapter global object visible in the browser.
- module.exports.browserDetails = browserDetails;
- module.exports.extractVersion = require('./utils').extractVersion;
- module.exports.disableLog = require('./utils').disableLog;
- // Uncomment the line below if you want logging to occur, including logging
- // for the switch statement below. Can also be turned on in the browser via
- // adapter.disableLog(false), but then logging from the switch statement below
- // will not appear.
- // require('./utils').disableLog(false);
- // Browser shims.
- var chromeShim = require('./chrome/chrome_shim') || null;
- var edgeShim = require('./edge/edge_shim') || null;
- var firefoxShim = require('./firefox/firefox_shim') || null;
- var safariShim = require('./safari/safari_shim') || null;
- // Shim browser if found.
- switch (browserDetails.browser) {
- case 'opera': // fallthrough as it uses chrome shims
- case 'chrome':
- if (!chromeShim || !chromeShim.shimPeerConnection) {
- logging('Chrome shim is not included in this adapter release.');
- return;
- }
- logging('adapter.js shimming chrome.');
- // Export to the adapter global object visible in the browser.
- module.exports.browserShim = chromeShim;
- chromeShim.shimGetUserMedia();
- chromeShim.shimMediaStream();
- chromeShim.shimSourceObject();
- chromeShim.shimPeerConnection();
- chromeShim.shimOnTrack();
- break;
- case 'firefox':
- if (!firefoxShim || !firefoxShim.shimPeerConnection) {
- logging('Firefox shim is not included in this adapter release.');
- return;
- }
- logging('adapter.js shimming firefox.');
- // Export to the adapter global object visible in the browser.
- module.exports.browserShim = firefoxShim;
- firefoxShim.shimGetUserMedia();
- firefoxShim.shimSourceObject();
- firefoxShim.shimPeerConnection();
- firefoxShim.shimOnTrack();
- break;
- case 'edge':
- if (!edgeShim || !edgeShim.shimPeerConnection) {
- logging('MS edge shim is not included in this adapter release.');
- return;
- }
- logging('adapter.js shimming edge.');
- // Export to the adapter global object visible in the browser.
- module.exports.browserShim = edgeShim;
- edgeShim.shimGetUserMedia();
- edgeShim.shimPeerConnection();
- break;
- case 'safari':
- if (!safariShim) {
- logging('Safari shim is not included in this adapter release.');
- return;
- }
- logging('adapter.js shimming safari.');
- // Export to the adapter global object visible in the browser.
- module.exports.browserShim = safariShim;
- safariShim.shimGetUserMedia();
- break;
- default:
- logging('Unsupported browser!');
- }
- })();
- },{"./chrome/chrome_shim":43,"./edge/edge_shim":45,"./firefox/firefox_shim":47,"./safari/safari_shim":49,"./utils":50}],43:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- var logging = require('../utils.js').log;
- var browserDetails = require('../utils.js').browserDetails;
- var chromeShim = {
- shimMediaStream: function() {
- window.MediaStream = window.MediaStream || window.webkitMediaStream;
- },
- shimOnTrack: function() {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- var self = this;
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- this.removeEventListener('addstream', this._ontrackpoly);
- }
- this.addEventListener('track', this._ontrack = f);
- this.addEventListener('addstream', this._ontrackpoly = function(e) {
- // onaddstream does not fire when a track is added to an existing
- // stream. But stream.onaddtrack is implemented so we use that.
- e.stream.addEventListener('addtrack', function(te) {
- var event = new Event('track');
- event.track = te.track;
- event.receiver = {track: te.track};
- event.streams = [e.stream];
- self.dispatchEvent(event);
- });
- e.stream.getTracks().forEach(function(track) {
- var event = new Event('track');
- event.track = track;
- event.receiver = {track: track};
- event.streams = [e.stream];
- this.dispatchEvent(event);
- }.bind(this));
- }.bind(this));
- }
- });
- }
- },
- shimSourceObject: function() {
- if (typeof window === 'object') {
- if (window.HTMLMediaElement &&
- !('srcObject' in window.HTMLMediaElement.prototype)) {
- // Shim the srcObject property, once, when HTMLMediaElement is found.
- Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
- get: function() {
- return this._srcObject;
- },
- set: function(stream) {
- var self = this;
- // Use _srcObject as a private property for this shim
- this._srcObject = stream;
- if (this.src) {
- URL.revokeObjectURL(this.src);
- }
- if (!stream) {
- this.src = '';
- return;
- }
- this.src = URL.createObjectURL(stream);
- // We need to recreate the blob url when a track is added or
- // removed. Doing it manually since we want to avoid a recursion.
- stream.addEventListener('addtrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- stream.addEventListener('removetrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- }
- });
- }
- }
- },
- shimPeerConnection: function() {
- // The RTCPeerConnection object.
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- // Translate iceTransportPolicy to iceTransports,
- // see https://code.google.com/p/webrtc/issues/detail?id=4869
- logging('PeerConnection');
- if (pcConfig && pcConfig.iceTransportPolicy) {
- pcConfig.iceTransports = pcConfig.iceTransportPolicy;
- }
- var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints);
- var origGetStats = pc.getStats.bind(pc);
- pc.getStats = function(selector, successCallback, errorCallback) {
- var self = this;
- var args = arguments;
- // If selector is a function then we are in the old style stats so just
- // pass back the original getStats format to avoid breaking old users.
- if (arguments.length > 0 && typeof selector === 'function') {
- return origGetStats(selector, successCallback);
- }
- var fixChromeStats_ = function(response) {
- var standardReport = {};
- var reports = response.result();
- reports.forEach(function(report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: report.type
- };
- report.names().forEach(function(name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
- return standardReport;
- };
- // shim getStats with maplike support
- var makeMapStats = function(stats, legacyStats) {
- var map = new Map(Object.keys(stats).map(function(key) {
- return[key, stats[key]];
- }));
- legacyStats = legacyStats || stats;
- Object.keys(legacyStats).forEach(function(key) {
- map[key] = legacyStats[key];
- });
- return map;
- };
- if (arguments.length >= 2) {
- var successCallbackWrapper_ = function(response) {
- args[1](makeMapStats(fixChromeStats_(response)));
- };
- return origGetStats.apply(this, [successCallbackWrapper_,
- arguments[0]]);
- }
- // promise-support
- return new Promise(function(resolve, reject) {
- if (args.length === 1 && typeof selector === 'object') {
- origGetStats.apply(self, [
- function(response) {
- resolve(makeMapStats(fixChromeStats_(response)));
- }, reject]);
- } else {
- // Preserve legacy chrome stats only on legacy access of stats obj
- origGetStats.apply(self, [
- function(response) {
- resolve(makeMapStats(fixChromeStats_(response),
- response.result()));
- }, reject]);
- }
- }).then(successCallback, errorCallback);
- };
- return pc;
- };
- window.RTCPeerConnection.prototype = webkitRTCPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if (webkitRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return webkitRTCPeerConnection.generateCertificate;
- }
- });
- }
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = webkitRTCPeerConnection.prototype[method];
- webkitRTCPeerConnection.prototype[method] = function() {
- var self = this;
- if (arguments.length < 1 || (arguments.length === 1 &&
- typeof arguments[0] === 'object')) {
- var opts = arguments.length === 1 ? arguments[0] : undefined;
- return new Promise(function(resolve, reject) {
- nativeMethod.apply(self, [resolve, reject, opts]);
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
- // add promise support -- natively available in Chrome 51
- if (browserDetails.version < 51) {
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = webkitRTCPeerConnection.prototype[method];
- webkitRTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- var self = this;
- var promise = new Promise(function(resolve, reject) {
- nativeMethod.apply(self, [args[0], resolve, reject]);
- });
- if (args.length < 2) {
- return promise;
- }
- return promise.then(function() {
- args[1].apply(null, []);
- },
- function(err) {
- if (args.length >= 3) {
- args[2].apply(null, [err]);
- }
- });
- };
- });
- }
- // shim implicit creation of RTCSessionDescription/RTCIceCandidate
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = webkitRTCPeerConnection.prototype[method];
- webkitRTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- RTCIceCandidate : RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- RTCPeerConnection.prototype.addIceCandidate;
- RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
- }
- };
- // Expose public methods.
- module.exports = {
- shimMediaStream: chromeShim.shimMediaStream,
- shimOnTrack: chromeShim.shimOnTrack,
- shimSourceObject: chromeShim.shimSourceObject,
- shimPeerConnection: chromeShim.shimPeerConnection,
- shimGetUserMedia: require('./getusermedia')
- };
- },{"../utils.js":50,"./getusermedia":44}],44:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- var logging = require('../utils.js').log;
- // Expose public methods.
- module.exports = function() {
- var constraintsToChrome_ = function(c) {
- if (typeof c !== 'object' || c.mandatory || c.optional) {
- return c;
- }
- var cc = {};
- Object.keys(c).forEach(function(key) {
- if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
- return;
- }
- var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
- if (r.exact !== undefined && typeof r.exact === 'number') {
- r.min = r.max = r.exact;
- }
- var oldname_ = function(prefix, name) {
- if (prefix) {
- return prefix + name.charAt(0).toUpperCase() + name.slice(1);
- }
- return (name === 'deviceId') ? 'sourceId' : name;
- };
- if (r.ideal !== undefined) {
- cc.optional = cc.optional || [];
- var oc = {};
- if (typeof r.ideal === 'number') {
- oc[oldname_('min', key)] = r.ideal;
- cc.optional.push(oc);
- oc = {};
- oc[oldname_('max', key)] = r.ideal;
- cc.optional.push(oc);
- } else {
- oc[oldname_('', key)] = r.ideal;
- cc.optional.push(oc);
- }
- }
- if (r.exact !== undefined && typeof r.exact !== 'number') {
- cc.mandatory = cc.mandatory || {};
- cc.mandatory[oldname_('', key)] = r.exact;
- } else {
- ['min', 'max'].forEach(function(mix) {
- if (r[mix] !== undefined) {
- cc.mandatory = cc.mandatory || {};
- cc.mandatory[oldname_(mix, key)] = r[mix];
- }
- });
- }
- });
- if (c.advanced) {
- cc.optional = (cc.optional || []).concat(c.advanced);
- }
- return cc;
- };
- var shimConstraints_ = function(constraints, func) {
- constraints = JSON.parse(JSON.stringify(constraints));
- if (constraints && constraints.audio) {
- constraints.audio = constraintsToChrome_(constraints.audio);
- }
- if (constraints && typeof constraints.video === 'object') {
- // Shim facingMode for mobile, where it defaults to "user".
- var face = constraints.video.facingMode;
- face = face && ((typeof face === 'object') ? face : {ideal: face});
- if ((face && (face.exact === 'user' || face.exact === 'environment' ||
- face.ideal === 'user' || face.ideal === 'environment')) &&
- !(navigator.mediaDevices.getSupportedConstraints &&
- navigator.mediaDevices.getSupportedConstraints().facingMode)) {
- delete constraints.video.facingMode;
- if (face.exact === 'environment' || face.ideal === 'environment') {
- // Look for "back" in label, or use last cam (typically back cam).
- return navigator.mediaDevices.enumerateDevices()
- .then(function(devices) {
- devices = devices.filter(function(d) {
- return d.kind === 'videoinput';
- });
- var back = devices.find(function(d) {
- return d.label.toLowerCase().indexOf('back') !== -1;
- }) || (devices.length && devices[devices.length - 1]);
- if (back) {
- constraints.video.deviceId = face.exact ? {exact: back.deviceId} :
- {ideal: back.deviceId};
- }
- constraints.video = constraintsToChrome_(constraints.video);
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- });
- }
- }
- constraints.video = constraintsToChrome_(constraints.video);
- }
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- };
- var shimError_ = function(e) {
- return {
- name: {
- PermissionDeniedError: 'NotAllowedError',
- ConstraintNotSatisfiedError: 'OverconstrainedError'
- }[e.name] || e.name,
- message: e.message,
- constraint: e.constraintName,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
- var getUserMedia_ = function(constraints, onSuccess, onError) {
- shimConstraints_(constraints, function(c) {
- navigator.webkitGetUserMedia(c, onSuccess, function(e) {
- onError(shimError_(e));
- });
- });
- };
- navigator.getUserMedia = getUserMedia_;
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- navigator.getUserMedia(constraints, resolve, reject);
- });
- };
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {
- getUserMedia: getUserMediaPromise_,
- enumerateDevices: function() {
- return new Promise(function(resolve) {
- var kinds = {audio: 'audioinput', video: 'videoinput'};
- return MediaStreamTrack.getSources(function(devices) {
- resolve(devices.map(function(device) {
- return {label: device.label,
- kind: kinds[device.kind],
- deviceId: device.id,
- groupId: ''};
- }));
- });
- });
- }
- };
- }
- // A shim for getUserMedia method on the mediaDevices object.
- // TODO(KaptenJansson) remove once implemented in Chrome stable.
- if (!navigator.mediaDevices.getUserMedia) {
- navigator.mediaDevices.getUserMedia = function(constraints) {
- return getUserMediaPromise_(constraints);
- };
- } else {
- // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
- // function which returns a Promise, it does not accept spec-style
- // constraints.
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(cs) {
- return shimConstraints_(cs, function(c) {
- return origGetUserMedia(c).then(function(stream) {
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('', 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- });
- };
- }
- // Dummy devicechange event methods.
- // TODO(KaptenJansson) remove once implemented in Chrome stable.
- if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
- navigator.mediaDevices.addEventListener = function() {
- logging('Dummy mediaDevices.addEventListener called.');
- };
- }
- if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
- navigator.mediaDevices.removeEventListener = function() {
- logging('Dummy mediaDevices.removeEventListener called.');
- };
- }
- };
- },{"../utils.js":50}],45:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- var SDPUtils = require('sdp');
- var browserDetails = require('../utils').browserDetails;
- var edgeShim = {
- shimPeerConnection: function() {
- if (window.RTCIceGatherer) {
- // ORTC defines an RTCIceCandidate object but no constructor.
- // Not implemented in Edge.
- if (!window.RTCIceCandidate) {
- window.RTCIceCandidate = function(args) {
- return args;
- };
- }
- // ORTC does not have a session description object but
- // other browsers (i.e. Chrome) that will support both PC and ORTC
- // in the future might have this defined already.
- if (!window.RTCSessionDescription) {
- window.RTCSessionDescription = function(args) {
- return args;
- };
- }
- // this adds an additional event listener to MediaStrackTrack that signals
- // when a tracks enabled property was changed.
- var origMSTEnabled = Object.getOwnPropertyDescriptor(
- MediaStreamTrack.prototype, 'enabled');
- Object.defineProperty(MediaStreamTrack.prototype, 'enabled', {
- set: function(value) {
- origMSTEnabled.set.call(this, value);
- var ev = new Event('enabled');
- ev.enabled = value;
- this.dispatchEvent(ev);
- }
- });
- }
- window.RTCPeerConnection = function(config) {
- var self = this;
- var _eventTarget = document.createDocumentFragment();
- ['addEventListener', 'removeEventListener', 'dispatchEvent']
- .forEach(function(method) {
- self[method] = _eventTarget[method].bind(_eventTarget);
- });
- this.onicecandidate = null;
- this.onaddstream = null;
- this.ontrack = null;
- this.onremovestream = null;
- this.onsignalingstatechange = null;
- this.oniceconnectionstatechange = null;
- this.onnegotiationneeded = null;
- this.ondatachannel = null;
- this.localStreams = [];
- this.remoteStreams = [];
- this.getLocalStreams = function() {
- return self.localStreams;
- };
- this.getRemoteStreams = function() {
- return self.remoteStreams;
- };
- this.localDescription = new RTCSessionDescription({
- type: '',
- sdp: ''
- });
- this.remoteDescription = new RTCSessionDescription({
- type: '',
- sdp: ''
- });
- this.signalingState = 'stable';
- this.iceConnectionState = 'new';
- this.iceGatheringState = 'new';
- this.iceOptions = {
- gatherPolicy: 'all',
- iceServers: []
- };
- if (config && config.iceTransportPolicy) {
- switch (config.iceTransportPolicy) {
- case 'all':
- case 'relay':
- this.iceOptions.gatherPolicy = config.iceTransportPolicy;
- break;
- case 'none':
- // FIXME: remove once implementation and spec have added this.
- throw new TypeError('iceTransportPolicy "none" not supported');
- default:
- // don't set iceTransportPolicy.
- break;
- }
- }
- this.usingBundle = config && config.bundlePolicy === 'max-bundle';
- if (config && config.iceServers) {
- // Edge does not like
- // 1) stun:
- // 2) turn: that does not have all of turn:host:port?transport=udp
- // 3) turn: with ipv6 addresses
- var iceServers = JSON.parse(JSON.stringify(config.iceServers));
- this.iceOptions.iceServers = iceServers.filter(function(server) {
- if (server && server.urls) {
- var urls = server.urls;
- if (typeof urls === 'string') {
- urls = [urls];
- }
- urls = urls.filter(function(url) {
- return (url.indexOf('turn:') === 0 &&
- url.indexOf('transport=udp') !== -1 &&
- url.indexOf('turn:[') === -1) ||
- (url.indexOf('stun:') === 0 &&
- browserDetails.version >= 14393);
- })[0];
- return !!urls;
- }
- return false;
- });
- }
- this._config = config;
- // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
- // everything that is needed to describe a SDP m-line.
- this.transceivers = [];
- // since the iceGatherer is currently created in createOffer but we
- // must not emit candidates until after setLocalDescription we buffer
- // them in this array.
- this._localIceCandidatesBuffer = [];
- };
- window.RTCPeerConnection.prototype._emitBufferedCandidates = function() {
- var self = this;
- var sections = SDPUtils.splitSections(self.localDescription.sdp);
- // FIXME: need to apply ice candidates in a way which is async but
- // in-order
- this._localIceCandidatesBuffer.forEach(function(event) {
- var end = !event.candidate || Object.keys(event.candidate).length === 0;
- if (end) {
- for (var j = 1; j < sections.length; j++) {
- if (sections[j].indexOf('\r\na=end-of-candidates\r\n') === -1) {
- sections[j] += 'a=end-of-candidates\r\n';
- }
- }
- } else if (event.candidate.candidate.indexOf('typ endOfCandidates')
- === -1) {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=' + event.candidate.candidate + '\r\n';
- }
- self.localDescription.sdp = sections.join('');
- self.dispatchEvent(event);
- if (self.onicecandidate !== null) {
- self.onicecandidate(event);
- }
- if (!event.candidate && self.iceGatheringState !== 'complete') {
- var complete = self.transceivers.every(function(transceiver) {
- return transceiver.iceGatherer &&
- transceiver.iceGatherer.state === 'completed';
- });
- if (complete) {
- self.iceGatheringState = 'complete';
- }
- }
- });
- this._localIceCandidatesBuffer = [];
- };
- window.RTCPeerConnection.prototype.getConfiguration = function() {
- return this._config;
- };
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- // Clone is necessary for local demos mostly, attaching directly
- // to two different senders does not work (build 10547).
- var clonedStream = stream.clone();
- stream.getTracks().forEach(function(track, idx) {
- var clonedTrack = clonedStream.getTracks()[idx];
- track.addEventListener('enabled', function(event) {
- clonedTrack.enabled = event.enabled;
- });
- });
- this.localStreams.push(clonedStream);
- this._maybeFireNegotiationNeeded();
- };
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var idx = this.localStreams.indexOf(stream);
- if (idx > -1) {
- this.localStreams.splice(idx, 1);
- this._maybeFireNegotiationNeeded();
- }
- };
- window.RTCPeerConnection.prototype.getSenders = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpSender;
- })
- .map(function(transceiver) {
- return transceiver.rtpSender;
- });
- };
- window.RTCPeerConnection.prototype.getReceivers = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpReceiver;
- })
- .map(function(transceiver) {
- return transceiver.rtpReceiver;
- });
- };
- // Determines the intersection of local and remote capabilities.
- window.RTCPeerConnection.prototype._getCommonCapabilities =
- function(localCapabilities, remoteCapabilities) {
- var commonCapabilities = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: []
- };
- localCapabilities.codecs.forEach(function(lCodec) {
- for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
- var rCodec = remoteCapabilities.codecs[i];
- if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
- lCodec.clockRate === rCodec.clockRate) {
- // number of channels is the highest common number of channels
- rCodec.numChannels = Math.min(lCodec.numChannels,
- rCodec.numChannels);
- // push rCodec so we reply with offerer payload type
- commonCapabilities.codecs.push(rCodec);
- // determine common feedback mechanisms
- rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
- for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
- if (lCodec.rtcpFeedback[j].type === fb.type &&
- lCodec.rtcpFeedback[j].parameter === fb.parameter) {
- return true;
- }
- }
- return false;
- });
- // FIXME: also need to determine .parameters
- // see https://github.com/openpeer/ortc/issues/569
- break;
- }
- }
- });
- localCapabilities.headerExtensions
- .forEach(function(lHeaderExtension) {
- for (var i = 0; i < remoteCapabilities.headerExtensions.length;
- i++) {
- var rHeaderExtension = remoteCapabilities.headerExtensions[i];
- if (lHeaderExtension.uri === rHeaderExtension.uri) {
- commonCapabilities.headerExtensions.push(rHeaderExtension);
- break;
- }
- }
- });
- // FIXME: fecMechanisms
- return commonCapabilities;
- };
- // Create ICE gatherer, ICE transport and DTLS transport.
- window.RTCPeerConnection.prototype._createIceAndDtlsTransports =
- function(mid, sdpMLineIndex) {
- var self = this;
- var iceGatherer = new RTCIceGatherer(self.iceOptions);
- var iceTransport = new RTCIceTransport(iceGatherer);
- iceGatherer.onlocalcandidate = function(evt) {
- var event = new Event('icecandidate');
- event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
- var cand = evt.candidate;
- var end = !cand || Object.keys(cand).length === 0;
- // Edge emits an empty object for RTCIceCandidateComplete‥
- if (end) {
- // polyfill since RTCIceGatherer.state is not implemented in
- // Edge 10547 yet.
- if (iceGatherer.state === undefined) {
- iceGatherer.state = 'completed';
- }
- // Emit a candidate with type endOfCandidates to make the samples
- // work. Edge requires addIceCandidate with this empty candidate
- // to start checking. The real solution is to signal
- // end-of-candidates to the other side when getting the null
- // candidate but some apps (like the samples) don't do that.
- event.candidate.candidate =
- 'candidate:1 1 udp 1 0.0.0.0 9 typ endOfCandidates';
- } else {
- // RTCIceCandidate doesn't have a component, needs to be added
- cand.component = iceTransport.component === 'RTCP' ? 2 : 1;
- event.candidate.candidate = SDPUtils.writeCandidate(cand);
- }
- // update local description.
- var sections = SDPUtils.splitSections(self.localDescription.sdp);
- if (event.candidate.candidate.indexOf('typ endOfCandidates')
- === -1) {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=' + event.candidate.candidate + '\r\n';
- } else {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=end-of-candidates\r\n';
- }
- self.localDescription.sdp = sections.join('');
- var complete = self.transceivers.every(function(transceiver) {
- return transceiver.iceGatherer &&
- transceiver.iceGatherer.state === 'completed';
- });
- // Emit candidate if localDescription is set.
- // Also emits null candidate when all gatherers are complete.
- switch (self.iceGatheringState) {
- case 'new':
- self._localIceCandidatesBuffer.push(event);
- if (end && complete) {
- self._localIceCandidatesBuffer.push(
- new Event('icecandidate'));
- }
- break;
- case 'gathering':
- self._emitBufferedCandidates();
- self.dispatchEvent(event);
- if (self.onicecandidate !== null) {
- self.onicecandidate(event);
- }
- if (complete) {
- self.dispatchEvent(new Event('icecandidate'));
- if (self.onicecandidate !== null) {
- self.onicecandidate(new Event('icecandidate'));
- }
- self.iceGatheringState = 'complete';
- }
- break;
- case 'complete':
- // should not happen... currently!
- break;
- default: // no-op.
- break;
- }
- };
- iceTransport.onicestatechange = function() {
- self._updateConnectionState();
- };
- var dtlsTransport = new RTCDtlsTransport(iceTransport);
- dtlsTransport.ondtlsstatechange = function() {
- self._updateConnectionState();
- };
- dtlsTransport.onerror = function() {
- // onerror does not set state to failed by itself.
- dtlsTransport.state = 'failed';
- self._updateConnectionState();
- };
- return {
- iceGatherer: iceGatherer,
- iceTransport: iceTransport,
- dtlsTransport: dtlsTransport
- };
- };
- // Start the RTP Sender and Receiver for a transceiver.
- window.RTCPeerConnection.prototype._transceive = function(transceiver,
- send, recv) {
- var params = this._getCommonCapabilities(transceiver.localCapabilities,
- transceiver.remoteCapabilities);
- if (send && transceiver.rtpSender) {
- params.encodings = transceiver.sendEncodingParameters;
- params.rtcp = {
- cname: SDPUtils.localCName
- };
- if (transceiver.recvEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
- }
- transceiver.rtpSender.send(params);
- }
- if (recv && transceiver.rtpReceiver) {
- // remove RTX field in Edge 14942
- if (transceiver.kind === 'video'
- && transceiver.recvEncodingParameters) {
- transceiver.recvEncodingParameters.forEach(function(p) {
- delete p.rtx;
- });
- }
- params.encodings = transceiver.recvEncodingParameters;
- params.rtcp = {
- cname: transceiver.cname
- };
- if (transceiver.sendEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
- }
- transceiver.rtpReceiver.receive(params);
- }
- };
- window.RTCPeerConnection.prototype.setLocalDescription =
- function(description) {
- var self = this;
- var sections;
- var sessionpart;
- if (description.type === 'offer') {
- // FIXME: What was the purpose of this empty if statement?
- // if (!this._pendingOffer) {
- // } else {
- if (this._pendingOffer) {
- // VERY limited support for SDP munging. Limited to:
- // * changing the order of codecs
- sections = SDPUtils.splitSections(description.sdp);
- sessionpart = sections.shift();
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var caps = SDPUtils.parseRtpParameters(mediaSection);
- self._pendingOffer[sdpMLineIndex].localCapabilities = caps;
- });
- this.transceivers = this._pendingOffer;
- delete this._pendingOffer;
- }
- } else if (description.type === 'answer') {
- sections = SDPUtils.splitSections(self.remoteDescription.sdp);
- sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var transceiver = self.transceivers[sdpMLineIndex];
- var iceGatherer = transceiver.iceGatherer;
- var iceTransport = transceiver.iceTransport;
- var dtlsTransport = transceiver.dtlsTransport;
- var localCapabilities = transceiver.localCapabilities;
- var remoteCapabilities = transceiver.remoteCapabilities;
- var rejected = mediaSection.split('\n', 1)[0]
- .split(' ', 2)[1] === '0';
- if (!rejected && !transceiver.isDatachannel) {
- var remoteIceParameters = SDPUtils.getIceParameters(
- mediaSection, sessionpart);
- if (isIceLite) {
- var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
- .map(function(cand) {
- return SDPUtils.parseCandidate(cand);
- })
- .filter(function(cand) {
- return cand.component === '1';
- });
- // ice-lite only includes host candidates in the SDP so we can
- // use setRemoteCandidates (which implies an
- // RTCIceCandidateComplete)
- if (cands.length) {
- iceTransport.setRemoteCandidates(cands);
- }
- }
- var remoteDtlsParameters = SDPUtils.getDtlsParameters(
- mediaSection, sessionpart);
- if (isIceLite) {
- remoteDtlsParameters.role = 'server';
- }
- if (!self.usingBundle || sdpMLineIndex === 0) {
- iceTransport.start(iceGatherer, remoteIceParameters,
- isIceLite ? 'controlling' : 'controlled');
- dtlsTransport.start(remoteDtlsParameters);
- }
- // Calculate intersection of capabilities.
- var params = self._getCommonCapabilities(localCapabilities,
- remoteCapabilities);
- // Start the RTCRtpSender. The RTCRtpReceiver for this
- // transceiver has already been started in setRemoteDescription.
- self._transceive(transceiver,
- params.codecs.length > 0,
- false);
- }
- });
- }
- this.localDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-local-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
- // If a success callback was provided, emit ICE candidates after it
- // has been executed. Otherwise, emit callback after the Promise is
- // resolved.
- var hasCallback = arguments.length > 1 &&
- typeof arguments[1] === 'function';
- if (hasCallback) {
- var cb = arguments[1];
- window.setTimeout(function() {
- cb();
- if (self.iceGatheringState === 'new') {
- self.iceGatheringState = 'gathering';
- }
- self._emitBufferedCandidates();
- }, 0);
- }
- var p = Promise.resolve();
- p.then(function() {
- if (!hasCallback) {
- if (self.iceGatheringState === 'new') {
- self.iceGatheringState = 'gathering';
- }
- // Usually candidates will be emitted earlier.
- window.setTimeout(self._emitBufferedCandidates.bind(self), 500);
- }
- });
- return p;
- };
- window.RTCPeerConnection.prototype.setRemoteDescription =
- function(description) {
- var self = this;
- var stream = new MediaStream();
- var receiverList = [];
- var sections = SDPUtils.splitSections(description.sdp);
- var sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- this.usingBundle = SDPUtils.matchPrefix(sessionpart,
- 'a=group:BUNDLE ').length > 0;
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].substr(2).split(' ');
- var kind = mline[0];
- var rejected = mline[1] === '0';
- var direction = SDPUtils.getDirection(mediaSection, sessionpart);
- var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:');
- if (mid.length) {
- mid = mid[0].substr(6);
- } else {
- mid = SDPUtils.generateIdentifier();
- }
- // Reject datachannels which are not implemented yet.
- if (kind === 'application' && mline[2] === 'DTLS/SCTP') {
- self.transceivers[sdpMLineIndex] = {
- mid: mid,
- isDatachannel: true
- };
- return;
- }
- var transceiver;
- var iceGatherer;
- var iceTransport;
- var dtlsTransport;
- var rtpSender;
- var rtpReceiver;
- var sendEncodingParameters;
- var recvEncodingParameters;
- var localCapabilities;
- var track;
- // FIXME: ensure the mediaSection has rtcp-mux set.
- var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);
- var remoteIceParameters;
- var remoteDtlsParameters;
- if (!rejected) {
- remoteIceParameters = SDPUtils.getIceParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters.role = 'client';
- }
- recvEncodingParameters =
- SDPUtils.parseRtpEncodingParameters(mediaSection);
- var cname;
- // Gets the first SSRC. Note that with RTX there might be multiple
- // SSRCs.
- var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(obj) {
- return obj.attribute === 'cname';
- })[0];
- if (remoteSsrc) {
- cname = remoteSsrc.value;
- }
- var isComplete = SDPUtils.matchPrefix(mediaSection,
- 'a=end-of-candidates', sessionpart).length > 0;
- var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
- .map(function(cand) {
- return SDPUtils.parseCandidate(cand);
- })
- .filter(function(cand) {
- return cand.component === '1';
- });
- if (description.type === 'offer' && !rejected) {
- var transports = self.usingBundle && sdpMLineIndex > 0 ? {
- iceGatherer: self.transceivers[0].iceGatherer,
- iceTransport: self.transceivers[0].iceTransport,
- dtlsTransport: self.transceivers[0].dtlsTransport
- } : self._createIceAndDtlsTransports(mid, sdpMLineIndex);
- if (isComplete) {
- transports.iceTransport.setRemoteCandidates(cands);
- }
- localCapabilities = RTCRtpReceiver.getCapabilities(kind);
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- sendEncodingParameters = [{
- ssrc: (2 * sdpMLineIndex + 2) * 1001
- }];
- rtpReceiver = new RTCRtpReceiver(transports.dtlsTransport, kind);
- track = rtpReceiver.track;
- receiverList.push([track, rtpReceiver]);
- // FIXME: not correct when there are multiple streams but that is
- // not currently supported in this shim.
- stream.addTrack(track);
- // FIXME: look at direction.
- if (self.localStreams.length > 0 &&
- self.localStreams[0].getTracks().length >= sdpMLineIndex) {
- var localTrack;
- if (kind === 'audio') {
- localTrack = self.localStreams[0].getAudioTracks()[0];
- } else if (kind === 'video') {
- localTrack = self.localStreams[0].getVideoTracks()[0];
- }
- if (localTrack) {
- rtpSender = new RTCRtpSender(localTrack,
- transports.dtlsTransport);
- }
- }
- self.transceivers[sdpMLineIndex] = {
- iceGatherer: transports.iceGatherer,
- iceTransport: transports.iceTransport,
- dtlsTransport: transports.dtlsTransport,
- localCapabilities: localCapabilities,
- remoteCapabilities: remoteCapabilities,
- rtpSender: rtpSender,
- rtpReceiver: rtpReceiver,
- kind: kind,
- mid: mid,
- cname: cname,
- sendEncodingParameters: sendEncodingParameters,
- recvEncodingParameters: recvEncodingParameters
- };
- // Start the RTCRtpReceiver now. The RTPSender is started in
- // setLocalDescription.
- self._transceive(self.transceivers[sdpMLineIndex],
- false,
- direction === 'sendrecv' || direction === 'sendonly');
- } else if (description.type === 'answer' && !rejected) {
- transceiver = self.transceivers[sdpMLineIndex];
- iceGatherer = transceiver.iceGatherer;
- iceTransport = transceiver.iceTransport;
- dtlsTransport = transceiver.dtlsTransport;
- rtpSender = transceiver.rtpSender;
- rtpReceiver = transceiver.rtpReceiver;
- sendEncodingParameters = transceiver.sendEncodingParameters;
- localCapabilities = transceiver.localCapabilities;
- self.transceivers[sdpMLineIndex].recvEncodingParameters =
- recvEncodingParameters;
- self.transceivers[sdpMLineIndex].remoteCapabilities =
- remoteCapabilities;
- self.transceivers[sdpMLineIndex].cname = cname;
- if ((isIceLite || isComplete) && cands.length) {
- iceTransport.setRemoteCandidates(cands);
- }
- if (!self.usingBundle || sdpMLineIndex === 0) {
- iceTransport.start(iceGatherer, remoteIceParameters,
- 'controlling');
- dtlsTransport.start(remoteDtlsParameters);
- }
- self._transceive(transceiver,
- direction === 'sendrecv' || direction === 'recvonly',
- direction === 'sendrecv' || direction === 'sendonly');
- if (rtpReceiver &&
- (direction === 'sendrecv' || direction === 'sendonly')) {
- track = rtpReceiver.track;
- receiverList.push([track, rtpReceiver]);
- stream.addTrack(track);
- } else {
- // FIXME: actually the receiver should be created later.
- delete transceiver.rtpReceiver;
- }
- }
- });
- this.remoteDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-remote-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
- if (stream.getTracks().length) {
- self.remoteStreams.push(stream);
- window.setTimeout(function() {
- var event = new Event('addstream');
- event.stream = stream;
- self.dispatchEvent(event);
- if (self.onaddstream !== null) {
- window.setTimeout(function() {
- self.onaddstream(event);
- }, 0);
- }
- receiverList.forEach(function(item) {
- var track = item[0];
- var receiver = item[1];
- var trackEvent = new Event('track');
- trackEvent.track = track;
- trackEvent.receiver = receiver;
- trackEvent.streams = [stream];
- self.dispatchEvent(event);
- if (self.ontrack !== null) {
- window.setTimeout(function() {
- self.ontrack(trackEvent);
- }, 0);
- }
- });
- }, 0);
- }
- if (arguments.length > 1 && typeof arguments[1] === 'function') {
- window.setTimeout(arguments[1], 0);
- }
- return Promise.resolve();
- };
- window.RTCPeerConnection.prototype.close = function() {
- this.transceivers.forEach(function(transceiver) {
- /* not yet
- if (transceiver.iceGatherer) {
- transceiver.iceGatherer.close();
- }
- */
- if (transceiver.iceTransport) {
- transceiver.iceTransport.stop();
- }
- if (transceiver.dtlsTransport) {
- transceiver.dtlsTransport.stop();
- }
- if (transceiver.rtpSender) {
- transceiver.rtpSender.stop();
- }
- if (transceiver.rtpReceiver) {
- transceiver.rtpReceiver.stop();
- }
- });
- // FIXME: clean up tracks, local streams, remote streams, etc
- this._updateSignalingState('closed');
- };
- // Update the signaling state.
- window.RTCPeerConnection.prototype._updateSignalingState =
- function(newState) {
- this.signalingState = newState;
- var event = new Event('signalingstatechange');
- this.dispatchEvent(event);
- if (this.onsignalingstatechange !== null) {
- this.onsignalingstatechange(event);
- }
- };
- // Determine whether to fire the negotiationneeded event.
- window.RTCPeerConnection.prototype._maybeFireNegotiationNeeded =
- function() {
- // Fire away (for now).
- var event = new Event('negotiationneeded');
- this.dispatchEvent(event);
- if (this.onnegotiationneeded !== null) {
- this.onnegotiationneeded(event);
- }
- };
- // Update the connection state.
- window.RTCPeerConnection.prototype._updateConnectionState = function() {
- var self = this;
- var newState;
- var states = {
- 'new': 0,
- closed: 0,
- connecting: 0,
- checking: 0,
- connected: 0,
- completed: 0,
- failed: 0
- };
- this.transceivers.forEach(function(transceiver) {
- states[transceiver.iceTransport.state]++;
- states[transceiver.dtlsTransport.state]++;
- });
- // ICETransport.completed and connected are the same for this purpose.
- states.connected += states.completed;
- newState = 'new';
- if (states.failed > 0) {
- newState = 'failed';
- } else if (states.connecting > 0 || states.checking > 0) {
- newState = 'connecting';
- } else if (states.disconnected > 0) {
- newState = 'disconnected';
- } else if (states.new > 0) {
- newState = 'new';
- } else if (states.connected > 0 || states.completed > 0) {
- newState = 'connected';
- }
- if (newState !== self.iceConnectionState) {
- self.iceConnectionState = newState;
- var event = new Event('iceconnectionstatechange');
- this.dispatchEvent(event);
- if (this.oniceconnectionstatechange !== null) {
- this.oniceconnectionstatechange(event);
- }
- }
- };
- window.RTCPeerConnection.prototype.createOffer = function() {
- var self = this;
- if (this._pendingOffer) {
- throw new Error('createOffer called while there is a pending offer.');
- }
- var offerOptions;
- if (arguments.length === 1 && typeof arguments[0] !== 'function') {
- offerOptions = arguments[0];
- } else if (arguments.length === 3) {
- offerOptions = arguments[2];
- }
- var tracks = [];
- var numAudioTracks = 0;
- var numVideoTracks = 0;
- // Default to sendrecv.
- if (this.localStreams.length) {
- numAudioTracks = this.localStreams[0].getAudioTracks().length;
- numVideoTracks = this.localStreams[0].getVideoTracks().length;
- }
- // Determine number of audio and video tracks we need to send/recv.
- if (offerOptions) {
- // Reject Chrome legacy constraints.
- if (offerOptions.mandatory || offerOptions.optional) {
- throw new TypeError(
- 'Legacy mandatory/optional constraints not supported.');
- }
- if (offerOptions.offerToReceiveAudio !== undefined) {
- numAudioTracks = offerOptions.offerToReceiveAudio;
- }
- if (offerOptions.offerToReceiveVideo !== undefined) {
- numVideoTracks = offerOptions.offerToReceiveVideo;
- }
- }
- if (this.localStreams.length) {
- // Push local streams.
- this.localStreams[0].getTracks().forEach(function(track) {
- tracks.push({
- kind: track.kind,
- track: track,
- wantReceive: track.kind === 'audio' ?
- numAudioTracks > 0 : numVideoTracks > 0
- });
- if (track.kind === 'audio') {
- numAudioTracks--;
- } else if (track.kind === 'video') {
- numVideoTracks--;
- }
- });
- }
- // Create M-lines for recvonly streams.
- while (numAudioTracks > 0 || numVideoTracks > 0) {
- if (numAudioTracks > 0) {
- tracks.push({
- kind: 'audio',
- wantReceive: true
- });
- numAudioTracks--;
- }
- if (numVideoTracks > 0) {
- tracks.push({
- kind: 'video',
- wantReceive: true
- });
- numVideoTracks--;
- }
- }
- var sdp = SDPUtils.writeSessionBoilerplate();
- var transceivers = [];
- tracks.forEach(function(mline, sdpMLineIndex) {
- // For each track, create an ice gatherer, ice transport,
- // dtls transport, potentially rtpsender and rtpreceiver.
- var track = mline.track;
- var kind = mline.kind;
- var mid = SDPUtils.generateIdentifier();
- var transports = self.usingBundle && sdpMLineIndex > 0 ? {
- iceGatherer: transceivers[0].iceGatherer,
- iceTransport: transceivers[0].iceTransport,
- dtlsTransport: transceivers[0].dtlsTransport
- } : self._createIceAndDtlsTransports(mid, sdpMLineIndex);
- var localCapabilities = RTCRtpSender.getCapabilities(kind);
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- localCapabilities.codecs.forEach(function(codec) {
- // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
- // by adding level-asymmetry-allowed=1
- if (codec.name === 'H264' &&
- codec.parameters['level-asymmetry-allowed'] === undefined) {
- codec.parameters['level-asymmetry-allowed'] = '1';
- }
- });
- var rtpSender;
- var rtpReceiver;
- // generate an ssrc now, to be used later in rtpSender.send
- var sendEncodingParameters = [{
- ssrc: (2 * sdpMLineIndex + 1) * 1001
- }];
- if (track) {
- rtpSender = new RTCRtpSender(track, transports.dtlsTransport);
- }
- if (mline.wantReceive) {
- rtpReceiver = new RTCRtpReceiver(transports.dtlsTransport, kind);
- }
- transceivers[sdpMLineIndex] = {
- iceGatherer: transports.iceGatherer,
- iceTransport: transports.iceTransport,
- dtlsTransport: transports.dtlsTransport,
- localCapabilities: localCapabilities,
- remoteCapabilities: null,
- rtpSender: rtpSender,
- rtpReceiver: rtpReceiver,
- kind: kind,
- mid: mid,
- sendEncodingParameters: sendEncodingParameters,
- recvEncodingParameters: null
- };
- });
- if (this.usingBundle) {
- sdp += 'a=group:BUNDLE ' + transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- tracks.forEach(function(mline, sdpMLineIndex) {
- var transceiver = transceivers[sdpMLineIndex];
- sdp += SDPUtils.writeMediaSection(transceiver,
- transceiver.localCapabilities, 'offer', self.localStreams[0]);
- });
- this._pendingOffer = transceivers;
- var desc = new RTCSessionDescription({
- type: 'offer',
- sdp: sdp
- });
- if (arguments.length && typeof arguments[0] === 'function') {
- window.setTimeout(arguments[0], 0, desc);
- }
- return Promise.resolve(desc);
- };
- window.RTCPeerConnection.prototype.createAnswer = function() {
- var self = this;
- var sdp = SDPUtils.writeSessionBoilerplate();
- if (this.usingBundle) {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- this.transceivers.forEach(function(transceiver) {
- if (transceiver.isDatachannel) {
- sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
- 'c=IN IP4 0.0.0.0\r\n' +
- 'a=mid:' + transceiver.mid + '\r\n';
- return;
- }
- // Calculate intersection of capabilities.
- var commonCapabilities = self._getCommonCapabilities(
- transceiver.localCapabilities,
- transceiver.remoteCapabilities);
- sdp += SDPUtils.writeMediaSection(transceiver, commonCapabilities,
- 'answer', self.localStreams[0]);
- });
- var desc = new RTCSessionDescription({
- type: 'answer',
- sdp: sdp
- });
- if (arguments.length && typeof arguments[0] === 'function') {
- window.setTimeout(arguments[0], 0, desc);
- }
- return Promise.resolve(desc);
- };
- window.RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
- if (!candidate) {
- this.transceivers.forEach(function(transceiver) {
- transceiver.iceTransport.addRemoteCandidate({});
- });
- } else {
- var mLineIndex = candidate.sdpMLineIndex;
- if (candidate.sdpMid) {
- for (var i = 0; i < this.transceivers.length; i++) {
- if (this.transceivers[i].mid === candidate.sdpMid) {
- mLineIndex = i;
- break;
- }
- }
- }
- var transceiver = this.transceivers[mLineIndex];
- if (transceiver) {
- var cand = Object.keys(candidate.candidate).length > 0 ?
- SDPUtils.parseCandidate(candidate.candidate) : {};
- // Ignore Chrome's invalid candidates since Edge does not like them.
- if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
- return;
- }
- // Ignore RTCP candidates, we assume RTCP-MUX.
- if (cand.component !== '1') {
- return;
- }
- // A dirty hack to make samples work.
- if (cand.type === 'endOfCandidates') {
- cand = {};
- }
- transceiver.iceTransport.addRemoteCandidate(cand);
- // update the remoteDescription.
- var sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[mLineIndex + 1] += (cand.type ? candidate.candidate.trim()
- : 'a=end-of-candidates') + '\r\n';
- this.remoteDescription.sdp = sections.join('');
- }
- }
- if (arguments.length > 1 && typeof arguments[1] === 'function') {
- window.setTimeout(arguments[1], 0);
- }
- return Promise.resolve();
- };
- window.RTCPeerConnection.prototype.getStats = function() {
- var promises = [];
- this.transceivers.forEach(function(transceiver) {
- ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
- 'dtlsTransport'].forEach(function(method) {
- if (transceiver[method]) {
- promises.push(transceiver[method].getStats());
- }
- });
- });
- var cb = arguments.length > 1 && typeof arguments[1] === 'function' &&
- arguments[1];
- return new Promise(function(resolve) {
- // shim getStats with maplike support
- var results = new Map();
- Promise.all(promises).then(function(res) {
- res.forEach(function(result) {
- Object.keys(result).forEach(function(id) {
- results.set(id, result[id]);
- results[id] = result[id];
- });
- });
- if (cb) {
- window.setTimeout(cb, 0, results);
- }
- resolve(results);
- });
- });
- };
- }
- };
- // Expose public methods.
- module.exports = {
- shimPeerConnection: edgeShim.shimPeerConnection,
- shimGetUserMedia: require('./getusermedia')
- };
- },{"../utils":50,"./getusermedia":46,"sdp":41}],46:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- // Expose public methods.
- module.exports = function() {
- var shimError_ = function(e) {
- return {
- name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
- message: e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name;
- }
- };
- };
- // getUserMedia error shim.
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).catch(function(e) {
- return Promise.reject(shimError_(e));
- });
- };
- };
- },{}],47:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- var browserDetails = require('../utils').browserDetails;
- var firefoxShim = {
- shimOnTrack: function() {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- this.removeEventListener('addstream', this._ontrackpoly);
- }
- this.addEventListener('track', this._ontrack = f);
- this.addEventListener('addstream', this._ontrackpoly = function(e) {
- e.stream.getTracks().forEach(function(track) {
- var event = new Event('track');
- event.track = track;
- event.receiver = {track: track};
- event.streams = [e.stream];
- this.dispatchEvent(event);
- }.bind(this));
- }.bind(this));
- }
- });
- }
- },
- shimSourceObject: function() {
- // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
- if (typeof window === 'object') {
- if (window.HTMLMediaElement &&
- !('srcObject' in window.HTMLMediaElement.prototype)) {
- // Shim the srcObject property, once, when HTMLMediaElement is found.
- Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
- get: function() {
- return this.mozSrcObject;
- },
- set: function(stream) {
- this.mozSrcObject = stream;
- }
- });
- }
- }
- },
- shimPeerConnection: function() {
- if (typeof window !== 'object' || !(window.RTCPeerConnection ||
- window.mozRTCPeerConnection)) {
- return; // probably media.peerconnection.enabled=false in about:config
- }
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (browserDetails.version < 38) {
- // .urls is not supported in FF < 38.
- // create RTCIceServers with a single url.
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (server.hasOwnProperty('urls')) {
- for (var j = 0; j < server.urls.length; j++) {
- var newServer = {
- url: server.urls[j]
- };
- if (server.urls[j].indexOf('turn') === 0) {
- newServer.username = server.username;
- newServer.credential = server.credential;
- }
- newIceServers.push(newServer);
- }
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- }
- return new mozRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = mozRTCPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if (mozRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return mozRTCPeerConnection.generateCertificate;
- }
- });
- }
- window.RTCSessionDescription = mozRTCSessionDescription;
- window.RTCIceCandidate = mozRTCIceCandidate;
- }
- // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- RTCIceCandidate : RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- RTCPeerConnection.prototype.addIceCandidate;
- RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
- if (browserDetails.version < 48) {
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- var map = new Map();
- Object.keys(stats).forEach(function(key) {
- map.set(key, stats[key]);
- map[key] = stats[key];
- });
- return map;
- };
- var nativeGetStats = RTCPeerConnection.prototype.getStats;
- RTCPeerConnection.prototype.getStats = function(selector, onSucc, onErr) {
- return nativeGetStats.apply(this, [selector || null])
- .then(function(stats) {
- return makeMapStats(stats);
- })
- .then(onSucc, onErr);
- };
- }
- }
- };
- // Expose public methods.
- module.exports = {
- shimOnTrack: firefoxShim.shimOnTrack,
- shimSourceObject: firefoxShim.shimSourceObject,
- shimPeerConnection: firefoxShim.shimPeerConnection,
- shimGetUserMedia: require('./getusermedia')
- };
- },{"../utils":50,"./getusermedia":48}],48:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- var logging = require('../utils').log;
- var browserDetails = require('../utils').browserDetails;
- // Expose public methods.
- module.exports = function() {
- var shimError_ = function(e) {
- return {
- name: {
- SecurityError: 'NotAllowedError',
- PermissionDeniedError: 'NotAllowedError'
- }[e.name] || e.name,
- message: {
- 'The operation is insecure.': 'The request is not allowed by the ' +
- 'user agent or the platform in the current context.'
- }[e.message] || e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
- // getUserMedia constraints shim.
- var getUserMedia_ = function(constraints, onSuccess, onError) {
- var constraintsToFF37_ = function(c) {
- if (typeof c !== 'object' || c.require) {
- return c;
- }
- var require = [];
- Object.keys(c).forEach(function(key) {
- if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
- return;
- }
- var r = c[key] = (typeof c[key] === 'object') ?
- c[key] : {ideal: c[key]};
- if (r.min !== undefined ||
- r.max !== undefined || r.exact !== undefined) {
- require.push(key);
- }
- if (r.exact !== undefined) {
- if (typeof r.exact === 'number') {
- r. min = r.max = r.exact;
- } else {
- c[key] = r.exact;
- }
- delete r.exact;
- }
- if (r.ideal !== undefined) {
- c.advanced = c.advanced || [];
- var oc = {};
- if (typeof r.ideal === 'number') {
- oc[key] = {min: r.ideal, max: r.ideal};
- } else {
- oc[key] = r.ideal;
- }
- c.advanced.push(oc);
- delete r.ideal;
- if (!Object.keys(r).length) {
- delete c[key];
- }
- }
- });
- if (require.length) {
- c.require = require;
- }
- return c;
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- if (browserDetails.version < 38) {
- logging('spec: ' + JSON.stringify(constraints));
- if (constraints.audio) {
- constraints.audio = constraintsToFF37_(constraints.audio);
- }
- if (constraints.video) {
- constraints.video = constraintsToFF37_(constraints.video);
- }
- logging('ff37: ' + JSON.stringify(constraints));
- }
- return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
- onError(shimError_(e));
- });
- };
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- getUserMedia_(constraints, resolve, reject);
- });
- };
- // Shim for mediaDevices on older versions.
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
- addEventListener: function() { },
- removeEventListener: function() { }
- };
- }
- navigator.mediaDevices.enumerateDevices =
- navigator.mediaDevices.enumerateDevices || function() {
- return new Promise(function(resolve) {
- var infos = [
- {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
- {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
- ];
- resolve(infos);
- });
- };
- if (browserDetails.version < 41) {
- // Work around http://bugzil.la/1169665
- var orgEnumerateDevices =
- navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
- navigator.mediaDevices.enumerateDevices = function() {
- return orgEnumerateDevices().then(undefined, function(e) {
- if (e.name === 'NotFoundError') {
- return [];
- }
- throw e;
- });
- };
- }
- if (browserDetails.version < 49) {
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).then(function(stream) {
- // Work around https://bugzil.la/802326
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('The object can not be found here.',
- 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- };
- }
- navigator.getUserMedia = function(constraints, onSuccess, onError) {
- if (browserDetails.version < 44) {
- return getUserMedia_(constraints, onSuccess, onError);
- }
- // Replace Firefox 44+'s deprecation warning with unprefixed version.
- console.warn('navigator.getUserMedia has been replaced by ' +
- 'navigator.mediaDevices.getUserMedia');
- navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
- };
- };
- },{"../utils":50}],49:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- 'use strict';
- var safariShim = {
- // TODO: DrAlex, should be here, double check against LayoutTests
- // shimOnTrack: function() { },
- // TODO: once the back-end for the mac port is done, add.
- // TODO: check for webkitGTK+
- // shimPeerConnection: function() { },
- shimGetUserMedia: function() {
- navigator.getUserMedia = navigator.webkitGetUserMedia;
- }
- };
- // Expose public methods.
- module.exports = {
- shimGetUserMedia: safariShim.shimGetUserMedia
- // TODO
- // shimOnTrack: safariShim.shimOnTrack,
- // shimPeerConnection: safariShim.shimPeerConnection
- };
- },{}],50:[function(require,module,exports){
- /*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree.
- */
- /* eslint-env node */
- 'use strict';
- var logDisabled_ = true;
- // Utility methods.
- var utils = {
- disableLog: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- logDisabled_ = bool;
- return (bool) ? 'adapter.js logging disabled' :
- 'adapter.js logging enabled';
- },
- log: function() {
- if (typeof window === 'object') {
- if (logDisabled_) {
- return;
- }
- if (typeof console !== 'undefined' && typeof console.log === 'function') {
- console.log.apply(console, arguments);
- }
- }
- },
- /**
- * Extract browser version out of the provided user agent string.
- *
- * @param {!string} uastring userAgent string.
- * @param {!string} expr Regular expression used as match criteria.
- * @param {!number} pos position in the version string to be returned.
- * @return {!number} browser version.
- */
- extractVersion: function(uastring, expr, pos) {
- var match = uastring.match(expr);
- return match && match.length >= pos && parseInt(match[pos], 10);
- },
- /**
- * Browser detector.
- *
- * @return {object} result containing browser and version
- * properties.
- */
- detectBrowser: function() {
- // Returned result object.
- var result = {};
- result.browser = null;
- result.version = null;
- // Fail early if it's not a browser
- if (typeof window === 'undefined' || !window.navigator) {
- result.browser = 'Not a browser.';
- return result;
- }
- // Firefox.
- if (navigator.mozGetUserMedia) {
- result.browser = 'firefox';
- result.version = this.extractVersion(navigator.userAgent,
- /Firefox\/([0-9]+)\./, 1);
- // all webkit-based browsers
- } else if (navigator.webkitGetUserMedia) {
- // Chrome, Chromium, Webview, Opera, all use the chrome shim for now
- if (window.webkitRTCPeerConnection) {
- result.browser = 'chrome';
- result.version = this.extractVersion(navigator.userAgent,
- /Chrom(e|ium)\/([0-9]+)\./, 2);
- // Safari or unknown webkit-based
- // for the time being Safari has support for MediaStreams but not webRTC
- } else {
- // Safari UA substrings of interest for reference:
- // - webkit version: AppleWebKit/602.1.25 (also used in Op,Cr)
- // - safari UI version: Version/9.0.3 (unique to Safari)
- // - safari UI webkit version: Safari/601.4.4 (also used in Op,Cr)
- //
- // if the webkit version and safari UI webkit versions are equals,
- // ... this is a stable version.
- //
- // only the internal webkit version is important today to know if
- // media streams are supported
- //
- if (navigator.userAgent.match(/Version\/(\d+).(\d+)/)) {
- result.browser = 'safari';
- result.version = this.extractVersion(navigator.userAgent,
- /AppleWebKit\/([0-9]+)\./, 1);
- // unknown webkit-based browser
- } else {
- result.browser = 'Unsupported webkit-based browser ' +
- 'with GUM support but no WebRTC support.';
- return result;
- }
- }
- // Edge.
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) {
- result.browser = 'edge';
- result.version = this.extractVersion(navigator.userAgent,
- /Edge\/(\d+).(\d+)$/, 2);
- // Default fallthrough: not supported.
- } else {
- result.browser = 'Not a supported browser.';
- return result;
- }
- return result;
- }
- };
- // Export.
- module.exports = {
- log: utils.log,
- disableLog: utils.disableLog,
- browserDetails: utils.detectBrowser(),
- extractVersion: utils.extractVersion
- };
- },{}],51:[function(require,module,exports){
- module.exports={
- "name": "jssip",
- "title": "JsSIP",
- "description": "the Javascript SIP library",
- "version": "3.0.13",
- "homepage": "http://jssip.net",
- "author": "José Luis Millán <jmillan@aliax.net> (https://github.com/jmillan)",
- "contributors": [
- "Iñaki Baz Castillo <ibc@aliax.net> (https://github.com/ibc)",
- "Saúl Ibarra Corretgé <saghul@gmail.com> (https://github.com/saghul)"
- ],
- "main": "lib/JsSIP.js",
- "keywords": [
- "sip",
- "websocket",
- "webrtc",
- "node",
- "browser",
- "library"
- ],
- "license": "MIT",
- "repository": {
- "type": "git",
- "url": "https://github.com/versatica/JsSIP.git"
- },
- "bugs": {
- "url": "https://github.com/versatica/JsSIP/issues"
- },
- "dependencies": {
- "debug": "^2.6.8",
- "sdp-transform": "^2.3.0",
- "webrtc-adapter": "^3.4.3"
- },
- "devDependencies": {
- "browserify": "^14.3.0",
- "gulp": "git+https://github.com/gulpjs/gulp.git#4.0",
- "gulp-expect-file": "0.0.7",
- "gulp-header": "1.8.8",
- "gulp-jshint": "^2.0.4",
- "gulp-nodeunit-runner": "^0.2.2",
- "gulp-rename": "^1.2.2",
- "gulp-uglify": "^3.0.0",
- "gulp-util": "^3.0.8",
- "jshint": "^2.9.4",
- "jshint-stylish": "^2.2.1",
- "pegjs": "0.7.0",
- "vinyl-buffer": "^1.0.0",
- "vinyl-source-stream": "^1.1.0"
- },
- "scripts": {
- "test": "gulp test"
- }
- }
- },{}]},{},[7])(7)
- });
|