|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000 |
- ###############################################################################
- #
- # The MIT License (MIT)
- #
- # Copyright (c) typedef int GmbH
- #
- # 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.
- #
- ###############################################################################
-
- import re
- import binascii
- import textwrap
- from pprint import pformat
- from typing import Any, Dict, Optional
-
- import autobahn
- from autobahn.util import hlval
- from autobahn.wamp.exception import ProtocolError, InvalidUriError
- from autobahn.wamp.role import ROLE_NAME_TO_CLASS
-
- try:
- import cbor2
- import flatbuffers
- from autobahn.wamp import message_fbs
- except ImportError:
- _HAS_WAMP_FLATBUFFERS = False
- else:
- _HAS_WAMP_FLATBUFFERS = True
-
- __all__ = ('Message',
- 'Hello',
- 'Welcome',
- 'Abort',
- 'Challenge',
- 'Authenticate',
- 'Goodbye',
- 'Error',
- 'Publish',
- 'Published',
- 'Subscribe',
- 'Subscribed',
- 'Unsubscribe',
- 'Unsubscribed',
- 'Event',
- 'Call',
- 'Cancel',
- 'Result',
- 'Register',
- 'Registered',
- 'Unregister',
- 'Unregistered',
- 'Invocation',
- 'Interrupt',
- 'Yield',
- 'check_or_raise_uri',
- 'check_or_raise_realm_name',
- 'check_or_raise_id',
- 'check_or_raise_extra',
- 'is_valid_enc_algo',
- 'is_valid_enc_serializer',
- 'identify_realm_name_category',
- 'PAYLOAD_ENC_CRYPTO_BOX',
- 'PAYLOAD_ENC_MQTT',
- 'PAYLOAD_ENC_STANDARD_IDENTIFIERS')
-
- # all realm names in Autobahn/Crossbar.io must match this
- _URI_PAT_REALM_NAME = re.compile(r"^[A-Za-z][A-Za-z\d_\-@\.]{2,254}$")
-
- # if Ethereum addresses are enabled, realm names which are "0x" prefixed Ethereum addresses are also valid
- _URI_PAT_REALM_NAME_ETH = re.compile(r"^0x([A-Fa-f\d]{40})$")
-
- # realms names might also specifically match ENS URIs
- _URI_PAT_REALM_NAME_ENS = re.compile(r"^([a-z\d_\-@\.]{2,250})\.eth$")
-
- # since WAMP recommends using reverse dotted notation, reverse ENS names can be checked with this pattern
- _URI_PAT_REALM_NAME_ENS_REVERSE = re.compile(r"^eth\.([a-z\d_\-@\.]{2,250})$")
-
- # strict URI check allowing empty URI components
- _URI_PAT_STRICT_EMPTY = re.compile(r"^(([\da-z_]+\.)|\.)*([\da-z_]+)?$")
-
- # loose URI check allowing empty URI components
- _URI_PAT_LOOSE_EMPTY = re.compile(r"^(([^\s\.#]+\.)|\.)*([^\s\.#]+)?$")
-
- # strict URI check disallowing empty URI components
- _URI_PAT_STRICT_NON_EMPTY = re.compile(r"^([\da-z_]+\.)*([\da-z_]+)$")
-
- # loose URI check disallowing empty URI components
- _URI_PAT_LOOSE_NON_EMPTY = re.compile(r"^([^\s\.#]+\.)*([^\s\.#]+)$")
-
- # strict URI check disallowing empty URI components in all but the last component
- _URI_PAT_STRICT_LAST_EMPTY = re.compile(r"^([\da-z_]+\.)*([\da-z_]*)$")
-
- # loose URI check disallowing empty URI components in all but the last component
- _URI_PAT_LOOSE_LAST_EMPTY = re.compile(r"^([^\s\.#]+\.)*([^\s\.#]*)$")
-
- # custom (=implementation specific) WAMP attributes (used in WAMP message details/options)
- _CUSTOM_ATTRIBUTE = re.compile(r"^x_([a-z][\da-z_]+)?$")
-
- # Value for algo attribute in end-to-end encrypted messages using cryptobox, which
- # is a scheme based on Curve25519, SHA512, Salsa20 and Poly1305.
- # See: http://cr.yp.to/highspeed/coolnacl-20120725.pdf
- PAYLOAD_ENC_CRYPTO_BOX = 'cryptobox'
-
- # Payload transparency identifier for MQTT payloads (which are arbitrary binary).
- PAYLOAD_ENC_MQTT = 'mqtt'
-
- # Payload transparency identifier for XBR payloads
- PAYLOAD_ENC_XBR = 'xbr'
-
- # Payload transparency algorithm identifiers from the WAMP spec.
- PAYLOAD_ENC_STANDARD_IDENTIFIERS = [PAYLOAD_ENC_CRYPTO_BOX, PAYLOAD_ENC_MQTT, PAYLOAD_ENC_XBR]
-
- # Payload transparency serializer identifiers from the WAMP spec.
- PAYLOAD_ENC_STANDARD_SERIALIZERS = ['json', 'msgpack', 'cbor', 'ubjson', 'flatbuffers']
-
- ENC_ALGO_NONE = 0
- ENC_ALGO_CRYPTOBOX = 1
- ENC_ALGO_MQTT = 2
- ENC_ALGO_XBR = 3
-
- ENC_ALGOS = {
- ENC_ALGO_NONE: 'null',
- ENC_ALGO_CRYPTOBOX: 'cryptobox',
- ENC_ALGO_MQTT: 'mqtt',
- ENC_ALGO_XBR: 'xbr',
- }
-
- ENC_ALGOS_FROMSTR = {key: value for value, key in ENC_ALGOS.items()}
-
- ENC_SER_NONE = 0
- ENC_SER_JSON = 1
- ENC_SER_MSGPACK = 2
- ENC_SER_CBOR = 3
- ENC_SER_UBJSON = 4
- ENC_SER_OPAQUE = 5
- ENC_SER_FLATBUFFERS = 6
-
- ENC_SERS = {
- ENC_SER_NONE: 'null',
- ENC_SER_JSON: 'json',
- ENC_SER_MSGPACK: 'msgpack',
- ENC_SER_CBOR: 'cbor',
- ENC_SER_UBJSON: 'ubjson',
- ENC_SER_OPAQUE: 'opaque',
- ENC_SER_FLATBUFFERS: 'flatbuffers',
- }
-
- ENC_SERS_FROMSTR = {key: value for value, key in ENC_SERS.items()}
-
-
- def is_valid_enc_algo(enc_algo):
- """
- For WAMP payload transparency mode, check if the provided ``enc_algo``
- identifier in the WAMP message is a valid one.
-
- Currently defined standard identifiers are:
-
- * ``"cryptobox"``
- * ``"mqtt"``
- * ``"xbr"``
-
- Users can select arbitrary identifiers too, but these MUST start with ``"x_"``.
-
- :param enc_algo: The payload transparency algorithm identifier to check.
- :type enc_algo: str
-
- :returns: Returns ``True`` if and only if the payload transparency
- algorithm identifier is valid.
- :rtype: bool
- """
- return type(enc_algo) == str and (enc_algo in PAYLOAD_ENC_STANDARD_IDENTIFIERS or _CUSTOM_ATTRIBUTE.match(enc_algo))
-
-
- def is_valid_enc_serializer(enc_serializer):
- """
- For WAMP payload transparency mode, check if the provided ``enc_serializer``
- identifier in the WAMP message is a valid one.
-
- Currently, the only standard defined identifier are
-
- * ``"json"``
- * ``"msgpack"``
- * ``"cbor"``
- * ``"ubjson"``
- * ``"flatbuffers"``
-
- Users can select arbitrary identifiers too, but these MUST start with ``"x_"``.
-
- :param enc_serializer: The payload transparency serializer identifier to check.
- :type enc_serializer: str
-
- :returns: Returns ``True`` if and only if the payload transparency
- serializer identifier is valid.
- :rtype: bool
- """
- return type(enc_serializer) == str and (enc_serializer in PAYLOAD_ENC_STANDARD_SERIALIZERS or _CUSTOM_ATTRIBUTE.match(enc_serializer))
-
-
- def b2a(data, max_len=40):
- if type(data) == str:
- s = data
- elif type(data) == bytes:
- s = binascii.b2a_hex(data).decode('ascii')
- elif data is None:
- s = '-'
- else:
- s = '{}'.format(data)
- if len(s) > max_len:
- return s[:max_len] + '..'
- else:
- return s
-
-
- def identify_realm_name_category(value: Any) -> Optional[str]:
- """
- Identify the real name category of the given value:
-
- * ``"standalone"``: A normal, standalone WAMP realm name, e.g. ``"realm1"``.
- * ``"eth"``: An Ethereum address, e.g. ``"0xe59C7418403CF1D973485B36660728a5f4A8fF9c"``.
- * ``"ens"``: An Ethereum ENS name, e.g. ``"wamp-proto.eth"``.
- * ``"reverse_ens"``: An Ethereum ENS name in reverse notation, e.g. ``"eth.wamp-proto"``.
- * ``None``: The value is not a WAMP realm name.
-
- :param value: The value for which to identify realm name category.
- :return: The category identified, one of ``["standalone", "eth", "ens", "reverse-ens"]``
- or ``None``.
- """
- if type(value) != str:
- return None
- if _URI_PAT_REALM_NAME.match(value):
- if _URI_PAT_REALM_NAME_ENS.match(value):
- return 'ens'
- elif _URI_PAT_REALM_NAME_ENS_REVERSE.match(value):
- return 'reverse_ens'
- else:
- return 'standalone'
- elif _URI_PAT_REALM_NAME_ETH.match(value):
- return 'eth'
- else:
- return None
-
-
- def check_or_raise_uri(value: Any, message: str = "WAMP message invalid", strict: bool = False,
- allow_empty_components: bool = False, allow_last_empty: bool = False,
- allow_none: bool = False) -> str:
- """
- Check a value for being a valid WAMP URI.
-
- If the value is not a valid WAMP URI is invalid, raises :class:`autobahn.wamp.exception.InvalidUriError`,
- otherwise returns the value.
-
- :param value: The value to check.
- :param message: Prefix for message in exception raised when value is invalid.
- :param strict: If ``True``, do a strict check on the URI (the WAMP spec SHOULD behavior).
- :param allow_empty_components: If ``True``, allow empty URI components (for pattern based
- subscriptions and registrations).
- :param allow_last_empty: If ``True``, allow the last URI component to be empty (for prefix based
- subscriptions and registrations).
- :param allow_none: If ``True``, allow ``None`` for URIs.
- :returns: The URI value (if valid).
- :raises: instance of :class:`autobahn.wamp.exception.InvalidUriError`
- """
- if value is None:
- if allow_none:
- return
- else:
- raise InvalidUriError("{0}: URI cannot be null".format(message))
-
- if type(value) != str:
- if not (value is None and allow_none):
- raise InvalidUriError("{0}: invalid type {1} for URI".format(message, type(value)))
-
- if strict:
- if allow_last_empty:
- pat = _URI_PAT_STRICT_LAST_EMPTY
- elif allow_empty_components:
- pat = _URI_PAT_STRICT_EMPTY
- else:
- pat = _URI_PAT_STRICT_NON_EMPTY
- else:
- if allow_last_empty:
- pat = _URI_PAT_LOOSE_LAST_EMPTY
- elif allow_empty_components:
- pat = _URI_PAT_LOOSE_EMPTY
- else:
- pat = _URI_PAT_LOOSE_NON_EMPTY
-
- if not pat.match(value):
- raise InvalidUriError('{0}: invalid value "{1}" for URI (did not match pattern "{2}" with options strict={3}, allow_empty_components={4}, allow_last_empty={5}, allow_none={6})'.format(message, value, pat.pattern, strict, allow_empty_components, allow_last_empty, allow_none))
- else:
- return value
-
-
- def check_or_raise_realm_name(value, message="WAMP message invalid", allow_eth=True):
- """
- Check a value for being a valid WAMP URI.
-
- If the value is not a valid WAMP URI is invalid, raises :class:`autobahn.wamp.exception.InvalidUriError`,
- otherwise returns the value.
-
- :param value: The value to check, e.g. ``"realm1"`` or ``"com.example.myapp"`` or ``"eth.example"``.
- :param message: Prefix for message in exception raised when value is invalid.
- :param allow_eth: If ``True``, allow Ethereum addresses as realm names,
- e.g. ``"0xe59C7418403CF1D973485B36660728a5f4A8fF9c"``.
- :returns: The URI value (if valid).
- :raises: instance of :class:`autobahn.wamp.exception.InvalidUriError`
- """
- if value is None:
- raise InvalidUriError("{0}: realm name cannot be null".format(message))
-
- if type(value) != str:
- raise InvalidUriError("{0}: invalid type {1} for realm name".format(message, type(value)))
-
- if allow_eth:
- if _URI_PAT_REALM_NAME.match(value) or _URI_PAT_REALM_NAME_ETH.match(value):
- return value
- else:
- raise InvalidUriError(
- '{0}: invalid value "{1}" for realm name (did not match patterns '
- '"{2}" or "{3}")'.format(message, value,
- _URI_PAT_REALM_NAME.pattern,
- _URI_PAT_REALM_NAME_ETH.pattern))
- else:
- if _URI_PAT_REALM_NAME.match(value):
- return value
- else:
- raise InvalidUriError(
- '{0}: invalid value "{1}" for realm name (did not match pattern '
- '"{2}")'.format(message, value,
- _URI_PAT_REALM_NAME.pattern))
-
-
- def check_or_raise_id(value: Any, message: str = "WAMP message invalid") -> int:
- """
- Check a value for being a valid WAMP ID.
-
- If the value is not a valid WAMP ID, raises :class:`autobahn.wamp.exception.ProtocolError`,
- otherwise return the value.
-
- :param value: The value to check.
- :param message: Prefix for message in exception raised when value is invalid.
- :returns: The ID value (if valid).
- :raises: instance of :class:`autobahn.wamp.exception.ProtocolError`
- """
- if type(value) != int:
- raise ProtocolError("{0}: invalid type {1} for ID".format(message, type(value)))
- # the value 0 for WAMP IDs is possible in certain WAMP messages, e.g. UNREGISTERED with
- # router revocation signaling!
- if value < 0 or value > 9007199254740992: # 2**53
- raise ProtocolError("{0}: invalid value {1} for ID".format(message, value))
- return value
-
-
- def check_or_raise_extra(value: Any, message: str = "WAMP message invalid") -> Dict[str, Any]:
- """
- Check a value for being a valid WAMP extra dictionary.
-
- If the value is not a valid WAMP extra dictionary, raises :class:`autobahn.wamp.exception.ProtocolError`,
- otherwise return the value.
-
- :param value: The value to check.
- :param message: Prefix for message in exception raised when value is invalid.
- :returns: The extra dictionary (if valid).
- :raises: instance of :class:`autobahn.wamp.exception.ProtocolError`
- """
- if type(value) != dict:
- raise ProtocolError("{0}: invalid type {1} for WAMP extra".format(message, type(value)))
- for k in value.keys():
- if not isinstance(k, str):
- raise ProtocolError("{0}: invalid type {1} for key in WAMP extra ('{2}')".format(message, type(k), k))
- return value
-
-
- def _validate_kwargs(kwargs, message="WAMP message invalid"):
- """
- Check a value for being a valid WAMP kwargs dictionary.
-
- If the value is not a valid WAMP kwargs dictionary,
- raises :class:`autobahn.wamp.exception.ProtocolError`.
- Otherwise return the kwargs.
-
- The WAMP spec requires that the keys in kwargs are proper
- strings (unicode), not bytes. Note that the WAMP spec
- says nothing about keys in application payload. Key in the
- latter can be potentially of other type (if that is really
- wanted).
-
- :param kwargs: The keyword arguments to check.
- :type kwargs: dict
-
- :param message: Prefix for message in exception raised when
- value is invalid.
- :type message: str
-
- :returns: The kwargs dictionary (if valid).
- :rtype: dict
-
- :raises: instance of
- :class:`autobahn.wamp.exception.ProtocolError`
- """
- if kwargs is not None:
- if type(kwargs) != dict:
- raise ProtocolError("{0}: invalid type {1} for WAMP kwargs".format(message, type(kwargs)))
- for k in kwargs.keys():
- if not isinstance(k, str):
- raise ProtocolError("{0}: invalid type {1} for key in WAMP kwargs ('{2}')".format(message, type(k), k))
- return kwargs
-
-
- class Message(object):
- """
- WAMP message base class.
-
- .. note:: This is not supposed to be instantiated, but subclassed only.
- """
-
- MESSAGE_TYPE = None
- """
- WAMP message type code.
- """
-
- __slots__ = (
- '_from_fbs',
- '_serialized',
- '_correlation_id',
- '_correlation_uri',
- '_correlation_is_anchor',
- '_correlation_is_last',
-
- '_router_internal',
- )
-
- def __init__(self, from_fbs=None):
- # only filled in case this object has flatbuffers underlying
- self._from_fbs = from_fbs
-
- # serialization cache: mapping from ISerializer instances to serialized bytes
- self._serialized = {}
-
- # user attributes for message correlation (mainly for message tracing)
- self._correlation_id = None
- self._correlation_uri = None
- self._correlation_is_anchor = None
- self._correlation_is_last = None
-
- # non-serialized 'internal' attributes (used by Crossbar router)
- self._router_internal = None
-
- @property
- def correlation_id(self):
- return self._correlation_id
-
- @correlation_id.setter
- def correlation_id(self, value):
- assert(value is None or type(value) == str)
- self._correlation_id = value
-
- @property
- def correlation_uri(self):
- return self._correlation_uri
-
- @correlation_uri.setter
- def correlation_uri(self, value):
- assert(value is None or type(value) == str)
- self._correlation_uri = value
-
- @property
- def correlation_is_anchor(self):
- return self._correlation_is_anchor
-
- @correlation_is_anchor.setter
- def correlation_is_anchor(self, value):
- assert(value is None or type(value) == bool)
- self._correlation_is_anchor = value
-
- @property
- def correlation_is_last(self):
- return self._correlation_is_last
-
- @correlation_is_last.setter
- def correlation_is_last(self, value):
- assert(value is None or type(value) == bool)
- self._correlation_is_last = value
-
- def __eq__(self, other):
- """
- Compare this message to another message for equality.
-
- :param other: The other message to compare with.
- :type other: obj
-
- :returns: ``True`` iff the messages are equal.
- :rtype: bool
- """
- if not isinstance(other, self.__class__):
- return False
- # we only want the actual message data attributes (not eg _serialize)
- for k in self.__slots__:
- if k not in ['_serialized',
- '_correlation_id',
- '_correlation_uri',
- '_correlation_is_anchor',
- '_correlation_is_last'] and not k.startswith('_'):
- if not getattr(self, k) == getattr(other, k):
- return False
- return True
-
- def __ne__(self, other):
- """
- Compare this message to another message for inequality.
-
- :param other: The other message to compare with.
- :type other: obj
-
- :returns: ``True`` iff the messages are not equal.
- :rtype: bool
- """
- return not self.__eq__(other)
-
- def __str__(self) -> str:
- return '{}\n{}'.format(hlval(self.__class__.__name__.upper() + '::', color='blue', bold=True),
- hlval(textwrap.indent(pformat(self.marshal()), ' '), color='blue', bold=False))
-
- @staticmethod
- def parse(wmsg):
- """
- Factory method that parses a unserialized raw message (as returned byte
- :func:`autobahn.interfaces.ISerializer.unserialize`) into an instance
- of this class.
-
- :returns: An instance of this class.
- :rtype: obj
- """
- raise NotImplementedError()
-
- def marshal(self):
- raise NotImplementedError()
-
- @staticmethod
- def cast(buf):
- raise NotImplementedError()
-
- def build(self, builder):
- raise NotImplementedError()
-
- def uncache(self):
- """
- Resets the serialization cache.
- """
- self._serialized = {}
-
- def serialize(self, serializer):
- """
- Serialize this object into a wire level bytes representation and cache
- the resulting bytes. If the cache already contains an entry for the given
- serializer, return the cached representation directly.
-
- :param serializer: The wire level serializer to use.
- :type serializer: An instance that implements :class:`autobahn.interfaces.ISerializer`
-
- :returns: The serialized bytes.
- :rtype: bytes
- """
- # only serialize if not cached ..
- if serializer not in self._serialized:
- if serializer.NAME == 'flatbuffers':
- # flatbuffers get special treatment ..
- builder = flatbuffers.Builder(1024)
-
- # this is the core method writing out this message (self) to a (new) flatbuffer
- # FIXME: implement this method for all classes derived from Message
- obj = self.build(builder)
-
- builder.Finish(obj)
- buf = builder.Output()
- self._serialized[serializer] = bytes(buf)
- else:
- # all other serializers first marshal() the object and then serialize the latter
- self._serialized[serializer] = serializer.serialize(self.marshal())
-
- # cache is filled now: return serialized, cached bytes
- return self._serialized[serializer]
-
-
- class Hello(Message):
- """
- A WAMP ``HELLO`` message.
-
- Format: ``[HELLO, Realm|uri, Details|dict]``
- """
-
- MESSAGE_TYPE = 1
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'realm',
- 'roles',
- 'authmethods',
- 'authid',
- 'authrole',
- 'authextra',
- 'resumable',
- 'resume_session',
- 'resume_token',
- )
-
- def __init__(self,
- realm,
- roles,
- authmethods=None,
- authid=None,
- authrole=None,
- authextra=None,
- resumable=None,
- resume_session=None,
- resume_token=None):
- """
-
- :param realm: The URI of the WAMP realm to join.
- :type realm: str
-
- :param roles: The WAMP session roles and features to announce.
- :type roles: dict of :class:`autobahn.wamp.role.RoleFeatures`
-
- :param authmethods: The authentication methods to announce.
- :type authmethods: list of str or None
-
- :param authid: The authentication ID to announce.
- :type authid: str or None
-
- :param authrole: The authentication role to announce.
- :type authrole: str or None
-
- :param authextra: Application-specific "extra data" to be forwarded to the client.
- :type authextra: dict or None
-
- :param resumable: Whether the client wants this to be a session that can be later resumed.
- :type resumable: bool or None
-
- :param resume_session: The session the client would like to resume.
- :type resume_session: int or None
-
- :param resume_token: The secure authorisation token to resume the session.
- :type resume_token: str or None
- """
- assert(realm is None or isinstance(realm, str))
- assert(type(roles) == dict)
- assert(len(roles) > 0)
- for role in roles:
- assert(role in ['subscriber', 'publisher', 'caller', 'callee'])
- assert(isinstance(roles[role], autobahn.wamp.role.ROLE_NAME_TO_CLASS[role]))
- if authmethods:
- assert(type(authmethods) == list)
- for authmethod in authmethods:
- assert(type(authmethod) == str)
- assert(authid is None or type(authid) == str)
- assert(authrole is None or type(authrole) == str)
- assert(authextra is None or type(authextra) == dict)
- assert(resumable is None or type(resumable) == bool)
- assert(resume_session is None or type(resume_session) == int)
- assert(resume_token is None or type(resume_token) == str)
-
- Message.__init__(self)
- self.realm = realm
- self.roles = roles
- self.authmethods = authmethods
- self.authid = authid
- self.authrole = authrole
- self.authextra = authextra
- self.resumable = resumable
- self.resume_session = resume_session
- self.resume_token = resume_token
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Hello.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for HELLO".format(len(wmsg)))
-
- realm = check_or_raise_uri(wmsg[1], "'realm' in HELLO", allow_none=True)
- details = check_or_raise_extra(wmsg[2], "'details' in HELLO")
-
- roles = {}
-
- if 'roles' not in details:
- raise ProtocolError("missing mandatory roles attribute in options in HELLO")
-
- details_roles = check_or_raise_extra(details['roles'], "'roles' in 'details' in HELLO")
-
- if len(details_roles) == 0:
- raise ProtocolError("empty 'roles' in 'details' in HELLO")
-
- for role in details_roles:
- if role not in ['subscriber', 'publisher', 'caller', 'callee']:
- raise ProtocolError("invalid role '{0}' in 'roles' in 'details' in HELLO".format(role))
-
- role_cls = ROLE_NAME_TO_CLASS[role]
-
- details_role = check_or_raise_extra(details_roles[role], "role '{0}' in 'roles' in 'details' in HELLO".format(role))
-
- if 'features' in details_role:
- check_or_raise_extra(details_role['features'], "'features' in role '{0}' in 'roles' in 'details' in HELLO".format(role))
-
- role_features = role_cls(**details_role['features'])
-
- else:
- role_features = role_cls()
-
- roles[role] = role_features
-
- authmethods = None
- if 'authmethods' in details:
- details_authmethods = details['authmethods']
- if type(details_authmethods) != list:
- raise ProtocolError("invalid type {0} for 'authmethods' detail in HELLO".format(type(details_authmethods)))
-
- for auth_method in details_authmethods:
- if type(auth_method) != str:
- raise ProtocolError("invalid type {0} for item in 'authmethods' detail in HELLO".format(type(auth_method)))
-
- authmethods = details_authmethods
-
- authid = None
- if 'authid' in details:
- details_authid = details['authid']
- if type(details_authid) != str:
- raise ProtocolError("invalid type {0} for 'authid' detail in HELLO".format(type(details_authid)))
-
- authid = details_authid
-
- authrole = None
- if 'authrole' in details:
- details_authrole = details['authrole']
- if type(details_authrole) != str:
- raise ProtocolError("invalid type {0} for 'authrole' detail in HELLO".format(type(details_authrole)))
-
- authrole = details_authrole
-
- authextra = None
- if 'authextra' in details:
- details_authextra = details['authextra']
- if type(details_authextra) != dict:
- raise ProtocolError("invalid type {0} for 'authextra' detail in HELLO".format(type(details_authextra)))
-
- authextra = details_authextra
-
- resumable = None
- if 'resumable' in details:
- resumable = details['resumable']
- if type(resumable) != bool:
- raise ProtocolError("invalid type {0} for 'resumable' detail in HELLO".format(type(resumable)))
-
- resume_session = None
- if 'resume-session' in details:
- resume_session = details['resume-session']
- if type(resume_session) != int:
- raise ProtocolError("invalid type {0} for 'resume-session' detail in HELLO".format(type(resume_session)))
-
- resume_token = None
- if 'resume-token' in details:
- resume_token = details['resume-token']
- if type(resume_token) != str:
- raise ProtocolError("invalid type {0} for 'resume-token' detail in HELLO".format(type(resume_token)))
- else:
- if resume_session:
- raise ProtocolError("resume-token must be provided if resume-session is provided in HELLO")
-
- obj = Hello(realm, roles, authmethods, authid, authrole, authextra, resumable, resume_session, resume_token)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- details = {'roles': {}}
- for role in self.roles.values():
- details['roles'][role.ROLE] = {}
- for feature in role.__dict__:
- if not feature.startswith('_') and feature != 'ROLE' and getattr(role, feature) is not None:
- if 'features' not in details['roles'][role.ROLE]:
- details['roles'][role.ROLE] = {'features': {}}
- details['roles'][role.ROLE]['features'][feature] = getattr(role, feature)
-
- if self.authmethods is not None:
- details['authmethods'] = self.authmethods
-
- if self.authid is not None:
- details['authid'] = self.authid
-
- if self.authrole is not None:
- details['authrole'] = self.authrole
-
- if self.authextra is not None:
- details['authextra'] = self.authextra
-
- if self.resumable is not None:
- details['resumable'] = self.resumable
-
- if self.resume_session is not None:
- details['resume-session'] = self.resume_session
-
- if self.resume_token is not None:
- details['resume-token'] = self.resume_token
-
- return [Hello.MESSAGE_TYPE, self.realm, details]
-
-
- class Welcome(Message):
- """
- A WAMP ``WELCOME`` message.
-
- Format: ``[WELCOME, Session|id, Details|dict]``
- """
-
- MESSAGE_TYPE = 2
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'session',
- 'roles',
- 'realm',
- 'authid',
- 'authrole',
- 'authmethod',
- 'authprovider',
- 'authextra',
- 'resumed',
- 'resumable',
- 'resume_token',
- 'custom',
- )
-
- def __init__(self,
- session,
- roles,
- realm=None,
- authid=None,
- authrole=None,
- authmethod=None,
- authprovider=None,
- authextra=None,
- resumed=None,
- resumable=None,
- resume_token=None,
- custom=None):
- """
-
- :param session: The WAMP session ID the other peer is assigned.
- :type session: int
-
- :param roles: The WAMP roles to announce.
- :type roles: dict of :class:`autobahn.wamp.role.RoleFeatures`
-
- :param realm: The effective realm the session is joined on.
- :type realm: str or None
-
- :param authid: The authentication ID assigned.
- :type authid: str or None
-
- :param authrole: The authentication role assigned.
- :type authrole: str or None
-
- :param authmethod: The authentication method in use.
- :type authmethod: str or None
-
- :param authprovider: The authentication provided in use.
- :type authprovider: str or None
-
- :param authextra: Application-specific "extra data" to be forwarded to the client.
- :type authextra: arbitrary or None
-
- :param resumed: Whether the session is a resumed one.
- :type resumed: bool or None
-
- :param resumable: Whether this session can be resumed later.
- :type resumable: bool or None
-
- :param resume_token: The secure authorisation token to resume the session.
- :type resume_token: str or None
-
- :param custom: Implementation-specific "custom attributes" (`x_my_impl_attribute`) to be set.
- :type custom: dict or None
- """
- assert(type(session) == int)
- assert(type(roles) == dict)
- assert(len(roles) > 0)
- for role in roles:
- assert(role in ['broker', 'dealer'])
- assert(isinstance(roles[role], autobahn.wamp.role.ROLE_NAME_TO_CLASS[role]))
- assert(realm is None or type(realm) == str)
- assert(authid is None or type(authid) == str)
- assert(authrole is None or type(authrole) == str)
- assert(authmethod is None or type(authmethod) == str)
- assert(authprovider is None or type(authprovider) == str)
- assert(authextra is None or type(authextra) == dict)
- assert(resumed is None or type(resumed) == bool)
- assert(resumable is None or type(resumable) == bool)
- assert(resume_token is None or type(resume_token) == str)
- assert(custom is None or type(custom) == dict)
- if custom:
- for k in custom:
- assert(_CUSTOM_ATTRIBUTE.match(k))
-
- Message.__init__(self)
- self.session = session
- self.roles = roles
- self.realm = realm
- self.authid = authid
- self.authrole = authrole
- self.authmethod = authmethod
- self.authprovider = authprovider
- self.authextra = authextra
- self.resumed = resumed
- self.resumable = resumable
- self.resume_token = resume_token
- self.custom = custom or {}
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Welcome.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for WELCOME".format(len(wmsg)))
-
- session = check_or_raise_id(wmsg[1], "'session' in WELCOME")
- details = check_or_raise_extra(wmsg[2], "'details' in WELCOME")
-
- # FIXME: tigher value checking (types, URIs etc)
- realm = details.get('realm', None)
- authid = details.get('authid', None)
- authrole = details.get('authrole', None)
- authmethod = details.get('authmethod', None)
- authprovider = details.get('authprovider', None)
- authextra = details.get('authextra', None)
-
- resumed = None
- if 'resumed' in details:
- resumed = details['resumed']
- if not type(resumed) == bool:
- raise ProtocolError("invalid type {0} for 'resumed' detail in WELCOME".format(type(resumed)))
-
- resumable = None
- if 'resumable' in details:
- resumable = details['resumable']
- if not type(resumable) == bool:
- raise ProtocolError("invalid type {0} for 'resumable' detail in WELCOME".format(type(resumable)))
-
- resume_token = None
- if 'resume_token' in details:
- resume_token = details['resume_token']
- if not type(resume_token) == str:
- raise ProtocolError("invalid type {0} for 'resume_token' detail in WELCOME".format(type(resume_token)))
- elif resumable:
- raise ProtocolError("resume_token required when resumable is given in WELCOME")
-
- roles = {}
-
- if 'roles' not in details:
- raise ProtocolError("missing mandatory roles attribute in options in WELCOME")
-
- details_roles = check_or_raise_extra(details['roles'], "'roles' in 'details' in WELCOME")
-
- if len(details_roles) == 0:
- raise ProtocolError("empty 'roles' in 'details' in WELCOME")
-
- for role in details_roles:
- if role not in ['broker', 'dealer']:
- raise ProtocolError("invalid role '{0}' in 'roles' in 'details' in WELCOME".format(role))
-
- role_cls = ROLE_NAME_TO_CLASS[role]
-
- details_role = check_or_raise_extra(details_roles[role], "role '{0}' in 'roles' in 'details' in WELCOME".format(role))
-
- if 'features' in details_role:
- check_or_raise_extra(details_role['features'], "'features' in role '{0}' in 'roles' in 'details' in WELCOME".format(role))
-
- role_features = role_cls(**details_roles[role]['features'])
-
- else:
- role_features = role_cls()
-
- roles[role] = role_features
-
- custom = {}
- for k in details:
- if _CUSTOM_ATTRIBUTE.match(k):
- custom[k] = details[k]
-
- obj = Welcome(session, roles, realm, authid, authrole, authmethod, authprovider, authextra, resumed, resumable, resume_token, custom)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- details = {}
- details.update(self.custom)
-
- if self.realm:
- details['realm'] = self.realm
-
- if self.authid:
- details['authid'] = self.authid
-
- if self.authrole:
- details['authrole'] = self.authrole
-
- if self.authrole:
- details['authmethod'] = self.authmethod
-
- if self.authprovider:
- details['authprovider'] = self.authprovider
-
- if self.authextra:
- details['authextra'] = self.authextra
-
- if self.resumed:
- details['resumed'] = self.resumed
-
- if self.resumable:
- details['resumable'] = self.resumable
-
- if self.resume_token:
- details['resume_token'] = self.resume_token
-
- details['roles'] = {}
- for role in self.roles.values():
- details['roles'][role.ROLE] = {}
- for feature in role.__dict__:
- if not feature.startswith('_') and feature != 'ROLE' and getattr(role, feature) is not None:
- if 'features' not in details['roles'][role.ROLE]:
- details['roles'][role.ROLE] = {'features': {}}
- details['roles'][role.ROLE]['features'][feature] = getattr(role, feature)
-
- return [Welcome.MESSAGE_TYPE, self.session, details]
-
-
- class Abort(Message):
- """
- A WAMP ``ABORT`` message.
-
- Format: ``[ABORT, Details|dict, Reason|uri]``
- """
-
- MESSAGE_TYPE = 3
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'reason',
- 'message',
- )
-
- def __init__(self, reason, message=None):
- """
-
- :param reason: WAMP or application error URI for aborting reason.
- :type reason: str
-
- :param message: Optional human-readable closing message, e.g. for logging purposes.
- :type message: str or None
- """
- assert(type(reason) == str)
- assert(message is None or type(message) == str)
-
- Message.__init__(self)
- self.reason = reason
- self.message = message
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Abort.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for ABORT".format(len(wmsg)))
-
- details = check_or_raise_extra(wmsg[1], "'details' in ABORT")
- reason = check_or_raise_uri(wmsg[2], "'reason' in ABORT")
-
- message = None
-
- if 'message' in details:
-
- details_message = details['message']
- if type(details_message) != str:
- raise ProtocolError("invalid type {0} for 'message' detail in ABORT".format(type(details_message)))
-
- message = details_message
-
- obj = Abort(reason, message)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- details = {}
- if self.message:
- details['message'] = self.message
-
- return [Abort.MESSAGE_TYPE, details, self.reason]
-
-
- class Challenge(Message):
- """
- A WAMP ``CHALLENGE`` message.
-
- Format: ``[CHALLENGE, Method|string, Extra|dict]``
- """
-
- MESSAGE_TYPE = 4
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'method',
- 'extra',
- )
-
- def __init__(self, method, extra=None):
- """
-
- :param method: The authentication method.
- :type method: str
-
- :param extra: Authentication method specific information.
- :type extra: dict or None
- """
- assert(type(method) == str)
- assert(extra is None or type(extra) == dict)
-
- Message.__init__(self)
- self.method = method
- self.extra = extra or {}
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Challenge.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for CHALLENGE".format(len(wmsg)))
-
- method = wmsg[1]
- if type(method) != str:
- raise ProtocolError("invalid type {0} for 'method' in CHALLENGE".format(type(method)))
-
- extra = check_or_raise_extra(wmsg[2], "'extra' in CHALLENGE")
-
- obj = Challenge(method, extra)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [Challenge.MESSAGE_TYPE, self.method, self.extra]
-
-
- class Authenticate(Message):
- """
- A WAMP ``AUTHENTICATE`` message.
-
- Format: ``[AUTHENTICATE, Signature|string, Extra|dict]``
- """
-
- MESSAGE_TYPE = 5
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'signature',
- 'extra',
- )
-
- def __init__(self, signature, extra=None):
- """
-
- :param signature: The signature for the authentication challenge.
- :type signature: str
-
- :param extra: Authentication method specific information.
- :type extra: dict or None
- """
- assert(type(signature) == str)
- assert(extra is None or type(extra) == dict)
-
- Message.__init__(self)
- self.signature = signature
- self.extra = extra or {}
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Authenticate.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for AUTHENTICATE".format(len(wmsg)))
-
- signature = wmsg[1]
- if type(signature) != str:
- raise ProtocolError("invalid type {0} for 'signature' in AUTHENTICATE".format(type(signature)))
-
- extra = check_or_raise_extra(wmsg[2], "'extra' in AUTHENTICATE")
-
- obj = Authenticate(signature, extra)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [Authenticate.MESSAGE_TYPE, self.signature, self.extra]
-
-
- class Goodbye(Message):
- """
- A WAMP ``GOODBYE`` message.
-
- Format: ``[GOODBYE, Details|dict, Reason|uri]``
- """
-
- MESSAGE_TYPE = 6
- """
- The WAMP message code for this type of message.
- """
-
- DEFAULT_REASON = "wamp.close.normal"
- """
- Default WAMP closing reason.
- """
-
- __slots__ = (
- 'reason',
- 'message',
- 'resumable',
- )
-
- def __init__(self, reason=DEFAULT_REASON, message=None, resumable=None):
- """
-
- :param reason: Optional WAMP or application error URI for closing reason.
- :type reason: str
-
- :param message: Optional human-readable closing message, e.g. for logging purposes.
- :type message: str or None
-
- :param resumable: From the server: Whether the session is able to be resumed (true) or destroyed (false). From the client: Whether it should be resumable (true) or destroyed (false).
- :type resumable: bool or None
- """
- assert(type(reason) == str)
- assert(message is None or type(message) == str)
- assert(resumable is None or type(resumable) == bool)
-
- Message.__init__(self)
- self.reason = reason
- self.message = message
- self.resumable = resumable
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Goodbye.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for GOODBYE".format(len(wmsg)))
-
- details = check_or_raise_extra(wmsg[1], "'details' in GOODBYE")
- reason = check_or_raise_uri(wmsg[2], "'reason' in GOODBYE")
-
- message = None
- resumable = None
-
- if 'message' in details:
-
- details_message = details['message']
- if type(details_message) != str:
- raise ProtocolError("invalid type {0} for 'message' detail in GOODBYE".format(type(details_message)))
-
- message = details_message
-
- if 'resumable' in details:
- resumable = details['resumable']
- if type(resumable) != bool:
- raise ProtocolError("invalid type {0} for 'resumable' detail in GOODBYE".format(type(resumable)))
-
- obj = Goodbye(reason=reason,
- message=message,
- resumable=resumable)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- details = {}
- if self.message:
- details['message'] = self.message
-
- if self.resumable:
- details['resumable'] = self.resumable
-
- return [Goodbye.MESSAGE_TYPE, details, self.reason]
-
-
- class Error(Message):
- """
- A WAMP ``ERROR`` message.
-
- Formats:
-
- * ``[ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri]``
- * ``[ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri, Arguments|list]``
- * ``[ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri, Arguments|list, ArgumentsKw|dict]``
- * ``[ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri, Payload|binary]``
- """
-
- MESSAGE_TYPE = 8
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request_type',
- 'request',
- 'error',
- 'args',
- 'kwargs',
- 'payload',
- 'enc_algo',
- 'enc_key',
- 'enc_serializer',
- 'callee',
- 'callee_authid',
- 'callee_authrole',
- 'forward_for',
- )
-
- def __init__(self,
- request_type,
- request,
- error,
- args=None,
- kwargs=None,
- payload=None,
- enc_algo=None,
- enc_key=None,
- enc_serializer=None,
- callee=None,
- callee_authid=None,
- callee_authrole=None,
- forward_for=None):
- """
-
- :param request_type: The WAMP message type code for the original request.
- :type request_type: int
-
- :param request: The WAMP request ID of the original request (`Call`, `Subscribe`, ...) this error occurred for.
- :type request: int
-
- :param error: The WAMP or application error URI for the error that occurred.
- :type error: str
-
- :param args: Positional values for application-defined exception.
- Must be serializable using any serializers in use.
- :type args: list or None
-
- :param kwargs: Keyword values for application-defined exception.
- Must be serializable using any serializers in use.
- :type kwargs: dict or None
-
- :param payload: Alternative, transparent payload. If given, ``args`` and ``kwargs`` must be left unset.
- :type payload: bytes or None
-
- :param enc_algo: If using payload transparency, the encoding algorithm that was used to encode the payload.
- :type enc_algo: str or None
-
- :param enc_key: If using payload transparency with an encryption algorithm, the payload encryption key.
- :type enc_key: str or None
-
- :param enc_serializer: If using payload transparency, the payload object serializer that was used encoding the payload.
- :type enc_serializer: str or None
-
- :param callee: The WAMP session ID of the effective callee that responded with the error. Only filled if callee is disclosed.
- :type callee: None or int
-
- :param callee_authid: The WAMP authid of the responding callee. Only filled if callee is disclosed.
- :type callee_authid: None or unicode
-
- :param callee_authrole: The WAMP authrole of the responding callee. Only filled if callee is disclosed.
- :type callee_authrole: None or unicode
-
- :param forward_for: When this Error is forwarded for a client/callee (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(type(request_type) == int)
- assert(type(request) == int)
- assert(type(error) == str)
- assert(args is None or type(args) in [list, tuple])
- assert(kwargs is None or type(kwargs) == dict)
- assert(payload is None or type(payload) == bytes)
- assert(payload is None or (payload is not None and args is None and kwargs is None))
-
- assert(enc_algo is None or is_valid_enc_algo(enc_algo))
- assert((enc_algo is None and enc_key is None and enc_serializer is None) or (payload is not None and enc_algo is not None))
- assert(enc_key is None or type(enc_key) == str)
- assert(enc_serializer is None or is_valid_enc_serializer(enc_serializer))
-
- assert(callee is None or type(callee) == int)
- assert(callee_authid is None or type(callee_authid) == str)
- assert(callee_authrole is None or type(callee_authrole) == str)
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request_type = request_type
- self.request = request
- self.error = error
- self.args = args
- self.kwargs = _validate_kwargs(kwargs)
- self.payload = payload
-
- # payload transparency related knobs
- self.enc_algo = enc_algo
- self.enc_key = enc_key
- self.enc_serializer = enc_serializer
-
- # effective callee that responded with the error
- self.callee = callee
- self.callee_authid = callee_authid
- self.callee_authrole = callee_authrole
-
- # message forwarding
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Error.MESSAGE_TYPE)
-
- if len(wmsg) not in (5, 6, 7):
- raise ProtocolError("invalid message length {0} for ERROR".format(len(wmsg)))
-
- request_type = wmsg[1]
- if type(request_type) != int:
- raise ProtocolError("invalid type {0} for 'request_type' in ERROR".format(request_type))
-
- if request_type not in [Subscribe.MESSAGE_TYPE,
- Unsubscribe.MESSAGE_TYPE,
- Publish.MESSAGE_TYPE,
- Register.MESSAGE_TYPE,
- Unregister.MESSAGE_TYPE,
- Call.MESSAGE_TYPE,
- Invocation.MESSAGE_TYPE]:
- raise ProtocolError("invalid value {0} for 'request_type' in ERROR".format(request_type))
-
- request = check_or_raise_id(wmsg[2], "'request' in ERROR")
- details = check_or_raise_extra(wmsg[3], "'details' in ERROR")
- error = check_or_raise_uri(wmsg[4], "'error' in ERROR")
-
- args = None
- kwargs = None
- payload = None
- enc_algo = None
- enc_key = None
- enc_serializer = None
- callee = None
- callee_authid = None
- callee_authrole = None
- forward_for = None
-
- if len(wmsg) == 6 and type(wmsg[5]) == bytes:
-
- payload = wmsg[5]
-
- enc_algo = details.get('enc_algo', None)
- if enc_algo and not is_valid_enc_algo(enc_algo):
- raise ProtocolError("invalid value {0} for 'enc_algo' detail in EVENT".format(enc_algo))
-
- enc_key = details.get('enc_key', None)
- if enc_key and type(enc_key) != str:
- raise ProtocolError("invalid type {0} for 'enc_key' detail in EVENT".format(type(enc_key)))
-
- enc_serializer = details.get('enc_serializer', None)
- if enc_serializer and not is_valid_enc_serializer(enc_serializer):
- raise ProtocolError("invalid value {0} for 'enc_serializer' detail in EVENT".format(enc_serializer))
-
- else:
- if len(wmsg) > 5:
- args = wmsg[5]
- if args is not None and type(args) != list:
- raise ProtocolError("invalid type {0} for 'args' in ERROR".format(type(args)))
-
- if len(wmsg) > 6:
- kwargs = wmsg[6]
- if type(kwargs) != dict:
- raise ProtocolError("invalid type {0} for 'kwargs' in ERROR".format(type(kwargs)))
-
- if 'callee' in details:
-
- detail_callee = details['callee']
- if type(detail_callee) != int:
- raise ProtocolError("invalid type {0} for 'callee' detail in ERROR".format(type(detail_callee)))
-
- callee = detail_callee
-
- if 'callee_authid' in details:
-
- detail_callee_authid = details['callee_authid']
- if type(detail_callee_authid) != str:
- raise ProtocolError("invalid type {0} for 'callee_authid' detail in ERROR".format(type(detail_callee_authid)))
-
- callee_authid = detail_callee_authid
-
- if 'callee_authrole' in details:
-
- detail_callee_authrole = details['callee_authrole']
- if type(detail_callee_authrole) != str:
- raise ProtocolError("invalid type {0} for 'callee_authrole' detail in ERROR".format(type(detail_callee_authrole)))
-
- callee_authrole = detail_callee_authrole
-
- if 'forward_for' in details:
- forward_for = details['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in ERROR")
-
- obj = Error(request_type,
- request,
- error,
- args=args,
- kwargs=kwargs,
- payload=payload,
- enc_algo=enc_algo,
- enc_key=enc_key,
- enc_serializer=enc_serializer,
- callee=callee,
- callee_authid=callee_authid,
- callee_authrole=callee_authrole,
- forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- details = {}
-
- if self.callee is not None:
- details['callee'] = self.callee
- if self.callee_authid is not None:
- details['callee_authid'] = self.callee_authid
- if self.callee_authrole is not None:
- details['callee_authrole'] = self.callee_authrole
- if self.forward_for is not None:
- details['forward_for'] = self.forward_for
-
- if self.payload:
- if self.enc_algo is not None:
- details['enc_algo'] = self.enc_algo
- if self.enc_key is not None:
- details['enc_key'] = self.enc_key
- if self.enc_serializer is not None:
- details['enc_serializer'] = self.enc_serializer
- return [self.MESSAGE_TYPE, self.request_type, self.request, details, self.error, self.payload]
- else:
- if self.kwargs:
- return [self.MESSAGE_TYPE, self.request_type, self.request, details, self.error, self.args, self.kwargs]
- elif self.args:
- return [self.MESSAGE_TYPE, self.request_type, self.request, details, self.error, self.args]
- else:
- return [self.MESSAGE_TYPE, self.request_type, self.request, details, self.error]
-
-
- class Publish(Message):
- """
- A WAMP ``PUBLISH`` message.
-
- Formats:
-
- * ``[PUBLISH, Request|id, Options|dict, Topic|uri]``
- * ``[PUBLISH, Request|id, Options|dict, Topic|uri, Arguments|list]``
- * ``[PUBLISH, Request|id, Options|dict, Topic|uri, Arguments|list, ArgumentsKw|dict]``
- * ``[PUBLISH, Request|id, Options|dict, Topic|uri, Payload|binary]``
- """
-
- MESSAGE_TYPE = 16
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- # uint64 (key)
- '_request',
-
- # string (required, uri)
- '_topic',
-
- # [uint8]
- '_args',
-
- # [uint8]
- '_kwargs',
-
- # [uint8]
- '_payload',
-
- # Payload => uint8
- '_enc_algo',
-
- # Serializer => uint8
- '_enc_serializer',
-
- # [uint8]
- '_enc_key',
-
- # bool
- '_acknowledge',
-
- # bool
- '_exclude_me',
-
- # [uint64]
- '_exclude',
-
- # [string] (principal)
- '_exclude_authid',
-
- # [string] (principal)
- '_exclude_authrole',
-
- # [uint64]
- '_eligible',
-
- # [string] (principal)
- '_eligible_authid',
-
- # [string] (principal)
- '_eligible_authrole',
-
- # bool
- '_retain',
-
- # string
- '_transaction_hash',
-
- # [Principal]
- '_forward_for',
- )
-
- def __init__(self,
- request=None,
- topic=None,
- args=None,
- kwargs=None,
- payload=None,
- acknowledge=None,
- exclude_me=None,
- exclude=None,
- exclude_authid=None,
- exclude_authrole=None,
- eligible=None,
- eligible_authid=None,
- eligible_authrole=None,
- retain=None,
- transaction_hash=None,
- enc_algo=None,
- enc_key=None,
- enc_serializer=None,
- forward_for=None,
- from_fbs=None):
- """
-
- :param request: The WAMP request ID of this request.
- :type request: int
-
- :param topic: The WAMP or application URI of the PubSub topic the event should
- be published to.
- :type topic: str
-
- :param args: Positional values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type args: list or tuple or None
-
- :param kwargs: Keyword values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type kwargs: dict or None
-
- :param payload: Alternative, transparent payload. If given, ``args`` and ``kwargs`` must be left unset.
- :type payload: bytes or None
-
- :param acknowledge: If True, acknowledge the publication with a success or
- error response.
- :type acknowledge: bool or None
-
- :param exclude_me: If ``True``, exclude the publisher from receiving the event, even
- if he is subscribed (and eligible).
- :type exclude_me: bool or None
-
- :param exclude: List of WAMP session IDs to exclude from receiving this event.
- :type exclude: list of int or None
-
- :param exclude_authid: List of WAMP authids to exclude from receiving this event.
- :type exclude_authid: list of str or None
-
- :param exclude_authrole: List of WAMP authroles to exclude from receiving this event.
- :type exclude_authrole: list of str or None
-
- :param eligible: List of WAMP session IDs eligible to receive this event.
- :type eligible: list of int or None
-
- :param eligible_authid: List of WAMP authids eligible to receive this event.
- :type eligible_authid: list of str or None
-
- :param eligible_authrole: List of WAMP authroles eligible to receive this event.
- :type eligible_authrole: list of str or None
-
- :param retain: If ``True``, request the broker retain this event.
- :type retain: bool or None
-
- :param transaction_hash: An application provided transaction hash for the published event, which may
- be used in the router to throttle or deduplicate the events on the topic. See the discussion
- `here <https://github.com/wamp-proto/wamp-proto/issues/391#issuecomment-998577967>`_.
- :type transaction_hash: str
-
- :param enc_algo: If using payload transparency, the encoding algorithm that was used to encode the payload.
- :type enc_algo: str or None
-
- :param enc_key: If using payload transparency with an encryption algorithm, the payload encryption key.
- :type enc_key: str or None
-
- :param enc_serializer: If using payload transparency, the payload object serializer that was used encoding the payload.
- :type enc_serializer: str or None or None
-
- :param forward_for: When this Call is forwarded for a client (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(request is None or type(request) == int)
- assert(topic is None or type(topic) == str)
- assert(args is None or type(args) in [list, tuple, str, bytes])
- assert(kwargs is None or type(kwargs) in [dict, str, bytes])
- assert(payload is None or type(payload) == bytes)
- assert(payload is None or (payload is not None and args is None and kwargs is None))
- assert(acknowledge is None or type(acknowledge) == bool)
- assert(retain is None or type(retain) == bool)
- assert(transaction_hash is None or type(transaction_hash) == str)
-
- # publisher exlusion and black-/whitelisting
- assert(exclude_me is None or type(exclude_me) == bool)
-
- assert(exclude is None or type(exclude) == list)
- if exclude:
- for sessionid in exclude:
- assert(type(sessionid) == int)
-
- assert(exclude_authid is None or type(exclude_authid) == list)
- if exclude_authid:
- for authid in exclude_authid:
- assert(type(authid) == str)
-
- assert(exclude_authrole is None or type(exclude_authrole) == list)
- if exclude_authrole:
- for authrole in exclude_authrole:
- assert(type(authrole) == str)
-
- assert(eligible is None or type(eligible) == list)
- if eligible:
- for sessionid in eligible:
- assert(type(sessionid) == int)
-
- assert(eligible_authid is None or type(eligible_authid) == list)
- if eligible_authid:
- for authid in eligible_authid:
- assert(type(authid) == str)
-
- assert(eligible_authrole is None or type(eligible_authrole) == list)
- if eligible_authrole:
- for authrole in eligible_authrole:
- assert(type(authrole) == str)
-
- assert(enc_algo is None or is_valid_enc_algo(enc_algo))
- assert((enc_algo is None and enc_key is None and enc_serializer is None) or (payload is not None and enc_algo is not None))
- assert(enc_key is None or type(enc_key) == str)
- assert(enc_serializer is None or is_valid_enc_serializer(enc_serializer))
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self, from_fbs=from_fbs)
- self._request = request
- self._topic = topic
- self._args = args
- self._kwargs = _validate_kwargs(kwargs)
- self._payload = payload
- self._acknowledge = acknowledge
-
- # publisher exlusion and black-/whitelisting
- self._exclude_me = exclude_me
- self._exclude = exclude
- self._exclude_authid = exclude_authid
- self._exclude_authrole = exclude_authrole
- self._eligible = eligible
- self._eligible_authid = eligible_authid
- self._eligible_authrole = eligible_authrole
-
- # event retention
- self._retain = retain
-
- # application provided transaction hash for event
- self._transaction_hash = transaction_hash
-
- # payload transparency related knobs
- self._enc_algo = enc_algo
- self._enc_key = enc_key
- self._enc_serializer = enc_serializer
-
- # message forwarding
- self._forward_for = forward_for
-
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return False
- if not Message.__eq__(self, other):
- return False
- if other.request != self.request:
- return False
- if other.topic != self.topic:
- return False
- if other.args != self.args:
- return False
- if other.kwargs != self.kwargs:
- return False
- if other.payload != self.payload:
- return False
- if other.acknowledge != self.acknowledge:
- return False
- if other.exclude_me != self.exclude_me:
- return False
- if other.exclude != self.exclude:
- return False
- if other.exclude_authid != self.exclude_authid:
- return False
- if other.exclude_authrole != self.exclude_authrole:
- return False
- if other.eligible != self.eligible:
- return False
- if other.eligible_authid != self.eligible_authid:
- return False
- if other.eligible_authrole != self.eligible_authrole:
- return False
- if other.retain != self.retain:
- return False
- if other.transaction_hash != self.transaction_hash:
- return False
- if other.enc_algo != self.enc_algo:
- return False
- if other.enc_key != self.enc_key:
- return False
- if other.enc_serializer != self.enc_serializer:
- return False
- if other.forward_for != self.forward_for:
- return False
- return True
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- @property
- def request(self):
- if self._request is None and self._from_fbs:
- self._request = self._from_fbs.Request()
- return self._request
-
- @request.setter
- def request(self, value):
- assert(value is None or type(value) == int)
- self._request = value
-
- @property
- def topic(self):
- if self._topic is None and self._from_fbs:
- s = self._from_fbs.Topic()
- if s:
- self._topic = s.decode('utf8')
- return self._topic
-
- @topic.setter
- def topic(self, value):
- assert value is None or type(value) == str
- self._topic = value
-
- @property
- def args(self):
- if self._args is None and self._from_fbs:
- if self._from_fbs.ArgsLength():
- self._args = cbor2.loads(bytes(self._from_fbs.ArgsAsBytes()))
- return self._args
-
- @args.setter
- def args(self, value):
- assert(value is None or type(value) in [list, tuple])
- self._args = value
-
- @property
- def kwargs(self):
- if self._kwargs is None and self._from_fbs:
- if self._from_fbs.KwargsLength():
- self._kwargs = cbor2.loads(bytes(self._from_fbs.KwargsAsBytes()))
- return self._kwargs
-
- @kwargs.setter
- def kwargs(self, value):
- assert(value is None or type(value) == dict)
- self._kwargs = value
-
- @property
- def payload(self):
- if self._payload is None and self._from_fbs:
- if self._from_fbs.PayloadLength():
- self._payload = self._from_fbs.PayloadAsBytes()
- return self._payload
-
- @payload.setter
- def payload(self, value):
- assert value is None or type(value) == bytes
- self._payload = value
-
- @property
- def acknowledge(self):
- if self._acknowledge is None and self._from_fbs:
- acknowledge = self._from_fbs.Acknowledge()
- if acknowledge:
- self._acknowledge = acknowledge
- return self._acknowledge
-
- @acknowledge.setter
- def acknowledge(self, value):
- assert value is None or type(value) == bool
- self._acknowledge = value
-
- @property
- def exclude_me(self):
- if self._exclude_me is None and self._from_fbs:
- exclude_me = self._from_fbs.ExcludeMe()
- if exclude_me is False:
- self._exclude_me = exclude_me
- return self._exclude_me
-
- @exclude_me.setter
- def exclude_me(self, value):
- assert value is None or type(value) == bool
- self._exclude_me = value
-
- @property
- def exclude(self):
- if self._exclude is None and self._from_fbs:
- if self._from_fbs.ExcludeLength():
- exclude = []
- for j in range(self._from_fbs.ExcludeLength()):
- exclude.append(self._from_fbs.Exclude(j))
- self._exclude = exclude
- return self._exclude
-
- @exclude.setter
- def exclude(self, value):
- assert value is None or type(value) == list
- if value:
- for x in value:
- assert type(x) == int
- self._exclude = value
-
- @property
- def exclude_authid(self):
- if self._exclude_authid is None and self._from_fbs:
- if self._from_fbs.ExcludeAuthidLength():
- exclude_authid = []
- for j in range(self._from_fbs.ExcludeAuthidLength()):
- exclude_authid.append(self._from_fbs.ExcludeAuthid(j).decode('utf8'))
- self._exclude_authid = exclude_authid
- return self._exclude_authid
-
- @exclude_authid.setter
- def exclude_authid(self, value):
- assert value is None or type(value) == list
- if value:
- for x in value:
- assert type(x) == str
- self._exclude_authid = value
-
- @property
- def exclude_authrole(self):
- if self._exclude_authrole is None and self._from_fbs:
- if self._from_fbs.ExcludeAuthroleLength():
- exclude_authrole = []
- for j in range(self._from_fbs.ExcludeAuthroleLength()):
- exclude_authrole.append(self._from_fbs.ExcludeAuthrole(j).decode('utf8'))
- self._exclude_authrole = exclude_authrole
- return self._exclude_authrole
-
- @exclude_authrole.setter
- def exclude_authrole(self, value):
- assert value is None or type(value) == list
- if value:
- for x in value:
- assert type(x) == str
- self._exclude_authrole = value
-
- @property
- def eligible(self):
- if self._eligible is None and self._from_fbs:
- if self._from_fbs.EligibleLength():
- eligible = []
- for j in range(self._from_fbs.EligibleLength()):
- eligible.append(self._from_fbs.Eligible(j))
- self._eligible = eligible
- return self._eligible
-
- @eligible.setter
- def eligible(self, value):
- assert value is None or type(value) == list
- if value:
- for x in value:
- assert type(x) == int
- self._eligible = value
-
- @property
- def eligible_authid(self):
- if self._eligible_authid is None and self._from_fbs:
- if self._from_fbs.EligibleAuthidLength():
- eligible_authid = []
- for j in range(self._from_fbs.EligibleAuthidLength()):
- eligible_authid.append(self._from_fbs.EligibleAuthid(j).decode('utf8'))
- self._eligible_authid = eligible_authid
- return self._eligible_authid
-
- @eligible_authid.setter
- def eligible_authid(self, value):
- assert value is None or type(value) == list
- if value:
- for x in value:
- assert type(x) == str
- self._eligible_authid = value
-
- @property
- def eligible_authrole(self):
- if self._eligible_authrole is None and self._from_fbs:
- if self._from_fbs.EligibleAuthroleLength():
- eligible_authrole = []
- for j in range(self._from_fbs.EligibleAuthroleLength()):
- eligible_authrole.append(self._from_fbs.EligibleAuthrole(j).decode('utf8'))
- self._eligible_authrole = eligible_authrole
- return self._eligible_authrole
-
- @eligible_authrole.setter
- def eligible_authrole(self, value):
- assert value is None or type(value) == list
- if value:
- for x in value:
- assert type(x) == str
- self._eligible_authrole = value
-
- @property
- def retain(self):
- if self._retain is None and self._from_fbs:
- retain = self._from_fbs.Retain()
- if retain:
- self._retain = retain
- return self._retain
-
- @retain.setter
- def retain(self, value):
- assert value is None or type(value) == bool
- self._retain = value
-
- @property
- def transaction_hash(self):
- if self._transaction_hash is None and self._from_fbs:
- s = self._from_fbs.TransactionHash()
- if s:
- self._transaction_hash = s.decode('utf8')
- return self._transaction_hash
-
- @transaction_hash.setter
- def transaction_hash(self, value):
- assert value is None or type(value) == str
- self._transaction_hash = value
-
- @property
- def enc_algo(self):
- if self._enc_algo is None and self._from_fbs:
- enc_algo = self._from_fbs.EncAlgo()
- if enc_algo:
- self._enc_algo = enc_algo
- return self._enc_algo
-
- @enc_algo.setter
- def enc_algo(self, value):
- assert value is None or value in [ENC_ALGO_CRYPTOBOX, ENC_ALGO_MQTT, ENC_ALGO_XBR]
- self._enc_algo = value
-
- @property
- def enc_key(self):
- if self._enc_key is None and self._from_fbs:
- if self._from_fbs.EncKeyLength():
- self._enc_key = self._from_fbs.EncKeyAsBytes()
- return self._enc_key
-
- @enc_key.setter
- def enc_key(self, value):
- assert value is None or type(value) == bytes
- self._enc_key = value
-
- @property
- def enc_serializer(self):
- if self._enc_serializer is None and self._from_fbs:
- enc_serializer = self._from_fbs.EncSerializer()
- if enc_serializer:
- self._enc_serializer = enc_serializer
- return self._enc_serializer
-
- @enc_serializer.setter
- def enc_serializer(self, value):
- assert value is None or value in [ENC_SER_JSON, ENC_SER_MSGPACK, ENC_SER_CBOR, ENC_SER_UBJSON]
- self._enc_serializer = value
-
- @property
- def forward_for(self):
- # FIXME
- return self._forward_for
-
- @forward_for.setter
- def forward_for(self, value):
- # FIXME
- self._forward_for = value
-
- @staticmethod
- def cast(buf):
- return Publish(from_fbs=message_fbs.Publish.GetRootAsPublish(buf, 0))
-
- def build(self, builder):
-
- args = self.args
- if args:
- args = builder.CreateByteVector(cbor2.dumps(args))
-
- kwargs = self.kwargs
- if kwargs:
- kwargs = builder.CreateByteVector(cbor2.dumps(kwargs))
-
- payload = self.payload
- if payload:
- payload = builder.CreateByteVector(payload)
-
- topic = self.topic
- if topic:
- topic = builder.CreateString(topic)
-
- transaction_hash = self.transaction_hash
- if transaction_hash:
- transaction_hash = builder.CreateString(transaction_hash)
-
- enc_key = self.enc_key
- if enc_key:
- enc_key = builder.CreateByteVector(enc_key)
-
- # exclude: [int]
- exclude = self.exclude
- if exclude:
- message_fbs.PublishGen.PublishStartExcludeAuthidVector(builder, len(exclude))
- for session in reversed(exclude):
- builder.PrependUint64(session)
- exclude = builder.EndVector(len(exclude))
-
- # exclude_authid: [string]
- exclude_authid = self.exclude_authid
- if exclude_authid:
- _exclude_authid = []
- for authid in exclude_authid:
- _exclude_authid.append(builder.CreateString(authid))
- message_fbs.PublishGen.PublishStartExcludeAuthidVector(builder, len(_exclude_authid))
- for o in reversed(_exclude_authid):
- builder.PrependUOffsetTRelative(o)
- exclude_authid = builder.EndVector(len(_exclude_authid))
-
- # exclude_authrole: [string]
- exclude_authrole = self.exclude_authrole
- if exclude_authid:
- _exclude_authrole = []
- for authrole in exclude_authrole:
- _exclude_authrole.append(builder.CreateString(authrole))
- message_fbs.PublishGen.PublishStartExcludeAuthroleVector(builder, len(_exclude_authrole))
- for o in reversed(_exclude_authrole):
- builder.PrependUOffsetTRelative(o)
- exclude_authrole = builder.EndVector(len(_exclude_authrole))
-
- # eligible: [int]
- eligible = self.eligible
- if eligible:
- message_fbs.PublishGen.PublishStartEligibleAuthidVector(builder, len(eligible))
- for session in reversed(eligible):
- builder.PrependUint64(session)
- eligible = builder.EndVector(len(eligible))
-
- # eligible_authid: [string]
- eligible_authid = self.eligible_authid
- if eligible_authid:
- _eligible_authid = []
- for authid in eligible_authid:
- _eligible_authid.append(builder.CreateString(authid))
- message_fbs.PublishGen.PublishStartEligibleAuthidVector(builder, len(_eligible_authid))
- for o in reversed(_eligible_authid):
- builder.PrependUOffsetTRelative(o)
- eligible_authid = builder.EndVector(len(_eligible_authid))
-
- # eligible_authrole: [string]
- eligible_authrole = self.eligible_authrole
- if eligible_authrole:
- _eligible_authrole = []
- for authrole in eligible_authrole:
- _eligible_authrole.append(builder.CreateString(authrole))
- message_fbs.PublishGen.PublishStartEligibleAuthroleVector(builder, len(_eligible_authrole))
- for o in reversed(_eligible_authrole):
- builder.PrependUOffsetTRelative(o)
- eligible_authrole = builder.EndVector(len(_eligible_authrole))
-
- # now start and build a new object ..
- message_fbs.PublishGen.PublishStart(builder)
-
- if self.request is not None:
- message_fbs.PublishGen.PublishAddRequest(builder, self.request)
-
- if topic:
- message_fbs.PublishGen.PublishAddTopic(builder, topic)
-
- if args:
- message_fbs.PublishGen.PublishAddArgs(builder, args)
- if kwargs:
- message_fbs.PublishGen.PublishAddKwargs(builder, kwargs)
- if payload:
- message_fbs.PublishGen.PublishAddPayload(builder, payload)
-
- if self.enc_algo:
- message_fbs.PublishGen.PublishAddEncAlgo(builder, self.enc_algo)
- if self.enc_serializer:
- message_fbs.PublishGen.PublishAddEncSerializer(builder, self.enc_serializer)
- if enc_key:
- message_fbs.PublishGen.PublishAddEncKey(builder, enc_key)
-
- if self.acknowledge is not None:
- message_fbs.PublishGen.PublishAddAcknowledge(builder, self.acknowledge)
- if self.exclude_me is not None:
- message_fbs.PublishGen.PublishAddExcludeMe(builder, self.exclude_me)
-
- if exclude:
- message_fbs.PublishGen.PublishAddExclude(builder, exclude)
- if exclude_authid:
- message_fbs.PublishGen.PublishAddExcludeAuthid(builder, exclude_authid)
- if exclude_authrole:
- message_fbs.PublishGen.PublishAddExcludeAuthrole(builder, exclude_authrole)
-
- if eligible:
- message_fbs.PublishGen.PublishAddEligible(builder, eligible)
- if eligible_authid:
- message_fbs.PublishGen.PublishAddEligibleAuthid(builder, eligible_authid)
- if eligible_authrole:
- message_fbs.PublishGen.PublishAddEligibleAuthrole(builder, eligible_authrole)
-
- if self.retain is not None:
- message_fbs.PublishGen.PublishAddRetain(builder, self.retain)
- if transaction_hash is not None:
- message_fbs.PublishGen.PublishAddTransactionHash(builder, self.transaction_hash)
-
- # FIXME: add forward_for
-
- msg = message_fbs.PublishGen.PublishEnd(builder)
-
- message_fbs.Message.MessageStart(builder)
- message_fbs.Message.MessageAddMsgType(builder, message_fbs.MessageType.PUBLISH)
- message_fbs.Message.MessageAddMsg(builder, msg)
- union_msg = message_fbs.Message.MessageEnd(builder)
-
- return union_msg
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Publish.MESSAGE_TYPE)
-
- if len(wmsg) not in (4, 5, 6):
- raise ProtocolError("invalid message length {0} for PUBLISH".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in PUBLISH")
- options = check_or_raise_extra(wmsg[2], "'options' in PUBLISH")
- topic = check_or_raise_uri(wmsg[3], "'topic' in PUBLISH")
-
- args = None
- kwargs = None
- payload = None
-
- if len(wmsg) == 5 and type(wmsg[4]) in [str, bytes]:
-
- payload = wmsg[4]
-
- enc_algo = options.get('enc_algo', None)
- if enc_algo and not is_valid_enc_algo(enc_algo):
- raise ProtocolError("invalid value {0} for 'enc_algo' option in PUBLISH".format(enc_algo))
-
- enc_key = options.get('enc_key', None)
- if enc_key and type(enc_key) != str:
- raise ProtocolError("invalid type {0} for 'enc_key' option in PUBLISH".format(type(enc_key)))
-
- enc_serializer = options.get('enc_serializer', None)
- if enc_serializer and not is_valid_enc_serializer(enc_serializer):
- raise ProtocolError("invalid value {0} for 'enc_serializer' option in PUBLISH".format(enc_serializer))
-
- else:
- if len(wmsg) > 4:
- args = wmsg[4]
- if type(args) not in [list, str, bytes]:
- raise ProtocolError("invalid type {0} for 'args' in PUBLISH".format(type(args)))
-
- if len(wmsg) > 5:
- kwargs = wmsg[5]
- if type(kwargs) not in [dict, str, bytes]:
- raise ProtocolError("invalid type {0} for 'kwargs' in PUBLISH".format(type(kwargs)))
-
- enc_algo = None
- enc_key = None
- enc_serializer = None
-
- acknowledge = None
- exclude_me = None
- exclude = None
- exclude_authid = None
- exclude_authrole = None
- eligible = None
- eligible_authid = None
- eligible_authrole = None
- retain = None
- transaction_hash = None
- forward_for = None
-
- if 'acknowledge' in options:
-
- option_acknowledge = options['acknowledge']
- if type(option_acknowledge) != bool:
- raise ProtocolError("invalid type {0} for 'acknowledge' option in PUBLISH".format(type(option_acknowledge)))
-
- acknowledge = option_acknowledge
-
- if 'exclude_me' in options:
-
- option_exclude_me = options['exclude_me']
- if type(option_exclude_me) != bool:
- raise ProtocolError("invalid type {0} for 'exclude_me' option in PUBLISH".format(type(option_exclude_me)))
-
- exclude_me = option_exclude_me
-
- if 'exclude' in options:
-
- option_exclude = options['exclude']
- if type(option_exclude) != list:
- raise ProtocolError("invalid type {0} for 'exclude' option in PUBLISH".format(type(option_exclude)))
-
- for _sessionid in option_exclude:
- if type(_sessionid) != int:
- raise ProtocolError("invalid type {0} for value in 'exclude' option in PUBLISH".format(type(_sessionid)))
-
- exclude = option_exclude
-
- if 'exclude_authid' in options:
-
- option_exclude_authid = options['exclude_authid']
- if type(option_exclude_authid) != list:
- raise ProtocolError("invalid type {0} for 'exclude_authid' option in PUBLISH".format(type(option_exclude_authid)))
-
- for _authid in option_exclude_authid:
- if type(_authid) != str:
- raise ProtocolError("invalid type {0} for value in 'exclude_authid' option in PUBLISH".format(type(_authid)))
-
- exclude_authid = option_exclude_authid
-
- if 'exclude_authrole' in options:
-
- option_exclude_authrole = options['exclude_authrole']
- if type(option_exclude_authrole) != list:
- raise ProtocolError("invalid type {0} for 'exclude_authrole' option in PUBLISH".format(type(option_exclude_authrole)))
-
- for _authrole in option_exclude_authrole:
- if type(_authrole) != str:
- raise ProtocolError("invalid type {0} for value in 'exclude_authrole' option in PUBLISH".format(type(_authrole)))
-
- exclude_authrole = option_exclude_authrole
-
- if 'eligible' in options:
-
- option_eligible = options['eligible']
- if type(option_eligible) != list:
- raise ProtocolError("invalid type {0} for 'eligible' option in PUBLISH".format(type(option_eligible)))
-
- for sessionId in option_eligible:
- if type(sessionId) != int:
- raise ProtocolError("invalid type {0} for value in 'eligible' option in PUBLISH".format(type(sessionId)))
-
- eligible = option_eligible
-
- if 'eligible_authid' in options:
-
- option_eligible_authid = options['eligible_authid']
- if type(option_eligible_authid) != list:
- raise ProtocolError("invalid type {0} for 'eligible_authid' option in PUBLISH".format(type(option_eligible_authid)))
-
- for _authid in option_eligible_authid:
- if type(_authid) != str:
- raise ProtocolError("invalid type {0} for value in 'eligible_authid' option in PUBLISH".format(type(_authid)))
-
- eligible_authid = option_eligible_authid
-
- if 'eligible_authrole' in options:
-
- option_eligible_authrole = options['eligible_authrole']
- if type(option_eligible_authrole) != list:
- raise ProtocolError("invalid type {0} for 'eligible_authrole' option in PUBLISH".format(type(option_eligible_authrole)))
-
- for _authrole in option_eligible_authrole:
- if type(_authrole) != str:
- raise ProtocolError("invalid type {0} for value in 'eligible_authrole' option in PUBLISH".format(type(_authrole)))
-
- eligible_authrole = option_eligible_authrole
-
- if 'retain' in options:
- retain = options['retain']
- if type(retain) != bool:
- raise ProtocolError("invalid type {0} for 'retain' option in PUBLISH".format(type(retain)))
-
- if 'transaction_hash' in options:
- transaction_hash = options['transaction_hash']
- if type(transaction_hash) != str:
- raise ProtocolError("invalid type {0} for 'transaction_hash' option in PUBLISH".format(type(transaction_hash)))
-
- if 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in PUBLISH")
-
- obj = Publish(request,
- topic,
- args=args,
- kwargs=kwargs,
- payload=payload,
- acknowledge=acknowledge,
- exclude_me=exclude_me,
- exclude=exclude,
- exclude_authid=exclude_authid,
- exclude_authrole=exclude_authrole,
- eligible=eligible,
- eligible_authid=eligible_authid,
- eligible_authrole=eligible_authrole,
- retain=retain,
- transaction_hash=transaction_hash,
- enc_algo=enc_algo,
- enc_key=enc_key,
- enc_serializer=enc_serializer,
- forward_for=forward_for)
-
- return obj
-
- def marshal_options(self):
- options = {}
-
- if self.acknowledge is not None:
- options['acknowledge'] = self.acknowledge
-
- if self.exclude_me is not None:
- options['exclude_me'] = self.exclude_me
- if self.exclude is not None:
- options['exclude'] = self.exclude
- if self.exclude_authid is not None:
- options['exclude_authid'] = self.exclude_authid
- if self.exclude_authrole is not None:
- options['exclude_authrole'] = self.exclude_authrole
- if self.eligible is not None:
- options['eligible'] = self.eligible
- if self.eligible_authid is not None:
- options['eligible_authid'] = self.eligible_authid
- if self.eligible_authrole is not None:
- options['eligible_authrole'] = self.eligible_authrole
- if self.retain is not None:
- options['retain'] = self.retain
- if self.transaction_hash is not None:
- options['transaction_hash'] = self.transaction_hash
-
- if self.payload:
- if self.enc_algo is not None:
- options['enc_algo'] = self.enc_algo
- if self.enc_key is not None:
- options['enc_key'] = self.enc_key
- if self.enc_serializer is not None:
- options['enc_serializer'] = self.enc_serializer
-
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- return options
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- options = self.marshal_options()
-
- if self.payload:
- return [Publish.MESSAGE_TYPE, self.request, options, self.topic, self.payload]
- else:
- if self.kwargs:
- return [Publish.MESSAGE_TYPE, self.request, options, self.topic, self.args, self.kwargs]
- elif self.args:
- return [Publish.MESSAGE_TYPE, self.request, options, self.topic, self.args]
- else:
- return [Publish.MESSAGE_TYPE, self.request, options, self.topic]
-
-
- class Published(Message):
- """
- A WAMP ``PUBLISHED`` message.
-
- Format: ``[PUBLISHED, PUBLISH.Request|id, Publication|id]``
- """
-
- MESSAGE_TYPE = 17
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'publication',
- )
-
- def __init__(self, request, publication):
- """
-
- :param request: The request ID of the original `PUBLISH` request.
- :type request: int
-
- :param publication: The publication ID for the published event.
- :type publication: int
- """
- assert(type(request) == int)
- assert(type(publication) == int)
-
- Message.__init__(self)
- self.request = request
- self.publication = publication
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Published.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for PUBLISHED".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in PUBLISHED")
- publication = check_or_raise_id(wmsg[2], "'publication' in PUBLISHED")
-
- obj = Published(request, publication)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [Published.MESSAGE_TYPE, self.request, self.publication]
-
-
- class Subscribe(Message):
- """
- A WAMP ``SUBSCRIBE`` message.
-
- Format: ``[SUBSCRIBE, Request|id, Options|dict, Topic|uri]``
- """
-
- MESSAGE_TYPE = 32
- """
- The WAMP message code for this type of message.
- """
-
- MATCH_EXACT = 'exact'
- MATCH_PREFIX = 'prefix'
- MATCH_WILDCARD = 'wildcard'
-
- __slots__ = (
- 'request',
- 'topic',
- 'match',
- 'get_retained',
- 'forward_for',
- )
-
- def __init__(self,
- request,
- topic,
- match=None,
- get_retained=None,
- forward_for=None):
- """
-
- :param request: The WAMP request ID of this request.
- :type request: int
-
- :param topic: The WAMP or application URI of the PubSub topic to subscribe to.
- :type topic: str
-
- :param match: The topic matching method to be used for the subscription.
- :type match: str
-
- :param get_retained: Whether the client wants the retained message we may have along with the subscription.
- :type get_retained: bool or None
-
- :param forward_for: When this Subscribe is forwarded over a router-to-router link,
- or via an intermediary router.
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(type(topic) == str)
- assert(match is None or type(match) == str)
- assert(match is None or match in [Subscribe.MATCH_EXACT, Subscribe.MATCH_PREFIX, Subscribe.MATCH_WILDCARD])
- assert(get_retained is None or type(get_retained) is bool)
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.topic = topic
- self.match = match or Subscribe.MATCH_EXACT
- self.get_retained = get_retained
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Subscribe.MESSAGE_TYPE)
-
- if len(wmsg) != 4:
- raise ProtocolError("invalid message length {0} for SUBSCRIBE".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in SUBSCRIBE")
- options = check_or_raise_extra(wmsg[2], "'options' in SUBSCRIBE")
- topic = check_or_raise_uri(wmsg[3], "'topic' in SUBSCRIBE", allow_empty_components=True)
-
- match = Subscribe.MATCH_EXACT
- get_retained = None
- forward_for = None
-
- if 'match' in options:
-
- option_match = options['match']
- if type(option_match) != str:
- raise ProtocolError("invalid type {0} for 'match' option in SUBSCRIBE".format(type(option_match)))
-
- if option_match not in [Subscribe.MATCH_EXACT, Subscribe.MATCH_PREFIX, Subscribe.MATCH_WILDCARD]:
- raise ProtocolError("invalid value {0} for 'match' option in SUBSCRIBE".format(option_match))
-
- match = option_match
-
- if 'get_retained' in options:
- get_retained = options['get_retained']
-
- if type(get_retained) != bool:
- raise ProtocolError("invalid type {0} for 'get_retained' option in SUBSCRIBE".format(type(get_retained)))
-
- if 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in SUBSCRIBE")
-
- obj = Subscribe(request, topic, match=match, get_retained=get_retained, forward_for=forward_for)
-
- return obj
-
- def marshal_options(self):
- options = {}
-
- if self.match and self.match != Subscribe.MATCH_EXACT:
- options['match'] = self.match
-
- if self.get_retained is not None:
- options['get_retained'] = self.get_retained
-
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- return options
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [Subscribe.MESSAGE_TYPE, self.request, self.marshal_options(), self.topic]
-
-
- class Subscribed(Message):
- """
- A WAMP ``SUBSCRIBED`` message.
-
- Format: ``[SUBSCRIBED, SUBSCRIBE.Request|id, Subscription|id]``
- """
-
- MESSAGE_TYPE = 33
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'subscription',
- )
-
- def __init__(self, request, subscription):
- """
-
- :param request: The request ID of the original ``SUBSCRIBE`` request.
- :type request: int
-
- :param subscription: The subscription ID for the subscribed topic (or topic pattern).
- :type subscription: int
- """
- assert(type(request) == int)
- assert(type(subscription) == int)
-
- Message.__init__(self)
- self.request = request
- self.subscription = subscription
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Subscribed.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for SUBSCRIBED".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in SUBSCRIBED")
- subscription = check_or_raise_id(wmsg[2], "'subscription' in SUBSCRIBED")
-
- obj = Subscribed(request, subscription)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [Subscribed.MESSAGE_TYPE, self.request, self.subscription]
-
-
- class Unsubscribe(Message):
- """
- A WAMP ``UNSUBSCRIBE`` message.
-
- Formats:
-
- * ``[UNSUBSCRIBE, Request|id, SUBSCRIBED.Subscription|id]``
- * ``[UNSUBSCRIBE, Request|id, SUBSCRIBED.Subscription|id, Options|dict]``
- """
-
- MESSAGE_TYPE = 34
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'subscription',
- 'forward_for',
- )
-
- def __init__(self, request, subscription, forward_for=None):
- """
-
- :param request: The WAMP request ID of this request.
- :type request: int
-
- :param subscription: The subscription ID for the subscription to unsubscribe from.
- :type subscription: int
-
- :param forward_for: When this Unsubscribe is forwarded over a router-to-router link,
- or via an intermediary router.
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(type(subscription) == int)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.subscription = subscription
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Unsubscribe.MESSAGE_TYPE)
-
- if len(wmsg) not in [3, 4]:
- raise ProtocolError("invalid message length {0} for WAMP UNSUBSCRIBE".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in UNSUBSCRIBE")
- subscription = check_or_raise_id(wmsg[2], "'subscription' in UNSUBSCRIBE")
-
- options = None
- if len(wmsg) > 3:
- options = check_or_raise_extra(wmsg[3], "'options' in UNSUBSCRIBE")
-
- forward_for = None
- if options and 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in UNSUBSCRIBE")
-
- obj = Unsubscribe(request, subscription, forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- if self.forward_for:
- options = {
- 'forward_for': self.forward_for,
- }
- return [Unsubscribe.MESSAGE_TYPE, self.request, self.subscription, options]
- else:
- return [Unsubscribe.MESSAGE_TYPE, self.request, self.subscription]
-
-
- class Unsubscribed(Message):
- """
- A WAMP ``UNSUBSCRIBED`` message.
-
- Formats:
-
- * ``[UNSUBSCRIBED, UNSUBSCRIBE.Request|id]``
- * ``[UNSUBSCRIBED, UNSUBSCRIBE.Request|id, Details|dict]``
- """
-
- MESSAGE_TYPE = 35
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'subscription',
- 'reason',
- )
-
- def __init__(self, request, subscription=None, reason=None):
- """
-
- :param request: The request ID of the original ``UNSUBSCRIBE`` request or
- ``0`` is router triggered unsubscribe ("router revocation signaling").
- :type request: int
-
- :param subscription: If unsubscribe was actively triggered by router, the ID
- of the subscription revoked.
- :type subscription: int or None
-
- :param reason: The reason (an URI) for an active (router initiated) revocation.
- :type reason: str or None.
- """
- assert(type(request) == int)
- assert(subscription is None or type(subscription) == int)
- assert(reason is None or type(reason) == str)
- assert((request != 0 and subscription is None) or (request == 0 and subscription != 0))
-
- Message.__init__(self)
- self.request = request
- self.subscription = subscription
- self.reason = reason
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Unsubscribed.MESSAGE_TYPE)
-
- if len(wmsg) not in [2, 3]:
- raise ProtocolError("invalid message length {0} for UNSUBSCRIBED".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in UNSUBSCRIBED")
-
- subscription = None
- reason = None
-
- if len(wmsg) > 2:
-
- details = check_or_raise_extra(wmsg[2], "'details' in UNSUBSCRIBED")
-
- if "subscription" in details:
- details_subscription = details["subscription"]
- if type(details_subscription) != int:
- raise ProtocolError("invalid type {0} for 'subscription' detail in UNSUBSCRIBED".format(type(details_subscription)))
- subscription = details_subscription
-
- if "reason" in details:
- reason = check_or_raise_uri(details["reason"], "'reason' in UNSUBSCRIBED")
-
- obj = Unsubscribed(request, subscription, reason)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- if self.reason is not None or self.subscription is not None:
- details = {}
- if self.reason is not None:
- details["reason"] = self.reason
- if self.subscription is not None:
- details["subscription"] = self.subscription
- return [Unsubscribed.MESSAGE_TYPE, self.request, details]
- else:
- return [Unsubscribed.MESSAGE_TYPE, self.request]
-
-
- class Event(Message):
- """
- A WAMP ``EVENT`` message.
-
- Formats:
-
- * ``[EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict]``
- * ``[EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict, PUBLISH.Arguments|list]``
- * ``[EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict, PUBLISH.Arguments|list, PUBLISH.ArgumentsKw|dict]``
- * ``[EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict, PUBLISH.Payload|binary]``
- """
-
- MESSAGE_TYPE = 36
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- # uint64
- '_subscription',
-
- # uint64
- '_publication',
-
- # [uint8]
- '_args',
-
- # [uint8]
- '_kwargs',
-
- # [uint8]
- '_payload',
-
- # Payload => uint8
- '_enc_algo',
-
- # Serializer => uint8
- '_enc_serializer',
-
- # [uint8]
- '_enc_key',
-
- # uint64
- '_publisher',
-
- # string (principal)
- '_publisher_authid',
-
- # string (principal)
- '_publisher_authrole',
-
- # string (uri)
- '_topic',
-
- # bool
- '_retained',
-
- # string
- '_transaction_hash',
-
- # bool - FIXME: rename to "acknowledge"
- '_x_acknowledged_delivery',
-
- # [Principal]
- '_forward_for',
- )
-
- def __init__(self, subscription=None, publication=None, args=None, kwargs=None, payload=None,
- publisher=None, publisher_authid=None, publisher_authrole=None, topic=None,
- retained=None, transaction_hash=None, x_acknowledged_delivery=None,
- enc_algo=None, enc_key=None, enc_serializer=None, forward_for=None,
- from_fbs=None):
- """
-
- :param subscription: The subscription ID this event is dispatched under.
- :type subscription: int
-
- :param publication: The publication ID of the dispatched event.
- :type publication: int
-
- :param args: Positional values for application-defined exception.
- Must be serializable using any serializers in use.
- :type args: list or tuple or None
-
- :param kwargs: Keyword values for application-defined exception.
- Must be serializable using any serializers in use.
- :type kwargs: dict or None
-
- :param payload: Alternative, transparent payload. If given, ``args`` and ``kwargs`` must be left unset.
- :type payload: bytes or None
-
- :param publisher: The WAMP session ID of the publisher. Only filled if publisher is disclosed.
- :type publisher: None or int
-
- :param publisher_authid: The WAMP authid of the publisher. Only filled if publisher is disclosed.
- :type publisher_authid: None or unicode
-
- :param publisher_authrole: The WAMP authrole of the publisher. Only filled if publisher is disclosed.
- :type publisher_authrole: None or unicode
-
- :param topic: For pattern-based subscriptions, the event MUST contain the actual topic published to.
- :type topic: str or None
-
- :param retained: Whether the message was retained by the broker on the topic, rather than just published.
- :type retained: bool or None
-
- :param transaction_hash: An application provided transaction hash for the originating call, which may
- be used in the router to throttle or deduplicate the calls on the procedure. See the discussion
- `here <https://github.com/wamp-proto/wamp-proto/issues/391#issuecomment-998577967>`_.
- :type transaction_hash: str
-
- :param x_acknowledged_delivery: Whether this Event should be acknowledged.
- :type x_acknowledged_delivery: bool or None
-
- :param enc_algo: If using payload transparency, the encoding algorithm that was used to encode the payload.
- :type enc_algo: str or None
-
- :param enc_key: If using payload transparency with an encryption algorithm, the payload encryption key.
- :type enc_key: str or None
-
- :param enc_serializer: If using payload transparency, the payload object serializer that was used encoding the payload.
- :type enc_serializer: str or None
-
- :param forward_for: When this Event is forwarded for a client (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(subscription is None or type(subscription) == int)
- assert(publication is None or type(publication) == int)
- assert(args is None or type(args) in [list, tuple])
- assert(kwargs is None or type(kwargs) == dict)
- assert(payload is None or type(payload) == bytes)
- assert(payload is None or (payload is not None and args is None and kwargs is None))
- assert(publisher is None or type(publisher) == int)
- assert(publisher_authid is None or type(publisher_authid) == str)
- assert(publisher_authrole is None or type(publisher_authrole) == str)
- assert(topic is None or type(topic) == str)
- assert(retained is None or type(retained) == bool)
- assert(transaction_hash is None or type(transaction_hash) == str)
- assert(x_acknowledged_delivery is None or type(x_acknowledged_delivery) == bool)
- assert(enc_algo is None or is_valid_enc_algo(enc_algo))
- assert((enc_algo is None and enc_key is None and enc_serializer is None) or (payload is not None and enc_algo is not None))
- assert(enc_key is None or type(enc_key) == str)
- assert(enc_serializer is None or is_valid_enc_serializer(enc_serializer))
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self, from_fbs=from_fbs)
- self._subscription = subscription
- self._publication = publication
- self._args = args
- self._kwargs = _validate_kwargs(kwargs)
- self._payload = payload
- self._publisher = publisher
- self._publisher_authid = publisher_authid
- self._publisher_authrole = publisher_authrole
- self._topic = topic
- self._retained = retained
- self._transaction_hash = transaction_hash
- self._x_acknowledged_delivery = x_acknowledged_delivery
- self._enc_algo = enc_algo
- self._enc_key = enc_key
- self._enc_serializer = enc_serializer
- self._forward_for = forward_for
-
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return False
- if not Message.__eq__(self, other):
- return False
- if other.subscription != self.subscription:
- return False
- if other.publication != self.publication:
- return False
- if other.args != self.args:
- return False
- if other.kwargs != self.kwargs:
- return False
- if other.payload != self.payload:
- return False
- if other.publisher != self.publisher:
- return False
- if other.publisher_authid != self.publisher_authid:
- return False
- if other.publisher_authrole != self.publisher_authrole:
- return False
- if other.topic != self.topic:
- return False
- if other.retained != self.retained:
- return False
- if other.transaction_hash != self.transaction_hash:
- return False
- if other.x_acknowledged_delivery != self.x_acknowledged_delivery:
- return False
- if other.enc_algo != self.enc_algo:
- return False
- if other.enc_key != self.enc_key:
- return False
- if other.enc_serializer != self.enc_serializer:
- return False
- if other.forward_for != self.forward_for:
- return False
- return True
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- @property
- def subscription(self):
- if self._subscription is None and self._from_fbs:
- self._subscription = self._from_fbs.Subscription()
- return self._subscription
-
- @subscription.setter
- def subscription(self, value):
- assert(value is None or type(value) == int)
- self._subscription = value
-
- @property
- def publication(self):
- if self._publication is None and self._from_fbs:
- self._publication = self._from_fbs.Publication()
- return self._publication
-
- @publication.setter
- def publication(self, value):
- assert(value is None or type(value) == int)
- self._publication = value
-
- @property
- def args(self):
- if self._args is None and self._from_fbs:
- if self._from_fbs.ArgsLength():
- self._args = cbor2.loads(bytes(self._from_fbs.ArgsAsBytes()))
- return self._args
-
- @args.setter
- def args(self, value):
- assert(value is None or type(value) in [list, tuple])
- self._args = value
-
- @property
- def kwargs(self):
- if self._kwargs is None and self._from_fbs:
- if self._from_fbs.KwargsLength():
- self._kwargs = cbor2.loads(bytes(self._from_fbs.KwargsAsBytes()))
- return self._kwargs
-
- @kwargs.setter
- def kwargs(self, value):
- assert(value is None or type(value) == dict)
- self._kwargs = value
-
- @property
- def payload(self):
- if self._payload is None and self._from_fbs:
- if self._from_fbs.PayloadLength():
- self._payload = self._from_fbs.PayloadAsBytes()
- return self._payload
-
- @payload.setter
- def payload(self, value):
- assert value is None or type(value) == bytes
- self._payload = value
-
- @property
- def publisher(self):
- if self._publisher is None and self._from_fbs:
- publisher = self._from_fbs.Publisher()
- if publisher:
- self._publisher = publisher
- return self._publisher
-
- @publisher.setter
- def publisher(self, value):
- assert value is None or type(value) == int
- self._publisher = value
-
- @property
- def publisher_authid(self):
- if self._publisher_authid is None and self._from_fbs:
- s = self._from_fbs.PublisherAuthid()
- if s:
- self._publisher_authid = s.decode('utf8')
- return self._publisher_authid
-
- @publisher_authid.setter
- def publisher_authid(self, value):
- assert value is None or type(value) == str
- self._publisher_authid = value
-
- @property
- def publisher_authrole(self):
- if self._publisher_authrole is None and self._from_fbs:
- s = self._from_fbs.PublisherAuthrole()
- if s:
- self._publisher_authrole = s.decode('utf8')
- return self._publisher_authrole
-
- @publisher_authrole.setter
- def publisher_authrole(self, value):
- assert value is None or type(value) == str
- self._publisher_authrole = value
-
- @property
- def topic(self):
- if self._topic is None and self._from_fbs:
- s = self._from_fbs.Topic()
- if s:
- self._topic = s.decode('utf8')
- return self._topic
-
- @topic.setter
- def topic(self, value):
- assert value is None or type(value) == str
- self._topic = value
-
- @property
- def retained(self):
- if self._retained is None and self._from_fbs:
- self._retained = self._from_fbs.Retained()
- return self._retained
-
- @retained.setter
- def retained(self, value):
- assert value is None or type(value) == bool
- self._retained = value
-
- @property
- def transaction_hash(self):
- if self._transaction_hash is None and self._from_fbs:
- s = self._from_fbs.TransactionHash()
- if s:
- self._transaction_hash = s.decode('utf8')
- return self._transaction_hash
-
- @transaction_hash.setter
- def transaction_hash(self, value):
- assert value is None or type(value) == str
- self._transaction_hash = value
-
- @property
- def x_acknowledged_delivery(self):
- if self._x_acknowledged_delivery is None and self._from_fbs:
- x_acknowledged_delivery = self._from_fbs.Acknowledge()
- if x_acknowledged_delivery:
- self._x_acknowledged_delivery = x_acknowledged_delivery
- return self._x_acknowledged_delivery
-
- @x_acknowledged_delivery.setter
- def x_acknowledged_delivery(self, value):
- assert value is None or type(value) == bool
- self._x_acknowledged_delivery = value
-
- @property
- def enc_algo(self):
- if self._enc_algo is None and self._from_fbs:
- enc_algo = self._from_fbs.EncAlgo()
- if enc_algo:
- self._enc_algo = enc_algo
- return self._enc_algo
-
- @enc_algo.setter
- def enc_algo(self, value):
- assert value is None or value in [ENC_ALGO_CRYPTOBOX, ENC_ALGO_MQTT, ENC_ALGO_XBR]
- self._enc_algo = value
-
- @property
- def enc_key(self):
- if self._enc_key is None and self._from_fbs:
- if self._from_fbs.EncKeyLength():
- self._enc_key = self._from_fbs.EncKeyAsBytes()
- return self._enc_key
-
- @enc_key.setter
- def enc_key(self, value):
- assert value is None or type(value) == bytes
- self._enc_key = value
-
- @property
- def enc_serializer(self):
- if self._enc_serializer is None and self._from_fbs:
- enc_serializer = self._from_fbs.EncSerializer()
- if enc_serializer:
- self._enc_serializer = enc_serializer
- return self._enc_serializer
-
- @enc_serializer.setter
- def enc_serializer(self, value):
- assert value is None or value in [ENC_SER_JSON, ENC_SER_MSGPACK, ENC_SER_CBOR, ENC_SER_UBJSON]
- self._enc_serializer = value
-
- @property
- def forward_for(self):
- # FIXME
- return self._forward_for
-
- @forward_for.setter
- def forward_for(self, value):
- # FIXME
- self._forward_for = value
-
- @staticmethod
- def cast(buf):
- return Event(from_fbs=message_fbs.Event.GetRootAsEvent(buf, 0))
-
- def build(self, builder):
-
- args = self.args
- if args:
- args = builder.CreateByteVector(cbor2.dumps(args))
-
- kwargs = self.kwargs
- if kwargs:
- kwargs = builder.CreateByteVector(cbor2.dumps(kwargs))
-
- payload = self.payload
- if payload:
- payload = builder.CreateByteVector(payload)
-
- publisher_authid = self.publisher_authid
- if publisher_authid:
- publisher_authid = builder.CreateString(publisher_authid)
-
- publisher_authrole = self.publisher_authrole
- if publisher_authrole:
- publisher_authrole = builder.CreateString(publisher_authrole)
-
- topic = self.topic
- if topic:
- topic = builder.CreateString(topic)
-
- transaction_hash = self.transaction_hash
- if transaction_hash:
- transaction_hash = builder.CreateString(transaction_hash)
-
- enc_key = self.enc_key
- if enc_key:
- enc_key = builder.CreateByteVector(enc_key)
-
- message_fbs.EventGen.EventStart(builder)
-
- if self.subscription:
- message_fbs.EventGen.EventAddSubscription(builder, self.subscription)
- if self.publication:
- message_fbs.EventGen.EventAddPublication(builder, self.publication)
-
- if args:
- message_fbs.EventGen.EventAddArgs(builder, args)
- if kwargs:
- message_fbs.EventGen.EventAddKwargs(builder, kwargs)
- if payload:
- message_fbs.EventGen.EventAddPayload(builder, payload)
-
- if self.publisher:
- message_fbs.EventGen.EventAddPublisher(builder, self.publisher)
- if publisher_authid:
- message_fbs.EventGen.EventAddPublisherAuthid(builder, publisher_authid)
- if publisher_authrole:
- message_fbs.EventGen.EventAddPublisherAuthrole(builder, publisher_authrole)
-
- if topic:
- message_fbs.EventGen.EventAddTopic(builder, topic)
- if self.retained is not None:
- message_fbs.EventGen.EventAddRetained(builder, self.retained)
- if transaction_hash is not None:
- message_fbs.EventGen.EventAddTransactionHash(builder, transaction_hash)
- if self.x_acknowledged_delivery is not None:
- message_fbs.EventGen.EventAddAcknowledge(builder, self.x_acknowledged_delivery)
-
- if self.enc_algo:
- message_fbs.EventGen.EventAddEncAlgo(builder, self.enc_algo)
- if enc_key:
- message_fbs.EventGen.EventAddEncKey(builder, enc_key)
- if self.enc_serializer:
- message_fbs.EventGen.EventAddEncSerializer(builder, self.enc_serializer)
-
- # FIXME: add forward_for
-
- msg = message_fbs.EventGen.EventEnd(builder)
-
- message_fbs.Message.MessageStart(builder)
- message_fbs.Message.MessageAddMsgType(builder, message_fbs.MessageType.EVENT)
- message_fbs.Message.MessageAddMsg(builder, msg)
- union_msg = message_fbs.Message.MessageEnd(builder)
-
- return union_msg
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Event.MESSAGE_TYPE)
-
- if len(wmsg) not in (4, 5, 6):
- raise ProtocolError("invalid message length {0} for EVENT".format(len(wmsg)))
-
- subscription = check_or_raise_id(wmsg[1], "'subscription' in EVENT")
- publication = check_or_raise_id(wmsg[2], "'publication' in EVENT")
- details = check_or_raise_extra(wmsg[3], "'details' in EVENT")
-
- args = None
- kwargs = None
- payload = None
- enc_algo = None
- enc_key = None
- enc_serializer = None
-
- if len(wmsg) == 5 and type(wmsg[4]) == bytes:
-
- payload = wmsg[4]
-
- enc_algo = details.get('enc_algo', None)
- if enc_algo and not is_valid_enc_algo(enc_algo):
- raise ProtocolError("invalid value {0} for 'enc_algo' detail in EVENT".format(enc_algo))
-
- enc_key = details.get('enc_key', None)
- if enc_key and type(enc_key) != str:
- raise ProtocolError("invalid type {0} for 'enc_key' detail in EVENT".format(type(enc_key)))
-
- enc_serializer = details.get('enc_serializer', None)
- if enc_serializer and not is_valid_enc_serializer(enc_serializer):
- raise ProtocolError("invalid value {0} for 'enc_serializer' detail in EVENT".format(enc_serializer))
-
- else:
- if len(wmsg) > 4:
- args = wmsg[4]
- if args is not None and type(args) != list:
- raise ProtocolError("invalid type {0} for 'args' in EVENT".format(type(args)))
- if len(wmsg) > 5:
- kwargs = wmsg[5]
- if type(kwargs) != dict:
- raise ProtocolError("invalid type {0} for 'kwargs' in EVENT".format(type(kwargs)))
-
- publisher = None
- publisher_authid = None
- publisher_authrole = None
- topic = None
- retained = None
- transaction_hash = None
- forward_for = None
- x_acknowledged_delivery = None
-
- if 'publisher' in details:
-
- detail_publisher = details['publisher']
- if type(detail_publisher) != int:
- raise ProtocolError("invalid type {0} for 'publisher' detail in EVENT".format(type(detail_publisher)))
-
- publisher = detail_publisher
-
- if 'publisher_authid' in details:
-
- detail_publisher_authid = details['publisher_authid']
- if type(detail_publisher_authid) != str:
- raise ProtocolError("invalid type {0} for 'publisher_authid' detail in EVENT".format(type(detail_publisher_authid)))
-
- publisher_authid = detail_publisher_authid
-
- if 'publisher_authrole' in details:
-
- detail_publisher_authrole = details['publisher_authrole']
- if type(detail_publisher_authrole) != str:
- raise ProtocolError("invalid type {0} for 'publisher_authrole' detail in EVENT".format(type(detail_publisher_authrole)))
-
- publisher_authrole = detail_publisher_authrole
-
- if 'topic' in details:
-
- detail_topic = details['topic']
- if type(detail_topic) != str:
- raise ProtocolError("invalid type {0} for 'topic' detail in EVENT".format(type(detail_topic)))
-
- topic = detail_topic
-
- if 'retained' in details:
- retained = details['retained']
- if type(retained) != bool:
- raise ProtocolError("invalid type {0} for 'retained' detail in EVENT".format(type(retained)))
-
- if 'transaction_hash' in details:
-
- detail_transaction_hash = details['transaction_hash']
- if type(detail_transaction_hash) != str:
- raise ProtocolError("invalid type {0} for 'transaction_hash' detail in EVENT".format(type(detail_transaction_hash)))
-
- transaction_hash = detail_transaction_hash
-
- if 'x_acknowledged_delivery' in details:
- x_acknowledged_delivery = details['x_acknowledged_delivery']
- if type(x_acknowledged_delivery) != bool:
- raise ProtocolError("invalid type {0} for 'x_acknowledged_delivery' detail in EVENT".format(type(x_acknowledged_delivery)))
-
- if 'forward_for' in details:
- forward_for = details['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in EVENT")
-
- obj = Event(subscription,
- publication,
- args=args,
- kwargs=kwargs,
- payload=payload,
- publisher=publisher,
- publisher_authid=publisher_authid,
- publisher_authrole=publisher_authrole,
- topic=topic,
- retained=retained,
- transaction_hash=transaction_hash,
- x_acknowledged_delivery=x_acknowledged_delivery,
- enc_algo=enc_algo,
- enc_key=enc_key,
- enc_serializer=enc_serializer,
- forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- details = {}
-
- if self.publisher is not None:
- details['publisher'] = self.publisher
-
- if self.publisher_authid is not None:
- details['publisher_authid'] = self.publisher_authid
-
- if self.publisher_authrole is not None:
- details['publisher_authrole'] = self.publisher_authrole
-
- if self.topic is not None:
- details['topic'] = self.topic
-
- if self.retained is not None:
- details['retained'] = self.retained
-
- if self.transaction_hash is not None:
- details['transaction_hash'] = self.transaction_hash
-
- if self.x_acknowledged_delivery is not None:
- details['x_acknowledged_delivery'] = self.x_acknowledged_delivery
-
- if self.forward_for is not None:
- details['forward_for'] = self.forward_for
-
- if self.payload:
- if self.enc_algo is not None:
- details['enc_algo'] = self.enc_algo
- if self.enc_key is not None:
- details['enc_key'] = self.enc_key
- if self.enc_serializer is not None:
- details['enc_serializer'] = self.enc_serializer
- return [Event.MESSAGE_TYPE, self.subscription, self.publication, details, self.payload]
- else:
- if self.kwargs:
- return [Event.MESSAGE_TYPE, self.subscription, self.publication, details, self.args, self.kwargs]
- elif self.args:
- return [Event.MESSAGE_TYPE, self.subscription, self.publication, details, self.args]
- else:
- return [Event.MESSAGE_TYPE, self.subscription, self.publication, details]
-
-
- class EventReceived(Message):
- """
- A WAMP ``EVENT_RECEIVED`` message.
-
- Format: ``[EVENT_RECEIVED, EVENT.Publication|id]``
- """
-
- # NOTE: Implementation-specific message! Should be 37 on ratification.
- MESSAGE_TYPE = 337
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'publication',
- )
-
- def __init__(self, publication):
- """
-
- :param publication: The publication ID for the sent event.
- :type publication: int
- """
- assert(type(publication) == int)
-
- Message.__init__(self)
- self.publication = publication
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == EventReceived.MESSAGE_TYPE)
-
- if len(wmsg) != 2:
- raise ProtocolError("invalid message length {0} for EVENT_RECEIVED".format(len(wmsg)))
-
- publication = check_or_raise_id(wmsg[1], "'publication' in EVENT_RECEIVED")
-
- obj = EventReceived(publication)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [EventReceived.MESSAGE_TYPE, self.publication]
-
-
- class Call(Message):
- """
- A WAMP ``CALL`` message.
-
- Formats:
-
- * ``[CALL, Request|id, Options|dict, Procedure|uri]``
- * ``[CALL, Request|id, Options|dict, Procedure|uri, Arguments|list]``
- * ``[CALL, Request|id, Options|dict, Procedure|uri, Arguments|list, ArgumentsKw|dict]``
- * ``[CALL, Request|id, Options|dict, Procedure|uri, Payload|binary]``
- """
-
- MESSAGE_TYPE = 48
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'procedure',
- 'args',
- 'kwargs',
- 'payload',
- 'timeout',
- 'receive_progress',
- 'transaction_hash',
- 'enc_algo',
- 'enc_key',
- 'enc_serializer',
- 'caller',
- 'caller_authid',
- 'caller_authrole',
- 'forward_for',
- )
-
- def __init__(self,
- request,
- procedure,
- args=None,
- kwargs=None,
- payload=None,
- timeout=None,
- receive_progress=None,
- transaction_hash=None,
- enc_algo=None,
- enc_key=None,
- enc_serializer=None,
- caller=None,
- caller_authid=None,
- caller_authrole=None,
- forward_for=None):
- """
-
- :param request: The WAMP request ID of this request.
- :type request: int
-
- :param procedure: The WAMP or application URI of the procedure which should be called.
- :type procedure: str
-
- :param args: Positional values for application-defined call arguments.
- Must be serializable using any serializers in use.
- :type args: list or tuple or None
-
- :param kwargs: Keyword values for application-defined call arguments.
- Must be serializable using any serializers in use.
- :type kwargs: dict or None
-
- :param payload: Alternative, transparent payload. If given, ``args`` and ``kwargs`` must be left unset.
- :type payload: bytes or None
-
- :param timeout: If present, let the callee automatically cancel
- the call after this ms.
- :type timeout: int or None
-
- :param receive_progress: If ``True``, indicates that the caller wants to receive
- progressive call results.
- :type receive_progress: bool or None
-
- :param transaction_hash: An application provided transaction hash for the originating call, which may
- be used in the router to throttle or deduplicate the calls on the procedure. See the discussion
- `here <https://github.com/wamp-proto/wamp-proto/issues/391#issuecomment-998577967>`_.
- :type transaction_hash: str
-
- :param enc_algo: If using payload transparency, the encoding algorithm that was used to encode the payload.
- :type enc_algo: str or None
-
- :param enc_key: If using payload transparency with an encryption algorithm, the payload encryption key.
- :type enc_key: str or None
-
- :param enc_serializer: If using payload transparency, the payload object serializer that was used encoding the payload.
- :type enc_serializer: str or None
-
- :param caller: The WAMP session ID of the caller. Only filled if caller is disclosed.
- :type caller: None or int
-
- :param caller_authid: The WAMP authid of the caller. Only filled if caller is disclosed.
- :type caller_authid: None or unicode
-
- :param caller_authrole: The WAMP authrole of the caller. Only filled if caller is disclosed.
- :type caller_authrole: None or unicode
-
- :param forward_for: When this Publish is forwarded for a client (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(type(procedure) == str)
- assert(args is None or type(args) in [list, tuple])
- assert(kwargs is None or type(kwargs) == dict)
- assert(payload is None or type(payload) == bytes)
- assert(payload is None or (payload is not None and args is None and kwargs is None))
- assert(timeout is None or type(timeout) == int)
- assert(receive_progress is None or type(receive_progress) == bool)
- assert(transaction_hash is None or type(transaction_hash) == str)
-
- # payload transparency related knobs
- assert(enc_algo is None or is_valid_enc_algo(enc_algo))
- assert(enc_key is None or type(enc_key) == str)
- assert(enc_serializer is None or is_valid_enc_serializer(enc_serializer))
- assert((enc_algo is None and enc_key is None and enc_serializer is None) or (payload is not None and enc_algo is not None))
-
- assert(caller is None or type(caller) == int)
- assert(caller_authid is None or type(caller_authid) == str)
- assert(caller_authrole is None or type(caller_authrole) == str)
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.procedure = procedure
- self.args = args
- self.kwargs = _validate_kwargs(kwargs)
- self.payload = payload
- self.timeout = timeout
- self.receive_progress = receive_progress
- self.transaction_hash = transaction_hash
-
- # payload transparency related knobs
- self.enc_algo = enc_algo
- self.enc_key = enc_key
- self.enc_serializer = enc_serializer
-
- # message forwarding
- self.caller = caller
- self.caller_authid = caller_authid
- self.caller_authrole = caller_authrole
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Call.MESSAGE_TYPE)
-
- if len(wmsg) not in (4, 5, 6):
- raise ProtocolError("invalid message length {0} for CALL".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in CALL")
- options = check_or_raise_extra(wmsg[2], "'options' in CALL")
- procedure = check_or_raise_uri(wmsg[3], "'procedure' in CALL")
-
- args = None
- kwargs = None
- payload = None
- enc_algo = None
- enc_key = None
- enc_serializer = None
-
- if len(wmsg) == 5 and type(wmsg[4]) in [str, bytes]:
-
- payload = wmsg[4]
-
- enc_algo = options.get('enc_algo', None)
- if enc_algo and not is_valid_enc_algo(enc_algo):
- raise ProtocolError("invalid value {0} for 'enc_algo' detail in CALL".format(enc_algo))
-
- enc_key = options.get('enc_key', None)
- if enc_key and type(enc_key) != str:
- raise ProtocolError("invalid type {0} for 'enc_key' detail in CALL".format(type(enc_key)))
-
- enc_serializer = options.get('enc_serializer', None)
- if enc_serializer and not is_valid_enc_serializer(enc_serializer):
- raise ProtocolError("invalid value {0} for 'enc_serializer' detail in CALL".format(enc_serializer))
-
- else:
- if len(wmsg) > 4:
- args = wmsg[4]
- if args is not None and type(args) != list:
- raise ProtocolError("invalid type {0} for 'args' in CALL".format(type(args)))
-
- if len(wmsg) > 5:
- kwargs = wmsg[5]
- if type(kwargs) != dict:
- raise ProtocolError("invalid type {0} for 'kwargs' in CALL".format(type(kwargs)))
-
- timeout = None
- receive_progress = None
- transaction_hash = None
- caller = None
- caller_authid = None
- caller_authrole = None
- forward_for = None
-
- if 'timeout' in options:
-
- option_timeout = options['timeout']
- if type(option_timeout) != int:
- raise ProtocolError("invalid type {0} for 'timeout' option in CALL".format(type(option_timeout)))
-
- if option_timeout < 0:
- raise ProtocolError("invalid value {0} for 'timeout' option in CALL".format(option_timeout))
-
- timeout = option_timeout
-
- if 'receive_progress' in options:
-
- option_receive_progress = options['receive_progress']
- if type(option_receive_progress) != bool:
- raise ProtocolError("invalid type {0} for 'receive_progress' option in CALL".format(type(option_receive_progress)))
-
- receive_progress = option_receive_progress
-
- if 'transaction_hash' in options:
-
- option_transaction_hash = options['transaction_hash']
- if type(option_transaction_hash) != str:
- raise ProtocolError("invalid type {0} for 'transaction_hash' detail in CALL".format(type(option_transaction_hash)))
-
- transaction_hash = option_transaction_hash
-
- if 'caller' in options:
-
- option_caller = options['caller']
- if type(option_caller) != int:
- raise ProtocolError("invalid type {0} for 'caller' detail in CALL".format(type(option_caller)))
-
- caller = option_caller
-
- if 'caller_authid' in options:
-
- option_caller_authid = options['caller_authid']
- if type(option_caller_authid) != str:
- raise ProtocolError("invalid type {0} for 'caller_authid' detail in CALL".format(type(option_caller_authid)))
-
- caller_authid = option_caller_authid
-
- if 'caller_authrole' in options:
-
- option_caller_authrole = options['caller_authrole']
- if type(option_caller_authrole) != str:
- raise ProtocolError("invalid type {0} for 'caller_authrole' detail in CALL".format(type(option_caller_authrole)))
-
- caller_authrole = option_caller_authrole
-
- if 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in CALL")
-
- obj = Call(request,
- procedure,
- args=args,
- kwargs=kwargs,
- payload=payload,
- timeout=timeout,
- receive_progress=receive_progress,
- transaction_hash=transaction_hash,
- enc_algo=enc_algo,
- enc_key=enc_key,
- enc_serializer=enc_serializer,
- caller=caller,
- caller_authid=caller_authid,
- caller_authrole=caller_authrole,
- forward_for=forward_for)
-
- return obj
-
- def marshal_options(self):
- options = {}
-
- if self.timeout is not None:
- options['timeout'] = self.timeout
-
- if self.receive_progress is not None:
- options['receive_progress'] = self.receive_progress
-
- if self.transaction_hash is not None:
- options['transaction_hash'] = self.transaction_hash
-
- if self.payload:
- if self.enc_algo is not None:
- options['enc_algo'] = self.enc_algo
- if self.enc_key is not None:
- options['enc_key'] = self.enc_key
- if self.enc_serializer is not None:
- options['enc_serializer'] = self.enc_serializer
-
- if self.caller is not None:
- options['caller'] = self.caller
- if self.caller_authid is not None:
- options['caller_authid'] = self.caller_authid
- if self.caller_authrole is not None:
- options['caller_authrole'] = self.caller_authrole
-
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- return options
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- options = self.marshal_options()
-
- if self.payload:
- return [Call.MESSAGE_TYPE, self.request, options, self.procedure, self.payload]
- else:
- if self.kwargs:
- return [Call.MESSAGE_TYPE, self.request, options, self.procedure, self.args, self.kwargs]
- elif self.args:
- return [Call.MESSAGE_TYPE, self.request, options, self.procedure, self.args]
- else:
- return [Call.MESSAGE_TYPE, self.request, options, self.procedure]
-
-
- class Cancel(Message):
- """
- A WAMP ``CANCEL`` message.
-
- Format: ``[CANCEL, CALL.Request|id, Options|dict]``
-
- See: https://wamp-proto.org/static/rfc/draft-oberstet-hybi-crossbar-wamp.html#rfc.section.14.3.4
- """
-
- MESSAGE_TYPE = 49
- """
- The WAMP message code for this type of message.
- """
-
- SKIP = 'skip'
- KILL = 'kill'
- KILLNOWAIT = 'killnowait'
-
- __slots__ = (
- 'request',
- 'mode',
- 'forward_for',
- )
-
- def __init__(self, request, mode=None, forward_for=None):
- """
-
- :param request: The WAMP request ID of the original `CALL` to cancel.
- :type request: int
-
- :param mode: Specifies how to cancel the call (``"skip"``, ``"killnowait"`` or ``"kill"``).
- :type mode: str or None
-
- :param forward_for: When this Cancel is forwarded for a client (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(mode is None or type(mode) == str)
- assert(mode in [None, self.SKIP, self.KILLNOWAIT, self.KILL])
- assert(forward_for is None or type(forward_for) == list)
-
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.mode = mode
-
- # message forwarding
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Cancel.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for CANCEL".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in CANCEL")
- options = check_or_raise_extra(wmsg[2], "'options' in CANCEL")
-
- # options
- #
- mode = None
- forward_for = None
-
- if 'mode' in options:
-
- option_mode = options['mode']
- if type(option_mode) != str:
- raise ProtocolError("invalid type {0} for 'mode' option in CANCEL".format(type(option_mode)))
-
- if option_mode not in [Cancel.SKIP, Cancel.KILLNOWAIT, Cancel.KILL]:
- raise ProtocolError("invalid value '{0}' for 'mode' option in CANCEL".format(option_mode))
-
- mode = option_mode
-
- if 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in CANCEL")
-
- obj = Cancel(request, mode=mode, forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- options = {}
-
- if self.mode is not None:
- options['mode'] = self.mode
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- return [Cancel.MESSAGE_TYPE, self.request, options]
-
-
- class Result(Message):
- """
- A WAMP ``RESULT`` message.
-
- Formats:
-
- * ``[RESULT, CALL.Request|id, Details|dict]``
- * ``[RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list]``
- * ``[RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list, YIELD.ArgumentsKw|dict]``
- * ``[RESULT, CALL.Request|id, Details|dict, Payload|binary]``
- """
-
- MESSAGE_TYPE = 50
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'args',
- 'kwargs',
- 'payload',
- 'progress',
- 'enc_algo',
- 'enc_key',
- 'enc_serializer',
- 'callee',
- 'callee_authid',
- 'callee_authrole',
- 'forward_for',
- )
-
- def __init__(self,
- request,
- args=None,
- kwargs=None,
- payload=None,
- progress=None,
- enc_algo=None,
- enc_key=None,
- enc_serializer=None,
- callee=None,
- callee_authid=None,
- callee_authrole=None,
- forward_for=None):
- """
-
- :param request: The request ID of the original `CALL` request.
- :type request: int
-
- :param args: Positional values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type args: list or tuple or None
-
- :param kwargs: Keyword values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type kwargs: dict or None
-
- :param payload: Alternative, transparent payload. If given, ``args`` and ``kwargs`` must be left unset.
- :type payload: bytes or None
-
- :param progress: If ``True``, this result is a progressive call result, and subsequent
- results (or a final error) will follow.
- :type progress: bool or None
-
- :param enc_algo: If using payload transparency, the encoding algorithm that was used to encode the payload.
- :type enc_algo: str or None
-
- :param enc_key: If using payload transparency with an encryption algorithm, the payload encryption key.
- :type enc_key: str or None
-
- :param enc_serializer: If using payload transparency, the payload object serializer that was used encoding the payload.
- :type enc_serializer: str or None
-
- :param callee: The WAMP session ID of the effective callee that responded with the result. Only filled if callee is disclosed.
- :type callee: None or int
-
- :param callee_authid: The WAMP authid of the responding callee. Only filled if callee is disclosed.
- :type callee_authid: None or unicode
-
- :param callee_authrole: The WAMP authrole of the responding callee. Only filled if callee is disclosed.
- :type callee_authrole: None or unicode
-
- :param forward_for: When this Result is forwarded for a client/callee (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(args is None or type(args) in [list, tuple])
- assert(kwargs is None or type(kwargs) == dict)
- assert(payload is None or type(payload) == bytes)
- assert(payload is None or (payload is not None and args is None and kwargs is None))
- assert(progress is None or type(progress) == bool)
-
- assert(enc_algo is None or is_valid_enc_algo(enc_algo))
- assert(enc_key is None or type(enc_key) == str)
- assert(enc_serializer is None or is_valid_enc_serializer(enc_serializer))
- assert((enc_algo is None and enc_key is None and enc_serializer is None) or (payload is not None and enc_algo is not None))
-
- assert(callee is None or type(callee) == int)
- assert(callee_authid is None or type(callee_authid) == str)
- assert(callee_authrole is None or type(callee_authrole) == str)
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.args = args
- self.kwargs = _validate_kwargs(kwargs)
- self.payload = payload
- self.progress = progress
-
- # payload transparency related knobs
- self.enc_algo = enc_algo
- self.enc_key = enc_key
- self.enc_serializer = enc_serializer
-
- # effective callee that responded with the result
- self.callee = callee
- self.callee_authid = callee_authid
- self.callee_authrole = callee_authrole
-
- # message forwarding
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Result.MESSAGE_TYPE)
-
- if len(wmsg) not in (3, 4, 5):
- raise ProtocolError("invalid message length {0} for RESULT".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in RESULT")
- details = check_or_raise_extra(wmsg[2], "'details' in RESULT")
-
- args = None
- kwargs = None
- payload = None
- progress = None
- enc_algo = None
- enc_key = None
- enc_serializer = None
- callee = None
- callee_authid = None
- callee_authrole = None
- forward_for = None
-
- if len(wmsg) == 4 and type(wmsg[3]) in [str, bytes]:
-
- payload = wmsg[3]
-
- enc_algo = details.get('enc_algo', None)
- if enc_algo and not is_valid_enc_algo(enc_algo):
- raise ProtocolError("invalid value {0} for 'enc_algo' detail in RESULT".format(enc_algo))
-
- enc_key = details.get('enc_key', None)
- if enc_key and type(enc_key) != str:
- raise ProtocolError("invalid type {0} for 'enc_key' detail in RESULT".format(type(enc_key)))
-
- enc_serializer = details.get('enc_serializer', None)
- if enc_serializer and not is_valid_enc_serializer(enc_serializer):
- raise ProtocolError("invalid value {0} for 'enc_serializer' detail in RESULT".format(enc_serializer))
-
- else:
- if len(wmsg) > 3:
- args = wmsg[3]
- if args is not None and type(args) != list:
- raise ProtocolError("invalid type {0} for 'args' in RESULT".format(type(args)))
-
- if len(wmsg) > 4:
- kwargs = wmsg[4]
- if type(kwargs) != dict:
- raise ProtocolError("invalid type {0} for 'kwargs' in RESULT".format(type(kwargs)))
-
- if 'progress' in details:
-
- detail_progress = details['progress']
- if type(detail_progress) != bool:
- raise ProtocolError("invalid type {0} for 'progress' option in RESULT".format(type(detail_progress)))
-
- progress = detail_progress
-
- if 'callee' in details:
-
- detail_callee = details['callee']
- if type(detail_callee) != int:
- raise ProtocolError("invalid type {0} for 'callee' detail in RESULT".format(type(detail_callee)))
-
- callee = detail_callee
-
- if 'callee_authid' in details:
-
- detail_callee_authid = details['callee_authid']
- if type(detail_callee_authid) != str:
- raise ProtocolError("invalid type {0} for 'callee_authid' detail in RESULT".format(type(detail_callee_authid)))
-
- callee_authid = detail_callee_authid
-
- if 'callee_authrole' in details:
-
- detail_callee_authrole = details['callee_authrole']
- if type(detail_callee_authrole) != str:
- raise ProtocolError("invalid type {0} for 'callee_authrole' detail in RESULT".format(type(detail_callee_authrole)))
-
- callee_authrole = detail_callee_authrole
-
- if 'forward_for' in details:
- forward_for = details['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in RESULT")
-
- obj = Result(request,
- args=args,
- kwargs=kwargs,
- payload=payload,
- progress=progress,
- enc_algo=enc_algo,
- enc_key=enc_key,
- enc_serializer=enc_serializer,
- callee=callee,
- callee_authid=callee_authid,
- callee_authrole=callee_authrole,
- forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- details = {}
-
- if self.progress is not None:
- details['progress'] = self.progress
-
- if self.callee is not None:
- details['callee'] = self.callee
- if self.callee_authid is not None:
- details['callee_authid'] = self.callee_authid
- if self.callee_authrole is not None:
- details['callee_authrole'] = self.callee_authrole
- if self.forward_for is not None:
- details['forward_for'] = self.forward_for
-
- if self.payload:
- if self.enc_algo is not None:
- details['enc_algo'] = self.enc_algo
- if self.enc_key is not None:
- details['enc_key'] = self.enc_key
- if self.enc_serializer is not None:
- details['enc_serializer'] = self.enc_serializer
- return [Result.MESSAGE_TYPE, self.request, details, self.payload]
- else:
- if self.kwargs:
- return [Result.MESSAGE_TYPE, self.request, details, self.args, self.kwargs]
- elif self.args:
- return [Result.MESSAGE_TYPE, self.request, details, self.args]
- else:
- return [Result.MESSAGE_TYPE, self.request, details]
-
-
- class Register(Message):
- """
- A WAMP ``REGISTER`` message.
-
- Format: ``[REGISTER, Request|id, Options|dict, Procedure|uri]``
- """
-
- MESSAGE_TYPE = 64
- """
- The WAMP message code for this type of message.
- """
-
- MATCH_EXACT = 'exact'
- MATCH_PREFIX = 'prefix'
- MATCH_WILDCARD = 'wildcard'
-
- INVOKE_SINGLE = 'single'
- INVOKE_FIRST = 'first'
- INVOKE_LAST = 'last'
- INVOKE_ROUNDROBIN = 'roundrobin'
- INVOKE_RANDOM = 'random'
- INVOKE_ALL = 'all'
-
- __slots__ = (
- 'request',
- 'procedure',
- 'match',
- 'invoke',
- 'concurrency',
- 'force_reregister',
- 'forward_for',
- )
-
- def __init__(self,
- request,
- procedure,
- match=None,
- invoke=None,
- concurrency=None,
- force_reregister=None,
- forward_for=None):
- """
-
- :param request: The WAMP request ID of this request.
- :type request: int
-
- :param procedure: The WAMP or application URI of the RPC endpoint provided.
- :type procedure: str
-
- :param match: The procedure matching policy to be used for the registration.
- :type match: str
-
- :param invoke: The procedure invocation policy to be used for the registration.
- :type invoke: str
-
- :param concurrency: The (maximum) concurrency to be used for the registration.
- :type concurrency: int
-
- :param forward_for: When this Register is forwarded over a router-to-router link,
- or via an intermediary router.
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(type(procedure) == str)
- assert(match is None or type(match) == str)
- assert(match is None or match in [Register.MATCH_EXACT, Register.MATCH_PREFIX, Register.MATCH_WILDCARD])
- assert(invoke is None or type(invoke) == str)
- assert(invoke is None or invoke in [Register.INVOKE_SINGLE, Register.INVOKE_FIRST, Register.INVOKE_LAST, Register.INVOKE_ROUNDROBIN, Register.INVOKE_RANDOM])
- assert(concurrency is None or (type(concurrency) == int and concurrency > 0))
- assert force_reregister in [None, True, False]
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.procedure = procedure
- self.match = match or Register.MATCH_EXACT
- self.invoke = invoke or Register.INVOKE_SINGLE
- self.concurrency = concurrency
- self.force_reregister = force_reregister
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Register.MESSAGE_TYPE)
-
- if len(wmsg) != 4:
- raise ProtocolError("invalid message length {0} for REGISTER".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in REGISTER")
- options = check_or_raise_extra(wmsg[2], "'options' in REGISTER")
-
- match = Register.MATCH_EXACT
- invoke = Register.INVOKE_SINGLE
- concurrency = None
- force_reregister = None
- forward_for = None
-
- if 'match' in options:
-
- option_match = options['match']
- if type(option_match) != str:
- raise ProtocolError("invalid type {0} for 'match' option in REGISTER".format(type(option_match)))
-
- if option_match not in [Register.MATCH_EXACT, Register.MATCH_PREFIX, Register.MATCH_WILDCARD]:
- raise ProtocolError("invalid value {0} for 'match' option in REGISTER".format(option_match))
-
- match = option_match
-
- if match == Register.MATCH_EXACT:
- allow_empty_components = False
- allow_last_empty = False
-
- elif match == Register.MATCH_PREFIX:
- allow_empty_components = False
- allow_last_empty = True
-
- elif match == Register.MATCH_WILDCARD:
- allow_empty_components = True
- allow_last_empty = False
-
- else:
- raise Exception("logic error")
-
- procedure = check_or_raise_uri(wmsg[3], "'procedure' in REGISTER", allow_empty_components=allow_empty_components, allow_last_empty=allow_last_empty)
-
- if 'invoke' in options:
-
- option_invoke = options['invoke']
- if type(option_invoke) != str:
- raise ProtocolError("invalid type {0} for 'invoke' option in REGISTER".format(type(option_invoke)))
-
- if option_invoke not in [Register.INVOKE_SINGLE, Register.INVOKE_FIRST, Register.INVOKE_LAST, Register.INVOKE_ROUNDROBIN, Register.INVOKE_RANDOM]:
- raise ProtocolError("invalid value {0} for 'invoke' option in REGISTER".format(option_invoke))
-
- invoke = option_invoke
-
- if 'concurrency' in options:
-
- options_concurrency = options['concurrency']
- if type(options_concurrency) != int:
- raise ProtocolError("invalid type {0} for 'concurrency' option in REGISTER".format(type(options_concurrency)))
-
- if options_concurrency < 1:
- raise ProtocolError("invalid value {0} for 'concurrency' option in REGISTER".format(options_concurrency))
-
- concurrency = options_concurrency
-
- options_reregister = options.get('force_reregister', None)
- if options_reregister not in [True, False, None]:
- raise ProtocolError(
- "invalid type {0} for 'force_reregister option in REGISTER".format(
- type(options_reregister)
- )
- )
- if options_reregister is not None:
- force_reregister = options_reregister
-
- if 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in REGISTER")
-
- obj = Register(request, procedure, match=match, invoke=invoke, concurrency=concurrency,
- force_reregister=force_reregister, forward_for=forward_for)
-
- return obj
-
- def marshal_options(self):
- options = {}
-
- if self.match and self.match != Register.MATCH_EXACT:
- options['match'] = self.match
-
- if self.invoke and self.invoke != Register.INVOKE_SINGLE:
- options['invoke'] = self.invoke
-
- if self.concurrency:
- options['concurrency'] = self.concurrency
-
- if self.force_reregister is not None:
- options['force_reregister'] = self.force_reregister
-
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- return options
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [Register.MESSAGE_TYPE, self.request, self.marshal_options(), self.procedure]
-
-
- class Registered(Message):
- """
- A WAMP ``REGISTERED`` message.
-
- Format: ``[REGISTERED, REGISTER.Request|id, Registration|id]``
- """
-
- MESSAGE_TYPE = 65
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'registration',
- )
-
- def __init__(self, request, registration):
- """
-
- :param request: The request ID of the original ``REGISTER`` request.
- :type request: int
-
- :param registration: The registration ID for the registered procedure (or procedure pattern).
- :type registration: int
- """
- assert(type(request) == int)
- assert(type(registration) == int)
-
- Message.__init__(self)
- self.request = request
- self.registration = registration
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Registered.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for REGISTERED".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in REGISTERED")
- registration = check_or_raise_id(wmsg[2], "'registration' in REGISTERED")
-
- obj = Registered(request, registration)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- return [Registered.MESSAGE_TYPE, self.request, self.registration]
-
-
- class Unregister(Message):
- """
- A WAMP `UNREGISTER` message.
-
- Formats:
-
- * ``[UNREGISTER, Request|id, REGISTERED.Registration|id]``
- * ``[UNREGISTER, Request|id, REGISTERED.Registration|id, Options|dict]``
- """
-
- MESSAGE_TYPE = 66
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'registration',
- 'forward_for',
- )
-
- def __init__(self, request, registration, forward_for=None):
- """
-
- :param request: The WAMP request ID of this request.
- :type request: int
-
- :param registration: The registration ID for the registration to unregister.
- :type registration: int
-
- :param forward_for: When this Unregister is forwarded over a router-to-router link,
- or via an intermediary router.
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(type(registration) == int)
-
- Message.__init__(self)
- self.request = request
- self.registration = registration
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Unregister.MESSAGE_TYPE)
-
- if len(wmsg) not in [3, 4]:
- raise ProtocolError("invalid message length {0} for WAMP UNREGISTER".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in UNREGISTER")
- registration = check_or_raise_id(wmsg[2], "'registration' in UNREGISTER")
-
- options = None
- if len(wmsg) > 3:
- options = check_or_raise_extra(wmsg[3], "'options' in UNREGISTER")
-
- forward_for = None
- if options and 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in UNREGISTER")
-
- obj = Unregister(request, registration, forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- if self.forward_for:
- options = {
- 'forward_for': self.forward_for,
- }
- return [Unregister.MESSAGE_TYPE, self.request, self.registration, options]
- else:
- return [Unregister.MESSAGE_TYPE, self.request, self.registration]
-
-
- class Unregistered(Message):
- """
- A WAMP ``UNREGISTERED`` message.
-
- Formats:
-
- * ``[UNREGISTERED, UNREGISTER.Request|id]``
- * ``[UNREGISTERED, UNREGISTER.Request|id, Details|dict]``
- """
-
- MESSAGE_TYPE = 67
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'registration',
- 'reason',
- )
-
- def __init__(self, request, registration=None, reason=None):
- """
-
- :param request: The request ID of the original ``UNREGISTER`` request.
- :type request: int
-
- :param registration: If unregister was actively triggered by router, the ID
- of the registration revoked.
- :type registration: int or None
-
- :param reason: The reason (an URI) for revocation.
- :type reason: str or None.
- """
- assert(type(request) == int)
- assert(registration is None or type(registration) == int)
- assert(reason is None or type(reason) == str)
- assert((request != 0 and registration is None) or (request == 0 and registration != 0))
-
- Message.__init__(self)
- self.request = request
- self.registration = registration
- self.reason = reason
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Unregistered.MESSAGE_TYPE)
-
- if len(wmsg) not in [2, 3]:
- raise ProtocolError("invalid message length {0} for UNREGISTERED".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in UNREGISTERED")
-
- registration = None
- reason = None
-
- if len(wmsg) > 2:
-
- details = check_or_raise_extra(wmsg[2], "'details' in UNREGISTERED")
-
- if "registration" in details:
- details_registration = details["registration"]
- if type(details_registration) != int:
- raise ProtocolError("invalid type {0} for 'registration' detail in UNREGISTERED".format(type(details_registration)))
- registration = details_registration
-
- if "reason" in details:
- reason = check_or_raise_uri(details["reason"], "'reason' in UNREGISTERED")
-
- obj = Unregistered(request, registration, reason)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- if self.reason is not None or self.registration is not None:
- details = {}
- if self.reason is not None:
- details["reason"] = self.reason
- if self.registration is not None:
- details["registration"] = self.registration
- return [Unregistered.MESSAGE_TYPE, self.request, details]
- else:
- return [Unregistered.MESSAGE_TYPE, self.request]
-
-
- class Invocation(Message):
- """
- A WAMP ``INVOCATION`` message.
-
- Formats:
-
- * ``[INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict]``
- * ``[INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict, CALL.Arguments|list]``
- * ``[INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict, CALL.Arguments|list, CALL.ArgumentsKw|dict]``
- * ``[INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict, Payload|binary]``
- """
-
- MESSAGE_TYPE = 68
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'registration',
- 'args',
- 'kwargs',
- 'payload',
- 'timeout',
- 'receive_progress',
- 'caller',
- 'caller_authid',
- 'caller_authrole',
- 'procedure',
- 'transaction_hash',
- 'enc_algo',
- 'enc_key',
- 'enc_serializer',
- 'forward_for',
- )
-
- def __init__(self,
- request,
- registration,
- args=None,
- kwargs=None,
- payload=None,
- timeout=None,
- receive_progress=None,
- caller=None,
- caller_authid=None,
- caller_authrole=None,
- procedure=None,
- transaction_hash=None,
- enc_algo=None,
- enc_key=None,
- enc_serializer=None,
- forward_for=None):
- """
-
- :param request: The WAMP request ID of this request.
- :type request: int
-
- :param registration: The registration ID of the endpoint to be invoked.
- :type registration: int
-
- :param args: Positional values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type args: list or tuple or None
-
- :param kwargs: Keyword values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type kwargs: dict or None
-
- :param payload: Alternative, transparent payload. If given, ``args`` and ``kwargs`` must be left unset.
- :type payload: bytes or None
-
- :param timeout: If present, let the callee automatically cancels
- the invocation after this ms.
- :type timeout: int or None
-
- :param receive_progress: Indicates if the callee should produce progressive results.
- :type receive_progress: bool or None
-
- :param caller: The WAMP session ID of the caller. Only filled if caller is disclosed.
- :type caller: None or int
-
- :param caller_authid: The WAMP authid of the caller. Only filled if caller is disclosed.
- :type caller_authid: None or unicode
-
- :param caller_authrole: The WAMP authrole of the caller. Only filled if caller is disclosed.
- :type caller_authrole: None or unicode
-
- :param procedure: For pattern-based registrations, the invocation MUST include the actual procedure being called.
- :type procedure: str or None
-
- :param transaction_hash: An application provided transaction hash for the originating call, which may
- be used in the router to throttle or deduplicate the calls on the procedure. See the discussion
- `here <https://github.com/wamp-proto/wamp-proto/issues/391#issuecomment-998577967>`_.
- :type transaction_hash: str
-
- :param enc_algo: If using payload transparency, the encoding algorithm that was used to encode the payload.
- :type enc_algo: str or None
-
- :param enc_key: If using payload transparency with an encryption algorithm, the payload encryption key.
- :type enc_key: str or None
-
- :param enc_serializer: If using payload transparency, the payload object serializer that was used encoding the payload.
- :type enc_serializer: str or None
-
- :param forward_for: When this Call is forwarded for a client (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(type(registration) == int)
- assert(args is None or type(args) in [list, tuple])
- assert(kwargs is None or type(kwargs) == dict)
- assert(payload is None or type(payload) == bytes)
- assert(payload is None or (payload is not None and args is None and kwargs is None))
- assert(timeout is None or type(timeout) == int)
- assert(receive_progress is None or type(receive_progress) == bool)
- assert(caller is None or type(caller) == int)
- assert(caller_authid is None or type(caller_authid) == str)
- assert(caller_authrole is None or type(caller_authrole) == str)
- assert(procedure is None or type(procedure) == str)
- assert(transaction_hash is None or type(transaction_hash) == str)
- assert(enc_algo is None or is_valid_enc_algo(enc_algo))
- assert(enc_key is None or type(enc_key) == str)
- assert(enc_serializer is None or is_valid_enc_serializer(enc_serializer))
- assert((enc_algo is None and enc_key is None and enc_serializer is None) or (payload is not None and enc_algo is not None))
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.registration = registration
- self.args = args
- self.kwargs = _validate_kwargs(kwargs)
- self.payload = payload
- self.timeout = timeout
- self.receive_progress = receive_progress
- self.caller = caller
- self.caller_authid = caller_authid
- self.caller_authrole = caller_authrole
- self.procedure = procedure
- self.transaction_hash = transaction_hash
- self.enc_algo = enc_algo
- self.enc_key = enc_key
- self.enc_serializer = enc_serializer
-
- # message forwarding
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Invocation.MESSAGE_TYPE)
-
- if len(wmsg) not in (4, 5, 6):
- raise ProtocolError("invalid message length {0} for INVOCATION".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in INVOCATION")
- registration = check_or_raise_id(wmsg[2], "'registration' in INVOCATION")
- details = check_or_raise_extra(wmsg[3], "'details' in INVOCATION")
-
- args = None
- kwargs = None
- payload = None
- enc_algo = None
- enc_key = None
- enc_serializer = None
-
- if len(wmsg) == 5 and type(wmsg[4]) == bytes:
-
- payload = wmsg[4]
-
- enc_algo = details.get('enc_algo', None)
- if enc_algo and not is_valid_enc_algo(enc_algo):
- raise ProtocolError("invalid value {0} for 'enc_algo' detail in INVOCATION".format(enc_algo))
-
- enc_key = details.get('enc_key', None)
- if enc_key and type(enc_key) != str:
- raise ProtocolError("invalid type {0} for 'enc_key' detail in INVOCATION".format(type(enc_key)))
-
- enc_serializer = details.get('enc_serializer', None)
- if enc_serializer and not is_valid_enc_serializer(enc_serializer):
- raise ProtocolError("invalid value {0} for 'enc_serializer' detail in INVOCATION".format(enc_serializer))
-
- else:
- if len(wmsg) > 4:
- args = wmsg[4]
- if args is not None and type(args) != list:
- raise ProtocolError("invalid type {0} for 'args' in INVOCATION".format(type(args)))
-
- if len(wmsg) > 5:
- kwargs = wmsg[5]
- if type(kwargs) != dict:
- raise ProtocolError("invalid type {0} for 'kwargs' in INVOCATION".format(type(kwargs)))
-
- timeout = None
- receive_progress = None
- caller = None
- caller_authid = None
- caller_authrole = None
- procedure = None
- transaction_hash = None
- forward_for = None
-
- if 'timeout' in details:
-
- detail_timeout = details['timeout']
- if type(detail_timeout) != int:
- raise ProtocolError("invalid type {0} for 'timeout' detail in INVOCATION".format(type(detail_timeout)))
-
- if detail_timeout < 0:
- raise ProtocolError("invalid value {0} for 'timeout' detail in INVOCATION".format(detail_timeout))
-
- timeout = detail_timeout
-
- if 'receive_progress' in details:
-
- detail_receive_progress = details['receive_progress']
- if type(detail_receive_progress) != bool:
- raise ProtocolError("invalid type {0} for 'receive_progress' detail in INVOCATION".format(type(detail_receive_progress)))
-
- receive_progress = detail_receive_progress
-
- if 'caller' in details:
-
- detail_caller = details['caller']
- if type(detail_caller) != int:
- raise ProtocolError("invalid type {0} for 'caller' detail in INVOCATION".format(type(detail_caller)))
-
- caller = detail_caller
-
- if 'caller_authid' in details:
-
- detail_caller_authid = details['caller_authid']
- if type(detail_caller_authid) != str:
- raise ProtocolError("invalid type {0} for 'caller_authid' detail in INVOCATION".format(type(detail_caller_authid)))
-
- caller_authid = detail_caller_authid
-
- if 'caller_authrole' in details:
-
- detail_caller_authrole = details['caller_authrole']
- if type(detail_caller_authrole) != str:
- raise ProtocolError("invalid type {0} for 'caller_authrole' detail in INVOCATION".format(type(detail_caller_authrole)))
-
- caller_authrole = detail_caller_authrole
-
- if 'procedure' in details:
-
- detail_procedure = details['procedure']
- if type(detail_procedure) != str:
- raise ProtocolError("invalid type {0} for 'procedure' detail in INVOCATION".format(type(detail_procedure)))
-
- procedure = detail_procedure
-
- if 'transaction_hash' in details:
-
- detail_transaction_hash = details['transaction_hash']
- if type(detail_transaction_hash) != str:
- raise ProtocolError("invalid type {0} for 'transaction_hash' detail in EVENT".format(type(detail_transaction_hash)))
-
- transaction_hash = detail_transaction_hash
-
- if 'forward_for' in details:
- forward_for = details['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in INVOCATION")
-
- obj = Invocation(request,
- registration,
- args=args,
- kwargs=kwargs,
- payload=payload,
- timeout=timeout,
- receive_progress=receive_progress,
- caller=caller,
- caller_authid=caller_authid,
- caller_authrole=caller_authrole,
- procedure=procedure,
- transaction_hash=transaction_hash,
- enc_algo=enc_algo,
- enc_key=enc_key,
- enc_serializer=enc_serializer,
- forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- options = {}
-
- if self.timeout is not None:
- options['timeout'] = self.timeout
-
- if self.receive_progress is not None:
- options['receive_progress'] = self.receive_progress
-
- if self.caller is not None:
- options['caller'] = self.caller
-
- if self.caller_authid is not None:
- options['caller_authid'] = self.caller_authid
-
- if self.caller_authrole is not None:
- options['caller_authrole'] = self.caller_authrole
-
- if self.procedure is not None:
- options['procedure'] = self.procedure
-
- if self.transaction_hash is not None:
- options['transaction_hash'] = self.transaction_hash
-
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- if self.payload:
- if self.enc_algo is not None:
- options['enc_algo'] = self.enc_algo
- if self.enc_key is not None:
- options['enc_key'] = self.enc_key
- if self.enc_serializer is not None:
- options['enc_serializer'] = self.enc_serializer
- return [Invocation.MESSAGE_TYPE, self.request, self.registration, options, self.payload]
- else:
- if self.kwargs:
- return [Invocation.MESSAGE_TYPE, self.request, self.registration, options, self.args, self.kwargs]
- elif self.args:
- return [Invocation.MESSAGE_TYPE, self.request, self.registration, options, self.args]
- else:
- return [Invocation.MESSAGE_TYPE, self.request, self.registration, options]
-
-
- class Interrupt(Message):
- """
- A WAMP ``INTERRUPT`` message.
-
- Format: ``[INTERRUPT, INVOCATION.Request|id, Options|dict]``
-
- See: https://wamp-proto.org/static/rfc/draft-oberstet-hybi-crossbar-wamp.html#rfc.section.14.3.4
- """
-
- MESSAGE_TYPE = 69
- """
- The WAMP message code for this type of message.
- """
-
- KILL = 'kill'
- KILLNOWAIT = 'killnowait'
-
- __slots__ = (
- 'request',
- 'mode',
- 'reason',
- 'forward_for',
- )
-
- def __init__(self, request, mode=None, reason=None, forward_for=None):
- """
-
- :param request: The WAMP request ID of the original ``INVOCATION`` to interrupt.
- :type request: int
-
- :param mode: Specifies how to interrupt the invocation (``"killnowait"`` or ``"kill"``).
- With ``"kill"``, the router will wait for the callee to return an ERROR before
- proceeding (sending back an ERROR to the original caller). With ``"killnowait"`` the
- router will immediately proceed (on the caller side returning an ERROR) - but still
- expects the callee to send an ERROR to conclude the message exchange for the inflight
- call.
- :type mode: str or None
-
- :param reason: The reason (an URI) for the invocation interrupt, eg actively
- triggered by the caller (``"wamp.error.canceled"`` - ApplicationError.CANCELED) or
- passively because of timeout (``"wamp.error.timeout"`` - ApplicationError.TIMEOUT).
- :type reason: str or None.
-
- :param forward_for: When this Call is forwarded for a client (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(mode is None or type(mode) == str)
- assert(mode is None or mode in [self.KILL, self.KILLNOWAIT])
- assert(reason is None or type(reason) == str)
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.mode = mode
- self.reason = reason
-
- # message forwarding
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Interrupt.MESSAGE_TYPE)
-
- if len(wmsg) != 3:
- raise ProtocolError("invalid message length {0} for INTERRUPT".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in INTERRUPT")
- options = check_or_raise_extra(wmsg[2], "'options' in INTERRUPT")
-
- # options
- #
- mode = None
- reason = None
- forward_for = None
-
- if 'mode' in options:
-
- option_mode = options['mode']
- if type(option_mode) != str:
- raise ProtocolError("invalid type {0} for 'mode' option in INTERRUPT".format(type(option_mode)))
-
- if option_mode not in [Interrupt.KILL, Interrupt.KILLNOWAIT]:
- raise ProtocolError("invalid value '{0}' for 'mode' option in INTERRUPT".format(option_mode))
-
- mode = option_mode
-
- if 'reason' in options:
- reason = check_or_raise_uri(options['reason'], '"reason" in INTERRUPT')
-
- if 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in INTERRUPT")
-
- obj = Interrupt(request, mode=mode, reason=reason, forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- options = {}
-
- if self.mode is not None:
- options['mode'] = self.mode
-
- if self.reason is not None:
- options['reason'] = self.reason
-
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- return [Interrupt.MESSAGE_TYPE, self.request, options]
-
-
- class Yield(Message):
- """
- A WAMP ``YIELD`` message.
-
- Formats:
-
- * ``[YIELD, INVOCATION.Request|id, Options|dict]``
- * ``[YIELD, INVOCATION.Request|id, Options|dict, Arguments|list]``
- * ``[YIELD, INVOCATION.Request|id, Options|dict, Arguments|list, ArgumentsKw|dict]``
- * ``[YIELD, INVOCATION.Request|id, Options|dict, Payload|binary]``
- """
-
- MESSAGE_TYPE = 70
- """
- The WAMP message code for this type of message.
- """
-
- __slots__ = (
- 'request',
- 'args',
- 'kwargs',
- 'payload',
- 'progress',
- 'enc_algo',
- 'enc_key',
- 'enc_serializer',
- 'callee',
- 'callee_authid',
- 'callee_authrole',
- 'forward_for',
- )
-
- def __init__(self,
- request,
- args=None,
- kwargs=None,
- payload=None,
- progress=None,
- enc_algo=None,
- enc_key=None,
- enc_serializer=None,
- callee=None,
- callee_authid=None,
- callee_authrole=None,
- forward_for=None):
- """
-
- :param request: The WAMP request ID of the original call.
- :type request: int
-
- :param args: Positional values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type args: list or tuple or None
-
- :param kwargs: Keyword values for application-defined event payload.
- Must be serializable using any serializers in use.
- :type kwargs: dict or None
-
- :param payload: Alternative, transparent payload. If given, ``args`` and ``kwargs`` must be left unset.
- :type payload: bytes or None
-
- :param progress: If ``True``, this result is a progressive invocation result, and subsequent
- results (or a final error) will follow.
- :type progress: bool or None
-
- :param enc_algo: If using payload transparency, the encoding algorithm that was used to encode the payload.
- :type enc_algo: str or None
-
- :param enc_key: If using payload transparency with an encryption algorithm, the payload encryption key.
- :type enc_key: str or None
-
- :param enc_serializer: If using payload transparency, the payload object serializer that was used encoding the payload.
- :type enc_serializer: str or None
-
- :param callee: The WAMP session ID of the effective callee that responded with the error. Only filled if callee is disclosed.
- :type callee: None or int
-
- :param callee_authid: The WAMP authid of the responding callee. Only filled if callee is disclosed.
- :type callee_authid: None or unicode
-
- :param callee_authrole: The WAMP authrole of the responding callee. Only filled if callee is disclosed.
- :type callee_authrole: None or unicode
-
- :param forward_for: When this Call is forwarded for a client (or from an intermediary router).
- :type forward_for: list[dict]
- """
- assert(type(request) == int)
- assert(args is None or type(args) in [list, tuple])
- assert(kwargs is None or type(kwargs) == dict)
- assert(payload is None or type(payload) == bytes)
- assert(payload is None or (payload is not None and args is None and kwargs is None))
- assert(progress is None or type(progress) == bool)
- assert(enc_algo is None or is_valid_enc_algo(enc_algo))
- assert((enc_algo is None and enc_key is None and enc_serializer is None) or (payload is not None and enc_algo is not None))
- assert(enc_key is None or type(enc_key) == str)
- assert(enc_serializer is None or is_valid_enc_serializer(enc_serializer))
-
- assert(callee is None or type(callee) == int)
- assert(callee_authid is None or type(callee_authid) == str)
- assert(callee_authrole is None or type(callee_authrole) == str)
-
- assert(forward_for is None or type(forward_for) == list)
- if forward_for:
- for ff in forward_for:
- assert type(ff) == dict
- assert 'session' in ff and type(ff['session']) == int
- assert 'authid' in ff and (ff['authid'] is None or type(ff['authid']) == str)
- assert 'authrole' in ff and type(ff['authrole']) == str
-
- Message.__init__(self)
- self.request = request
- self.args = args
- self.kwargs = _validate_kwargs(kwargs)
- self.payload = payload
- self.progress = progress
- self.enc_algo = enc_algo
- self.enc_key = enc_key
- self.enc_serializer = enc_serializer
-
- # effective callee that responded with the result
- self.callee = callee
- self.callee_authid = callee_authid
- self.callee_authrole = callee_authrole
-
- # message forwarding
- self.forward_for = forward_for
-
- @staticmethod
- def parse(wmsg):
- """
- Verifies and parses an unserialized raw message into an actual WAMP message instance.
-
- :param wmsg: The unserialized raw message.
- :type wmsg: list
-
- :returns: An instance of this class.
- """
- # this should already be verified by WampSerializer.unserialize
- assert(len(wmsg) > 0 and wmsg[0] == Yield.MESSAGE_TYPE)
-
- if len(wmsg) not in (3, 4, 5):
- raise ProtocolError("invalid message length {0} for YIELD".format(len(wmsg)))
-
- request = check_or_raise_id(wmsg[1], "'request' in YIELD")
- options = check_or_raise_extra(wmsg[2], "'options' in YIELD")
-
- args = None
- kwargs = None
- payload = None
- enc_algo = None
- enc_key = None
- enc_serializer = None
-
- if len(wmsg) == 4 and type(wmsg[3]) == bytes:
-
- payload = wmsg[3]
-
- enc_algo = options.get('enc_algo', None)
- if enc_algo and not is_valid_enc_algo(enc_algo):
- raise ProtocolError("invalid value {0} for 'enc_algo' detail in YIELD".format(enc_algo))
-
- enc_key = options.get('enc_key', None)
- if enc_key and type(enc_key) != str:
- raise ProtocolError("invalid type {0} for 'enc_key' detail in YIELD".format(type(enc_key)))
-
- enc_serializer = options.get('enc_serializer', None)
- if enc_serializer and not is_valid_enc_serializer(enc_serializer):
- raise ProtocolError("invalid value {0} for 'enc_serializer' detail in YIELD".format(enc_serializer))
-
- else:
- if len(wmsg) > 3:
- args = wmsg[3]
- if args is not None and type(args) != list:
- raise ProtocolError("invalid type {0} for 'args' in YIELD".format(type(args)))
-
- if len(wmsg) > 4:
- kwargs = wmsg[4]
- if type(kwargs) != dict:
- raise ProtocolError("invalid type {0} for 'kwargs' in YIELD".format(type(kwargs)))
-
- progress = None
- callee = None
- callee_authid = None
- callee_authrole = None
- forward_for = None
-
- if 'progress' in options:
-
- option_progress = options['progress']
- if type(option_progress) != bool:
- raise ProtocolError("invalid type {0} for 'progress' option in YIELD".format(type(option_progress)))
-
- progress = option_progress
-
- if 'callee' in options:
-
- option_callee = options['callee']
- if type(option_callee) != int:
- raise ProtocolError("invalid type {0} for 'callee' detail in YIELD".format(type(option_callee)))
-
- callee = option_callee
-
- if 'callee_authid' in options:
-
- option_callee_authid = options['callee_authid']
- if type(option_callee_authid) != str:
- raise ProtocolError("invalid type {0} for 'callee_authid' detail in YIELD".format(type(option_callee_authid)))
-
- callee_authid = option_callee_authid
-
- if 'callee_authrole' in options:
-
- option_callee_authrole = options['callee_authrole']
- if type(option_callee_authrole) != str:
- raise ProtocolError("invalid type {0} for 'callee_authrole' detail in YIELD".format(type(option_callee_authrole)))
-
- callee_authrole = option_callee_authrole
-
- if 'forward_for' in options:
- forward_for = options['forward_for']
- valid = False
- if type(forward_for) == list:
- for ff in forward_for:
- if type(ff) != dict:
- break
- if 'session' not in ff or type(ff['session']) != int:
- break
- if 'authid' not in ff or type(ff['authid']) != str:
- break
- if 'authrole' not in ff or type(ff['authrole']) != str:
- break
- valid = True
-
- if not valid:
- raise ProtocolError("invalid type/value {0} for/within 'forward_for' option in YIELD")
-
- obj = Yield(request,
- args=args,
- kwargs=kwargs,
- payload=payload,
- progress=progress,
- enc_algo=enc_algo,
- enc_key=enc_key,
- enc_serializer=enc_serializer,
- callee=callee,
- callee_authid=callee_authid,
- callee_authrole=callee_authrole,
- forward_for=forward_for)
-
- return obj
-
- def marshal(self):
- """
- Marshal this object into a raw message for subsequent serialization to bytes.
-
- :returns: The serialized raw message.
- :rtype: list
- """
- options = {}
-
- if self.progress is not None:
- options['progress'] = self.progress
-
- if self.callee is not None:
- options['callee'] = self.callee
- if self.callee_authid is not None:
- options['callee_authid'] = self.callee_authid
- if self.callee_authrole is not None:
- options['callee_authrole'] = self.callee_authrole
- if self.forward_for is not None:
- options['forward_for'] = self.forward_for
-
- if self.payload:
- if self.enc_algo is not None:
- options['enc_algo'] = self.enc_algo
- if self.enc_key is not None:
- options['enc_key'] = self.enc_key
- if self.enc_serializer is not None:
- options['enc_serializer'] = self.enc_serializer
- return [Yield.MESSAGE_TYPE, self.request, options, self.payload]
- else:
- if self.kwargs:
- return [Yield.MESSAGE_TYPE, self.request, options, self.args, self.kwargs]
- elif self.args:
- return [Yield.MESSAGE_TYPE, self.request, options, self.args]
- else:
- return [Yield.MESSAGE_TYPE, self.request, options]
|