endpoint.hpp 456 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745
  1. // Copyright Takatoshi Kondo 2015
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(MQTT_ENDPOINT_HPP)
  7. #define MQTT_ENDPOINT_HPP
  8. #include <mqtt/config.hpp> // should be top to configure variant limit
  9. #include <string>
  10. #include <vector>
  11. #include <deque>
  12. #include <functional>
  13. #include <set>
  14. #include <memory>
  15. #include <mutex>
  16. #include <atomic>
  17. #include <algorithm>
  18. #include <boost/lexical_cast.hpp>
  19. #include <boost/asio.hpp>
  20. #include <boost/lexical_cast.hpp>
  21. #include <boost/multi_index_container.hpp>
  22. #include <boost/multi_index/sequenced_index.hpp>
  23. #include <boost/multi_index/ordered_index.hpp>
  24. #include <boost/multi_index/member.hpp>
  25. #include <boost/multi_index/mem_fun.hpp>
  26. #include <boost/multi_index/composite_key.hpp>
  27. #include <boost/system/error_code.hpp>
  28. #include <boost/assert.hpp>
  29. #include <mqtt/namespace.hpp>
  30. #include <mqtt/tls.hpp>
  31. #include <mqtt/namespace.hpp>
  32. #include <mqtt/attributes.hpp>
  33. #include <mqtt/any.hpp>
  34. #include <mqtt/fixed_header.hpp>
  35. #include <mqtt/remaining_length.hpp>
  36. #include <mqtt/utf8encoded_strings.hpp>
  37. #include <mqtt/connect_flags.hpp>
  38. #include <mqtt/will.hpp>
  39. #include <mqtt/session_present.hpp>
  40. #include <mqtt/subscribe_options.hpp>
  41. #include <mqtt/publish.hpp>
  42. #include <mqtt/connect_return_code.hpp>
  43. #include <mqtt/exception.hpp>
  44. #include <mqtt/tcp_endpoint.hpp>
  45. #include <mqtt/shared_scope_guard.hpp>
  46. #include <mqtt/message_variant.hpp>
  47. #include <mqtt/two_byte_util.hpp>
  48. #include <mqtt/four_byte_util.hpp>
  49. #include <mqtt/packet_id_type.hpp>
  50. #include <mqtt/optional.hpp>
  51. #include <mqtt/property_variant.hpp>
  52. #include <mqtt/protocol_version.hpp>
  53. #include <mqtt/reason_code.hpp>
  54. #include <mqtt/buffer.hpp>
  55. #include <mqtt/shared_ptr_array.hpp>
  56. #include <mqtt/type_erased_socket.hpp>
  57. #include <mqtt/move.hpp>
  58. #include <mqtt/deprecated.hpp>
  59. #include <mqtt/deprecated_msg.hpp>
  60. #include <mqtt/error_code.hpp>
  61. #include <mqtt/log.hpp>
  62. #include <mqtt/variant_visit.hpp>
  63. #include <mqtt/topic_alias_send.hpp>
  64. #include <mqtt/topic_alias_recv.hpp>
  65. #include <mqtt/subscribe_entry.hpp>
  66. #include <mqtt/shared_subscriptions.hpp>
  67. #include <mqtt/packet_id_manager.hpp>
  68. #include <mqtt/store.hpp>
  69. #if defined(MQTT_USE_WS)
  70. #include <mqtt/ws_endpoint.hpp>
  71. #endif // defined(MQTT_USE_WS)
  72. // When https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90415 is fixed,
  73. // update the condition.
  74. // https://gcc.gnu.org/develop.html#timeline
  75. #define MQTT_LIBSTDCXX_GCC_730 20180125 // workaround required
  76. #define MQTT_LIBSTDCXX_GCC_740 20181206 // workaround required
  77. #define MQTT_LIBSTDCXX_GCC_750 20191114 // workaround required
  78. #define MQTT_LIBSTDCXX_GCC_810 20180502 // workaround required
  79. #define MQTT_LIBSTDCXX_GCC_820 20180726
  80. #define MQTT_LIBSTDCXX_GCC_830 20190222
  81. #define MQTT_LIBSTDCXX_GCC_910 20190503 // workaround required
  82. #define MQTT_LIBSTDCXX_GCC_920 20190812 // workaround required
  83. #if !defined(MQTT_DISABLE_LIBSTDCXX_TUPLE_ANY_WORKAROUND)
  84. #if defined(MQTT_STD_ANY) && defined(__GLIBCXX__) && (__GLIBCXX__ != MQTT_LIBSTDCXX_GCC_820) && (__GLIBCXX__ != MQTT_LIBSTDCXX_GCC_830)
  85. template <>
  86. struct std::is_constructible<std::tuple<std::any>> : std::true_type {
  87. };
  88. template <>
  89. struct std::is_constructible<std::tuple<std::any>, std::tuple<std::any> const&> : std::true_type {
  90. };
  91. template <>
  92. struct std::is_copy_constructible<std::tuple<std::any>> : std::true_type {
  93. };
  94. template <>
  95. struct std::is_copy_constructible<std::_Head_base<0, std::any, false>> : std::true_type {
  96. };
  97. template <>
  98. struct std::is_constructible<std::_Head_base<0, std::any, false>, std::_Head_base<0, std::any, false> const&> : std::true_type {
  99. };
  100. #endif // defined(MQTT_STD_ANY) && defined(__GLIBCXX__) && (__GLIBCXX__ != MQTT_LIBSTDCXX_GCC_820) && (__GLIBCXX__ != MQTT_LIBSTDCXX_GCC_830)
  101. #endif // !defined(MQTT_DISABLE_LIBSTDCXX_TUPLE_ANY_WORKAROUND)
  102. #undef MQTT_LIBSTDCXX_GCC_730
  103. #undef MQTT_LIBSTDCXX_GCC_740
  104. #undef MQTT_LIBSTDCXX_GCC_750
  105. #undef MQTT_LIBSTDCXX_GCC_810
  106. #undef MQTT_LIBSTDCXX_GCC_820
  107. #undef MQTT_LIBSTDCXX_GCC_830
  108. #undef MQTT_LIBSTDCXX_GCC_910
  109. #undef MQTT_LIBSTDCXX_GCC_920
  110. #if defined(__GNUC__)
  111. #pragma GCC diagnostic push
  112. #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
  113. #endif // defined(__GNUC__)
  114. #include <boost/asio/yield.hpp>
  115. namespace MQTT_NS {
  116. namespace detail {
  117. template <typename T>
  118. constexpr
  119. std::enable_if_t< ! std::is_convertible<std::decay_t<T>, publish_options>::value, bool>
  120. check_qos_value(T const&) {
  121. return false;
  122. }
  123. constexpr bool check_qos_value(publish_options pubopts) {
  124. return pubopts.get_qos() != qos::at_most_once;
  125. }
  126. template<typename ... Params>
  127. constexpr bool should_generate_packet_id(Params const& ... params) {
  128. #if __cplusplus >= 201703L
  129. return (check_qos_value(params) || ...); // defaults to false for empty.
  130. #else // __cplusplus >= 201703L
  131. const bool results[] = {false, check_qos_value(params)... };
  132. bool ret = false;
  133. for(const bool val : results)
  134. {
  135. ret |= val;
  136. }
  137. return ret;
  138. #endif // __cplusplus >= 201703L
  139. }
  140. } // namespace detail
  141. namespace as = boost::asio;
  142. namespace mi = boost::multi_index;
  143. template <typename Mutex = std::mutex, template<typename...> class LockGuard = std::lock_guard, std::size_t PacketIdBytes = 2>
  144. class endpoint : public std::enable_shared_from_this<endpoint<Mutex, LockGuard, PacketIdBytes>> {
  145. using this_type = endpoint<Mutex, LockGuard, PacketIdBytes>;
  146. using this_type_sp = std::shared_ptr<this_type>;
  147. public:
  148. using async_handler_t = std::function<void(error_code ec)>;
  149. using packet_id_t = typename packet_id_type<PacketIdBytes>::type;
  150. /**
  151. * @brief Constructor for client
  152. * @param ioc io_context
  153. * @param version protocol_version
  154. * @param async_operation
  155. * This flag effects the following automatic operation.
  156. * - puback/pubrec/pubrel/pubcomp if auto_pub_response_ is true.
  157. * - send store data (publish QoS1,2 and pubrel) on connack receive.
  158. * - disconnect
  159. * MQTT protocol requests sending connack/disconnect packet with error reason code if some error happens.<BR>
  160. * This function choose sync/async connack/disconnect.<BR>
  161. */
  162. endpoint(as::io_context& ioc, protocol_version version = protocol_version::undetermined, bool async_operation = false)
  163. :async_operation_{async_operation},
  164. version_(version),
  165. tim_pingresp_(ioc),
  166. tim_shutdown_(ioc)
  167. {
  168. MQTT_LOG("mqtt_api", info)
  169. << MQTT_ADD_VALUE(address, this)
  170. << "create"
  171. << " version:" << version
  172. << " async_operation:" << std::boolalpha << async_operation;
  173. }
  174. /**
  175. * @brief Constructor for server.
  176. * @param ioc io_context
  177. * @param socket connected socket. It should have already been connected with another endpoint.
  178. * @param version protocol_version
  179. * @param async_operation
  180. * This flag effects the following automatic operation.
  181. * - puback/pubrec/pubrel/pubcomp if auto_pub_response_ is true.
  182. * - send store data (publish QoS1,2 and pubrel) on connack receive.
  183. * - disconnect
  184. * MQTT protocol requests sending connack/disconnect packet with error reason code if some error happens.<BR>
  185. * This function choose sync/async connack/disconnect.<BR>
  186. */
  187. explicit endpoint(as::io_context& ioc, std::shared_ptr<MQTT_NS::socket> socket, protocol_version version = protocol_version::undetermined, bool async_operation = false)
  188. :socket_(force_move(socket)),
  189. connected_(true),
  190. async_operation_{async_operation},
  191. version_(version),
  192. tim_pingresp_(ioc),
  193. tim_shutdown_(ioc)
  194. {
  195. MQTT_LOG("mqtt_api", info)
  196. << MQTT_ADD_VALUE(address, this)
  197. << "create"
  198. << " version:" << version
  199. << " async_operation:" << std::boolalpha << async_operation;
  200. }
  201. // MQTT Common handlers
  202. private:
  203. /**
  204. * @brief Pingreq handler
  205. * See http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718086<BR>
  206. * 3.13 PINGREQ – PING request
  207. * @return if the handler returns true, then continue receiving, otherwise quit.
  208. */
  209. virtual bool on_pingreq() noexcept = 0;
  210. /**
  211. * @brief Pingresp handler
  212. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901200<BR>
  213. * 3.13 PINGRESP – PING response
  214. * @return if the handler returns true, then continue receiving, otherwise quit.
  215. */
  216. virtual bool on_pingresp() noexcept = 0;
  217. // MQTT v3_1_1 handlers
  218. /**
  219. * @brief Connect handler
  220. * @param client_id
  221. * Client Identifier.<BR>
  222. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349245<BR>
  223. * 3.1.3.1 Client Identifier
  224. * @param user_name
  225. * User Name.<BR>
  226. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349245<BR>
  227. * 3.1.3.4 User Name
  228. * @param password
  229. * Password.<BR>
  230. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349246<BR>
  231. * 3.1.3.5 Password
  232. * @param will
  233. * Will. It contains retain, QoS, topic, and message.<BR>
  234. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349232<BR>
  235. * 3.1.2.5 Will Flag<BR>
  236. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349233<BR>
  237. * 3.1.2.6 Will QoS<BR>
  238. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349234<BR>
  239. * 3.1.2.7 Will Retain<BR>
  240. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349243<BR>
  241. * 3.1.3.2 Will Topic<BR>
  242. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349244<BR>
  243. * 3.1.3.3 Will Message<BR>
  244. * @param clean_session
  245. * Clean Session<BR>
  246. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349231<BR>
  247. * 3.1.2.4 Clean Session
  248. * @param keep_alive
  249. * Keep Alive<BR>
  250. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349237<BR>
  251. * 3.1.2.10 Keep Alive
  252. * @return if the handler returns true, then continue receiving, otherwise quit.
  253. *
  254. */
  255. virtual bool on_connect(buffer client_id,
  256. optional<buffer> user_name,
  257. optional<buffer> password,
  258. optional<will> will,
  259. bool clean_session,
  260. std::uint16_t keep_alive) noexcept = 0;
  261. /**
  262. * @brief Connack handler
  263. * @param session_present
  264. * Session present flag.<BR>
  265. * See http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718036<BR>
  266. * 3.2.2.2 Session Present
  267. * @param return_code
  268. * connect_return_code<BR>
  269. * See http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718036<BR>
  270. * 3.2.2.3 Connect Return code
  271. * @return if the handler returns true, then continue receiving, otherwise quit.
  272. */
  273. virtual bool on_connack(bool session_present, connect_return_code return_code) noexcept = 0;
  274. /**
  275. * @brief Publish handler
  276. * @param packet_id
  277. * packet identifier<BR>
  278. * If received publish's QoS is 0, packet_id is nullopt.<BR>
  279. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718039<BR>
  280. * 3.3.2 Variable header
  281. * @param pubopts
  282. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718038<BR>
  283. * 3.3.1 Fixed header<BR>
  284. * You can check the fixed header using publish functions.
  285. * @param topic_name
  286. * Topic name
  287. * @param contents
  288. * Published contents
  289. * @return if the handler returns true, then continue receiving, otherwise quit.
  290. */
  291. virtual bool on_publish(optional<packet_id_t> packet_id,
  292. publish_options pubopts,
  293. buffer topic_name,
  294. buffer contents) noexcept = 0;
  295. /**
  296. * @brief Puback handler
  297. * @param packet_id
  298. * packet identifier<BR>
  299. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718045<BR>
  300. * 3.4.2 Variable header
  301. * @return if the handler returns true, then continue receiving, otherwise quit.
  302. */
  303. virtual bool on_puback(packet_id_t packet_id) noexcept = 0;
  304. /**
  305. * @brief Pubrec handler
  306. * @param packet_id
  307. * packet identifier<BR>
  308. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718050<BR>
  309. * 3.5.2 Variable header
  310. * @return if the handler returns true, then continue receiving, otherwise quit.
  311. */
  312. virtual bool on_pubrec(packet_id_t packet_id) noexcept = 0;
  313. /**
  314. * @brief Pubrel handler
  315. * @param packet_id
  316. * packet identifier<BR>
  317. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349791<BR>
  318. * 3.6.2 Variable header
  319. * @return if the handler returns true, then continue receiving, otherwise quit.
  320. */
  321. virtual bool on_pubrel(packet_id_t packet_id) noexcept = 0;
  322. /**
  323. * @brief Pubcomp handler
  324. * @param packet_id
  325. * packet identifier<BR>
  326. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718060<BR>
  327. * 3.7.2 Variable header
  328. * @return if the handler returns true, then continue receiving, otherwise quit.
  329. */
  330. virtual bool on_pubcomp(packet_id_t packet_id) noexcept = 0;
  331. /**
  332. * @brief Subscribe handler
  333. * @param packet_id packet identifier<BR>
  334. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349801<BR>
  335. * 3.8.2 Variable header
  336. * @param entries
  337. * Collection of Share Name, Topic Filter, and QoS.<BR>
  338. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349802<BR>
  339. * @return if the handler returns true, then continue receiving, otherwise quit.
  340. */
  341. virtual bool on_subscribe(packet_id_t packet_id,
  342. std::vector<subscribe_entry> entries) noexcept = 0;
  343. /**
  344. * @brief Suback handler
  345. * @param packet_id packet identifier<BR>
  346. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718070<BR>
  347. * 3.9.2 Variable header
  348. * @param qoss
  349. * Collection of QoS that is corresponding to subscribed topic order.<BR>
  350. * If subscription is failure, the value is nullopt.<BR>
  351. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718071<BR>
  352. * @return if the handler returns true, then continue receiving, otherwise quit.
  353. */
  354. virtual bool on_suback(packet_id_t packet_id, std::vector<suback_return_code> returns) noexcept = 0;
  355. /**
  356. * @brief Unsubscribe handler
  357. * @param packet_id packet identifier<BR>
  358. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349810<BR>
  359. * 3.10.2 Variable header
  360. * @param entries
  361. * Collection of Share Name and Topic Filter<BR>
  362. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc384800448<BR>
  363. * @return if the handler returns true, then continue receiving, otherwise quit.
  364. */
  365. virtual bool on_unsubscribe(packet_id_t packet_id, std::vector<unsubscribe_entry> entries) noexcept = 0;
  366. /**
  367. * @brief Unsuback handler
  368. * @param packet_id packet identifier<BR>
  369. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718045<BR>
  370. * 3.11.2 Variable header
  371. * @return if the handler returns true, then continue receiving, otherwise quit.
  372. */
  373. virtual bool on_unsuback(packet_id_t) noexcept = 0;
  374. /**
  375. * @brief Disconnect handler
  376. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc384800463<BR>
  377. * 3.14 DISCONNECT – Disconnect notification
  378. */
  379. virtual void on_disconnect() noexcept = 0;
  380. // MQTT v5 handlers
  381. /**
  382. * @brief Connect handler
  383. * @param client_id
  384. * Client Identifier.<BR>
  385. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059<BR>
  386. * 3.1.3.1 Client Identifier
  387. * @param user_name
  388. * User Name.<BR>
  389. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901071<BR>
  390. * 3.1.3.4 User Name
  391. * @param password
  392. * Password.<BR>
  393. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901072<BR>
  394. * 3.1.3.5 Password
  395. * @param will
  396. * Will. It contains retain, QoS, propertied, topic, and message.<BR>
  397. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901040<BR>
  398. * 3.1.2.5 Will Flag<BR>
  399. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901041<BR>
  400. * 3.1.2.6 Will QoS<BR>
  401. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901042<BR>
  402. * 3.1.2.7 Will Retain<BR>
  403. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901060<BR>
  404. * 3.1.3.2 Will Properties<BR>
  405. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901069<BR>
  406. * 3.1.3.3 Will Topic<BR>
  407. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901070<BR>
  408. * 3.1.3.3 Will Payload<BR>
  409. * @param clean_start
  410. * Clean Start<BR>
  411. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901039<BR>
  412. * 3.1.2.4 Clean Session
  413. * @param keep_alive
  414. * Keep Alive<BR>
  415. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901045<BR>
  416. * 3.1.2.10 Keep Alive
  417. * @param props
  418. * Properties<BR>
  419. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901046<BR>
  420. * 3.1.2.11 CONNECT Properties
  421. * @return if the handler returns true, then continue receiving, otherwise quit.
  422. *
  423. */
  424. virtual bool on_v5_connect(buffer client_id,
  425. optional<buffer> user_name,
  426. optional<buffer> password,
  427. optional<will> will,
  428. bool clean_start,
  429. std::uint16_t keep_alive,
  430. v5::properties props) noexcept = 0;
  431. /**
  432. * @brief Connack handler
  433. * @param session_present
  434. * Session present flag.<BR>
  435. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901078<BR>
  436. * 3.2.2.1.1 Session Present
  437. * @param reason_code
  438. * Connect Reason Code<BR>
  439. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901079<BR>
  440. * 3.2.2.2 Connect Reason code
  441. * @param props
  442. * Properties<BR>
  443. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901080<BR>
  444. * 3.2.2.3 CONNACK Properties
  445. * @return if the handler returns true, then continue receiving, otherwise quit.
  446. */
  447. virtual bool on_v5_connack(bool session_present,
  448. v5::connect_reason_code reason_code,
  449. v5::properties props) noexcept = 0;
  450. /**
  451. * @brief Publish handler
  452. * @param packet_id
  453. * packet identifier<BR>
  454. * If received publish's QoS is 0, packet_id is nullopt.<BR>
  455. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901108<BR>
  456. * 3.3.2.2 Packet Identifier
  457. * @param pubopts
  458. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901101<BR>
  459. * 3.3.1 Fixed header<BR>
  460. * You can check the fixed header using publish functions.
  461. * @param topic_name
  462. * Topic name<BR>
  463. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901107<BR>
  464. * 3.3.2.1 Topic Name<BR>
  465. * @param contents
  466. * Publish Payload<BR>
  467. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901119<BR>
  468. * 3.3.3 PUBLISH Payload
  469. * @param props
  470. * Properties<BR>
  471. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  472. * 3.3.2.3 PUBLISH Properties
  473. * @return if the handler returns true, then continue receiving, otherwise quit.
  474. */
  475. virtual bool on_v5_publish(optional<packet_id_t> packet_id,
  476. publish_options pubopts,
  477. buffer topic_name,
  478. buffer contents,
  479. v5::properties props) noexcept = 0;
  480. /**
  481. * @brief Puback handler
  482. * @param packet_id
  483. * packet identifier<BR>
  484. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901123<BR>
  485. * 3.4.2 Variable header
  486. * @param reason_code
  487. * PUBACK Reason Code<BR>
  488. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124<BR>
  489. * 3.4.2.1 PUBACK Reason Code
  490. * @param props
  491. * Properties<BR>
  492. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901125<BR>
  493. * 3.4.2.2 PUBACK Properties
  494. * @return if the handler returns true, then continue receiving, otherwise quit.
  495. */
  496. virtual bool on_v5_puback(packet_id_t packet_id,
  497. v5::puback_reason_code reason_code,
  498. v5::properties props) noexcept = 0;
  499. /**
  500. * @brief Pubrec handler
  501. * @param packet_id
  502. * packet identifier<BR>
  503. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901133<BR>
  504. * 3.5.2 Variable header
  505. * @param reason_code
  506. * PUBREC Reason Code<BR>
  507. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901134<BR>
  508. * 3.5.2.1 PUBREC Reason Code
  509. * @param props
  510. * Properties<BR>
  511. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901135<BR>
  512. * 3.5.2.2 PUBREC Properties
  513. * @return if the handler returns true, then continue receiving, otherwise quit.
  514. */
  515. virtual bool on_v5_pubrec(packet_id_t packet_id,
  516. v5::pubrec_reason_code reason_code,
  517. v5::properties props) noexcept = 0;
  518. /**
  519. * @brief Pubrel handler
  520. * @param packet_id
  521. * packet identifier<BR>
  522. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901143<BR>
  523. * 3.6.2 Variable header
  524. * @param reason_code
  525. * PUBREL Reason Code<BR>
  526. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144<BR>
  527. * 3.6.2.1 PUBREL Reason Code
  528. * @param props
  529. * Properties<BR>
  530. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901145<BR>
  531. * 3.6.2.2 PUBREL Properties
  532. * @return if the handler returns true, then continue receiving, otherwise quit.
  533. */
  534. virtual bool on_v5_pubrel(packet_id_t packet_id,
  535. v5::pubrel_reason_code reason_code,
  536. v5::properties props) noexcept = 0;
  537. /**
  538. * @brief Pubcomp handler
  539. * @param packet_id
  540. * packet identifier<BR>
  541. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901153<BR>
  542. * 3.7.2 Variable header
  543. * @param reason_code
  544. * PUBCOMP Reason Code<BR>
  545. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154<BR>
  546. * 3.7.2.1 PUBCOMP Reason Code
  547. * @param props
  548. * Properties<BR>
  549. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901155<BR>
  550. * 3.7.2.2 PUBCOMP Properties
  551. * @return if the handler returns true, then continue receiving, otherwise quit.
  552. */
  553. virtual bool on_v5_pubcomp(packet_id_t packet_id,
  554. v5::pubcomp_reason_code reason_code,
  555. v5::properties props) noexcept = 0;
  556. /**
  557. * @brief Subscribe handler
  558. * @param packet_id packet identifier<BR>
  559. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901163<BR>
  560. * 3.8.2 Variable header
  561. * @param entries
  562. * Collection of Share Name, Topic Filter, and Subscribe Options.<BR>
  563. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901168<BR>
  564. * @param props
  565. * Properties<BR>
  566. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  567. * 3.8.2.1 SUBSCRIBE Properties
  568. * @return if the handler returns true, then continue receiving, otherwise quit.
  569. */
  570. virtual bool on_v5_subscribe(packet_id_t packet_id,
  571. std::vector<subscribe_entry> entries,
  572. v5::properties props) noexcept = 0;
  573. /**
  574. * @brief Suback handler
  575. * @param packet_id packet identifier<BR>
  576. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901173<BR>
  577. * 3.9.2 Variable header
  578. * @param reasons
  579. * Collection of reason_code.<BR>
  580. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178<BR>
  581. * 3.9.3 SUBACK Payload
  582. * @param props
  583. * Properties<BR>
  584. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901174<BR>
  585. * 3.9.2.1 SUBACK Properties
  586. * @return if the handler returns true, then continue receiving, otherwise quit.
  587. */
  588. virtual bool on_v5_suback(packet_id_t packet_id,
  589. std::vector<v5::suback_reason_code> reasons,
  590. v5::properties props) noexcept = 0;
  591. /**
  592. * @brief Unsubscribe handler
  593. * @param packet_id packet identifier<BR>
  594. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901181<BR>
  595. * 3.10.2 Variable header
  596. * @param entries
  597. * Collection of Share Name and Topic Filter<BR>
  598. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901185<BR>
  599. * 3.10.3 UNSUBSCRIBE Payload
  600. * @param props
  601. * Properties<BR>
  602. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  603. * 3.10.2.1 UNSUBSCRIBE Properties
  604. * @return if the handler returns true, then continue receiving, otherwise quit.
  605. */
  606. virtual bool on_v5_unsubscribe(packet_id_t packet_id,
  607. std::vector<unsubscribe_entry> entries,
  608. v5::properties props) noexcept = 0;
  609. /**
  610. * @brief Unsuback handler
  611. * @param packet_id packet identifier<BR>
  612. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901189<BR>
  613. * 3.11.2 Variable header
  614. * @param reasons
  615. * Collection of reason_code.<BR>
  616. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194<BR>
  617. * 3.11.3 UNSUBACK Payload
  618. * @param props
  619. * Properties<BR>
  620. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901190<BR>
  621. * 3.11.2.1 UNSUBACK Properties
  622. * @return if the handler returns true, then continue receiving, otherwise quit.
  623. */
  624. virtual bool on_v5_unsuback(packet_id_t,
  625. std::vector<v5::unsuback_reason_code> reasons,
  626. v5::properties props) noexcept = 0;
  627. /**
  628. * @brief Disconnect handler
  629. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901205<BR>
  630. * 3.14 DISCONNECT – Disconnect notification
  631. * @param reason_code
  632. * DISCONNECT Reason Code<BR>
  633. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901208<BR>
  634. * 3.14.2.1 Disconnect Reason Code
  635. * @param props
  636. * Properties<BR>
  637. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901209<BR>
  638. * 3.14.2.2 DISCONNECT Properties
  639. */
  640. virtual void on_v5_disconnect(v5::disconnect_reason_code reason_code,
  641. v5::properties props) noexcept = 0;
  642. /**
  643. * @brief Auth handler
  644. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901217<BR>
  645. * 3.15 AUTH – Authentication exchange
  646. * @param reason_code
  647. * AUTH Reason Code<BR>
  648. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901220<BR>
  649. * 3.15.2.1 Authenticate Reason Code
  650. * @param props
  651. * Properties<BR>
  652. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901221<BR>
  653. * 3.15.2.2 AUTH Properties
  654. * @return if the handler returns true, then continue receiving, otherwise quit.
  655. */
  656. virtual bool on_v5_auth(v5::auth_reason_code reason_code,
  657. v5::properties props) noexcept = 0;
  658. // Original handlers
  659. protected:
  660. /**
  661. * @brief Close handler
  662. *
  663. * This handler is called if the client called `disconnect()` and the server closed the socket cleanly.
  664. * If the socket is closed by other reasons, error_handler is called.
  665. */
  666. virtual void on_close() noexcept = 0;
  667. /**
  668. * @brief Error handler
  669. *
  670. * This handler is called if the socket is closed without client's `disconnect()` call.
  671. *
  672. * @param ec error code
  673. */
  674. virtual void on_error(error_code ec) noexcept = 0;
  675. private:
  676. /**
  677. * @brief Publish response sent handler
  678. * This function is called just after puback sent on QoS1, or pubcomp sent on QoS2.
  679. * @param packet_id
  680. * packet identifier<BR>
  681. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901026<BR>
  682. * 2.2.1 Packet Identifier
  683. */
  684. virtual void on_pub_res_sent(packet_id_t packet_id) noexcept = 0;
  685. /**
  686. * @brief Serialize publish handler
  687. * You can serialize the publish message.
  688. * To restore the message, use restore_serialized_message().
  689. * @param msg publish message
  690. */
  691. virtual void on_serialize_publish_message(basic_publish_message<sizeof(packet_id_t)> msg) noexcept = 0;
  692. /**
  693. * @brief Serialize publish handler
  694. * You can serialize the publish message.
  695. * To restore the message, use restore_serialized_message().
  696. * @param msg v5::publish message
  697. */
  698. virtual void on_serialize_v5_publish_message(v5::basic_publish_message<sizeof(packet_id_t)> msg) noexcept = 0;
  699. /**
  700. * @brief Serialize pubrel handler
  701. * You can serialize the pubrel message.
  702. * If your storage has already had the publish message that has the same packet_id,
  703. * then you need to replace the publish message to pubrel message.
  704. * To restore the message, use restore_serialized_message().
  705. * @param msg pubrel message
  706. */
  707. virtual void on_serialize_pubrel_message(basic_pubrel_message<sizeof(packet_id_t)> msg) noexcept = 0;
  708. /**
  709. * @brief Serialize pubrel handler
  710. * You can serialize the pubrel message.
  711. * If your storage has already had the publish message that has the same packet_id,
  712. * then you need to replace the publish message to pubrel message.
  713. * To restore the message, use restore_serialized_message().
  714. * @param msg pubrel message
  715. */
  716. virtual void on_serialize_v5_pubrel_message(v5::basic_pubrel_message<sizeof(packet_id_t)> msg) noexcept = 0;
  717. /**
  718. * @brief Remove serialized message
  719. * @param packet_id packet identifier of the removing message
  720. */
  721. virtual void on_serialize_remove(packet_id_t packet_id) noexcept = 0;
  722. protected:
  723. /**
  724. * @brief Pre-send handler
  725. * This handler is called when any mqtt control packet is decided to send.
  726. */
  727. virtual void on_pre_send() noexcept = 0;
  728. private:
  729. /**
  730. * @brief is valid length handler
  731. * This handler is called when remaining length is received.
  732. * @param control_packet_type control_packet_type that has variable length
  733. * @param remaining length
  734. * @return true if check is success, otherwise false
  735. */
  736. virtual bool check_is_valid_length(control_packet_type packet_type, std::size_t remaining_length) noexcept = 0;
  737. protected:
  738. /**
  739. * @brief next read handler
  740. * This handler is called when the current mqtt message has been processed.
  741. * @param func A callback function that is called when async operation will finish.
  742. */
  743. MQTT_ALWAYS_INLINE virtual void on_mqtt_message_processed(any session_life_keeper) {
  744. if (async_read_on_message_processed_) {
  745. async_read_control_packet_type(force_move(session_life_keeper));
  746. }
  747. }
  748. public:
  749. endpoint(this_type const&) = delete;
  750. endpoint(this_type&&) = delete;
  751. endpoint& operator=(this_type const&) = delete;
  752. endpoint& operator=(this_type&&) = delete;
  753. /**
  754. * @brief Get clean session.
  755. *
  756. * See http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc385349231<BR>
  757. * 3.1.2.4 Clean Session<BR>
  758. * After constructing a endpoint, the clean session is set to false.
  759. * @return clean session
  760. */
  761. bool clean_session() const {
  762. return clean_start();
  763. }
  764. /**
  765. * @brief Get clean start.
  766. *
  767. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901039<BR>
  768. * 3.1.2.4 Clean Start<BR>
  769. * After constructing a endpoint, the clean start is set to false.
  770. * @return clean start
  771. */
  772. bool clean_start() const {
  773. return clean_start_;
  774. }
  775. /**
  776. * @brief Get the client id.
  777. * @return The client id of this client.
  778. */
  779. std::string const& get_client_id() const {
  780. return client_id_;
  781. }
  782. /**
  783. * @brief Set client id.
  784. * @param id client id
  785. *
  786. * This function should be called before calling connect().<BR>
  787. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059<BR>
  788. * 3.1.3.1 Client Identifier
  789. */
  790. void set_client_id(std::string id) {
  791. client_id_ = force_move(id);
  792. }
  793. /**
  794. * @brief get_total_bytes_received
  795. * @return The total bytes received on the socket.
  796. */
  797. std::size_t get_total_bytes_received() const {
  798. return total_bytes_received_;
  799. }
  800. /**
  801. * @brief get_total_bytes_sent
  802. * @return The total bytes sent on the socket.
  803. */
  804. std::size_t get_total_bytes_sent() const {
  805. return total_bytes_sent_;
  806. }
  807. /**
  808. * @brief Set auto publish response mode.
  809. * @param b set value
  810. *
  811. * When set auto publish response mode to true, puback, pubrec, pubrel,and pub comp automatically send.<BR>
  812. */
  813. void set_auto_pub_response(bool b = true) {
  814. auto_pub_response_ = b;
  815. }
  816. /**
  817. * @brief Set async operation flag
  818. * @param async if true async , otherwise sync
  819. *
  820. * This function overwrite async_operation_ flag that is set by constructor.
  821. *
  822. * This function should be called before sending any packets.
  823. * For server, in the CONNECT packet receiving handler.
  824. *
  825. * This flag effects the following automatic operation.
  826. * - puback/pubrec/pubrel/pubcomp if auto_pub_response_ is true.
  827. * - send store data (publish QoS1,2 and pubrel) on connack receive.
  828. * - disconnect
  829. * MQTT protocol requests sending connack/disconnect packet with error reason code if some error happens.<BR>
  830. * This function choose sync/async connack/disconnect.<BR>
  831. */
  832. void set_async_operation(bool async = true) {
  833. async_operation_ = async;
  834. }
  835. /**
  836. * @brief Set topic alias send auto mapping enable flag
  837. * @param b set value
  838. *
  839. * If set true then topic alias is automatically used.
  840. * topic alias is allocated and reused by LRU algorithm.
  841. * topic alias that is set manually can be used with this flag.
  842. */
  843. void set_auto_map_topic_alias_send(bool b = true) {
  844. auto_map_topic_alias_send_ = b;
  845. }
  846. /**
  847. * @brief Set topic alias send auto replacing enable flag
  848. * @param b set value
  849. *
  850. * If set true when publish without topic alias and topic alias send
  851. * map has corresponding entry, then use the alias.
  852. * topic alias that is set manually can be used with this flag.
  853. */
  854. void set_auto_replace_topic_alias_send(bool b = true) {
  855. auto_replace_topic_alias_send_ = b;
  856. }
  857. void set_packet_bulk_read_limit(std::size_t size) {
  858. packet_bulk_read_limit_ = size;
  859. }
  860. void set_props_bulk_read_limit(std::size_t size) {
  861. props_bulk_read_limit_ = size;
  862. }
  863. /**
  864. * @brief set topic alias maximum for receiving
  865. * @param max maximum value
  866. *
  867. */
  868. void set_topic_alias_maximum(topic_alias_t max) {
  869. LockGuard<Mutex> lck (topic_alias_recv_mtx_);
  870. if (max == 0) {
  871. topic_alias_recv_ = nullopt;
  872. }
  873. else {
  874. topic_alias_recv_.emplace(max);
  875. }
  876. }
  877. /**
  878. * @brief start session with a connected endpoint.
  879. * @param func finish handler that is called when the session is finished
  880. *
  881. */
  882. void start_session(any session_life_keeper = any()) {
  883. MQTT_LOG("mqtt_api", info)
  884. << MQTT_ADD_VALUE(address, this)
  885. << "start_session";
  886. shutdown_requested_ = false;
  887. async_read_control_packet_type(force_move(session_life_keeper));
  888. }
  889. // Blocking APIs
  890. /**
  891. * @brief Publish
  892. * @param topic_name
  893. * A topic name to publish
  894. * @param contents
  895. * The contents to publish
  896. * @param pubopts
  897. * qos, retain flag, and dup flag.
  898. * @param props (optional)
  899. * Properties<BR>
  900. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  901. * 3.3.2.3 PUBLISH Properties
  902. * @param life_keeper (optional)
  903. * An object that stays alive as long as the library holds a reference to any other parameters.
  904. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  905. * use this parameter to manage their lifetime.
  906. * @return packet_id. If qos is set to at_most_once, return 0.
  907. * packet_id is automatically generated.
  908. *
  909. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  910. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  911. * life_keeper parameter is important.
  912. */
  913. template <typename T, typename... Params>
  914. std::enable_if_t< ! std::is_convertible<std::decay_t<T>, packet_id_t>::value, packet_id_t >
  915. publish(T&& t, Params&&... params) {
  916. if(detail::should_generate_packet_id(params...)) {
  917. packet_id_t packet_id = acquire_unique_packet_id();
  918. publish(packet_id, std::forward<T>(t), std::forward<Params>(params)...);
  919. return packet_id;
  920. }
  921. else {
  922. publish(0, std::forward<T>(t), std::forward<Params>(params)...);
  923. return 0;
  924. }
  925. }
  926. /**
  927. * @brief Subscribe
  928. * @param topic_name
  929. * A topic name to subscribe
  930. * @param option
  931. * subscription options<BR>
  932. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  933. * 3.8.3.1 Subscription Options
  934. * @param props
  935. * Properties<BR>
  936. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  937. * 3.8.2.1 SUBSCRIBE Properties
  938. * @return packet_id.
  939. * packet_id is automatically generated.<BR>
  940. * You can subscribe multiple topics all at once.<BR>
  941. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  942. */
  943. template <typename T, typename... Params>
  944. std::enable_if_t< ! std::is_convertible<std::decay_t<T>, packet_id_t>::value, packet_id_t >
  945. subscribe(T&& t, Params&&... params) {
  946. packet_id_t packet_id = acquire_unique_packet_id();
  947. subscribe(packet_id, std::forward<T>(t), std::forward<Params>(params)...);
  948. return packet_id;
  949. }
  950. /**
  951. * @brief Unsubscribe
  952. * @param topic_name
  953. * A topic name to unsubscribe
  954. * @param props
  955. * Properties<BR>
  956. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  957. * 3.10.2.1 UNSUBSCRIBE Properties
  958. * @return packet_id.
  959. * packet_id is automatically generated.<BR>
  960. * You can subscribe multiple topics all at once.<BR>
  961. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  962. */
  963. template <typename T, typename... Params>
  964. std::enable_if_t< ! std::is_convertible<std::decay_t<T>, packet_id_t>::value, packet_id_t >
  965. unsubscribe(T&& t, Params&&... params) {
  966. packet_id_t packet_id = acquire_unique_packet_id();
  967. unsubscribe(packet_id, std::forward<T>(t), std::forward<Params>(params)...);
  968. return packet_id;
  969. }
  970. /**
  971. * @brief Disconnect
  972. * Send a disconnect packet to the connected broker. It is a clean disconnecting sequence.
  973. * The broker disconnects the endpoint after receives the disconnect packet.<BR>
  974. * When the endpoint disconnects using disconnect(), a will won't send.<BR>
  975. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901205<BR>
  976. * @param reason_code
  977. * DISCONNECT Reason Code<BR>
  978. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901208<BR>
  979. * 3.14.2.1 Disconnect Reason Code
  980. * @param props
  981. * Properties<BR>
  982. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901209<BR>
  983. * 3.14.2.2 DISCONNECT Properties
  984. */
  985. void disconnect(
  986. v5::disconnect_reason_code reason = v5::disconnect_reason_code::normal_disconnection,
  987. v5::properties props = {}
  988. ) {
  989. MQTT_LOG("mqtt_api", info)
  990. << MQTT_ADD_VALUE(address, this)
  991. << "disconnect"
  992. << " reason:" << reason;
  993. if (connected_ && mqtt_connected_) {
  994. disconnect_requested_ = true;
  995. send_disconnect(reason, force_move(props));
  996. }
  997. }
  998. /**
  999. * @brief Disconnect by endpoint
  1000. * Force disconnect. It is not a clean disconnect sequence.<BR>
  1001. * When the endpoint disconnects using force_disconnect(), a will will send.<BR>
  1002. */
  1003. void force_disconnect() {
  1004. MQTT_LOG("mqtt_api", info)
  1005. << MQTT_ADD_VALUE(address, this)
  1006. << "force_disconnect";
  1007. sync_shutdown(socket());
  1008. }
  1009. /**
  1010. * @brief Publish with already acquired packet identifier
  1011. * @param packet_id
  1012. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1013. * The ownership of the packet_id moves to the library.
  1014. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  1015. * @param topic_name
  1016. * A topic name to publish
  1017. * @param contents
  1018. * The contents to publish
  1019. * @param pubopts
  1020. * qos, retain flag, and dup flag.
  1021. * @param props
  1022. * Properties<BR>
  1023. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  1024. * 3.3.2.3 PUBLISH Properties
  1025. * @param life_keeper
  1026. * An object that stays alive as long as the library holds a reference to any other parameters.
  1027. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  1028. * use this parameter to manage their lifetime.
  1029. *
  1030. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  1031. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  1032. * life_keeper parameter is important.
  1033. */
  1034. void publish(
  1035. packet_id_t packet_id,
  1036. std::string topic_name,
  1037. std::string contents,
  1038. publish_options pubopts = {},
  1039. v5::properties props = {},
  1040. any life_keeper = {}
  1041. ) {
  1042. MQTT_LOG("mqtt_api", trace)
  1043. << MQTT_ADD_VALUE(address, this)
  1044. << "publish"
  1045. << " pid:" << packet_id
  1046. << " topic:" << topic_name
  1047. << " qos:" << pubopts.get_qos()
  1048. << " retain:" << pubopts.get_retain()
  1049. << " dup:" << pubopts.get_dup();
  1050. if (pubopts.get_qos() == qos::at_most_once) {
  1051. // In the at_most_once case, we know a priori that send_publish won't track the lifetime.
  1052. send_publish(packet_id,
  1053. as::buffer(topic_name),
  1054. as::buffer(contents),
  1055. pubopts,
  1056. force_move(props),
  1057. any{});
  1058. }
  1059. else {
  1060. auto sp_topic_name = std::make_shared<std::string>(force_move(topic_name));
  1061. auto sp_contents = std::make_shared<std::string>(force_move(contents));
  1062. auto topic_buf = as::buffer(*sp_topic_name);
  1063. auto contents_buf = as::buffer(*sp_contents);
  1064. send_publish(
  1065. packet_id,
  1066. topic_buf,
  1067. contents_buf,
  1068. pubopts,
  1069. force_move(props),
  1070. std::make_tuple(
  1071. force_move(life_keeper),
  1072. force_move(sp_topic_name),
  1073. force_move(sp_contents)
  1074. )
  1075. );
  1076. }
  1077. }
  1078. /**
  1079. * @brief Publish with already acquired packet identifier
  1080. * @param packet_id
  1081. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1082. * The ownership of the packet_id moves to the library.
  1083. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  1084. * @param topic_name
  1085. * A topic name to publish
  1086. * @param contents
  1087. * The contents or the range of the contents to publish
  1088. * @param pubopts
  1089. * qos, retain flag, and dup flag.
  1090. * @param props
  1091. * Properties<BR>
  1092. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  1093. * 3.3.2.3 PUBLISH Properties
  1094. * @param life_keeper
  1095. * An object that stays alive as long as the library holds a reference to any other parameters.
  1096. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  1097. * use this parameter to manage their lifetime.
  1098. *
  1099. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  1100. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  1101. * life_keeper parameter is important.
  1102. */
  1103. template <typename ConstBufferSequence>
  1104. typename std::enable_if<
  1105. as::is_const_buffer_sequence<ConstBufferSequence>::value
  1106. >::type
  1107. publish(
  1108. packet_id_t packet_id,
  1109. as::const_buffer topic_name,
  1110. ConstBufferSequence contents,
  1111. publish_options pubopts,
  1112. v5::properties props,
  1113. any life_keeper
  1114. ) {
  1115. MQTT_LOG("mqtt_api", trace)
  1116. << MQTT_ADD_VALUE(address, this)
  1117. << "publish"
  1118. << " pid:" << packet_id
  1119. << " topic:" << string_view(get_pointer(topic_name), get_size(topic_name))
  1120. << " qos:" << pubopts.get_qos()
  1121. << " retain:" << pubopts.get_retain()
  1122. << " dup:" << pubopts.get_dup();
  1123. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  1124. send_publish(
  1125. packet_id,
  1126. topic_name,
  1127. force_move(contents),
  1128. pubopts,
  1129. force_move(props),
  1130. force_move(life_keeper)
  1131. );
  1132. }
  1133. /**
  1134. * @brief Publish with already acquired packet identifier
  1135. * @param packet_id
  1136. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1137. * The ownership of the packet_id moves to the library.
  1138. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  1139. * @param topic_name
  1140. * A topic name to publish
  1141. * @param contents
  1142. * The contents or the range of the contents to publish
  1143. * @param pubopts
  1144. * qos, retain flag, and dup flag.
  1145. * @param life_keeper
  1146. * An object that stays alive as long as the library holds a reference to any other parameters.
  1147. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  1148. * use this parameter to manage their lifetime.
  1149. *
  1150. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  1151. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  1152. * life_keeper parameter is important.
  1153. */
  1154. template <typename ConstBufferSequence>
  1155. typename std::enable_if<
  1156. as::is_const_buffer_sequence<ConstBufferSequence>::value
  1157. >::type
  1158. publish(
  1159. packet_id_t packet_id,
  1160. as::const_buffer topic_name,
  1161. ConstBufferSequence contents,
  1162. publish_options pubopts,
  1163. any life_keeper
  1164. ) {
  1165. MQTT_LOG("mqtt_api", trace)
  1166. << MQTT_ADD_VALUE(address, this)
  1167. << "publish"
  1168. << " pid:" << packet_id
  1169. << " topic:" << string_view(get_pointer(topic_name), get_size(topic_name))
  1170. << " qos:" << pubopts.get_qos()
  1171. << " retain:" << pubopts.get_retain()
  1172. << " dup:" << pubopts.get_dup();
  1173. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  1174. send_publish(
  1175. packet_id,
  1176. topic_name,
  1177. force_move(contents),
  1178. pubopts,
  1179. v5::properties{},
  1180. force_move(life_keeper)
  1181. );
  1182. }
  1183. /**
  1184. * @brief Publish with already acquired packet identifier
  1185. * @param packet_id
  1186. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1187. * The ownership of the packet_id moves to the library.
  1188. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  1189. * @param topic_name
  1190. * A topic name to publish
  1191. * @param contents
  1192. * The contents or the range of the contents to publish
  1193. * @param pubopts
  1194. * qos, retain flag, and dup flag.
  1195. * @param life_keeper
  1196. * An object that stays alive as long as the library holds a reference to any other parameters.
  1197. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  1198. * use this parameter to manage their lifetime.
  1199. *
  1200. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  1201. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  1202. * life_keeper parameter is important.
  1203. * If topic_name and contents don't manage their lifetimes, then life_keeper should be used to keep
  1204. * their lifetimes.
  1205. */
  1206. template <typename BufferSequence>
  1207. typename std::enable_if<
  1208. is_buffer_sequence<BufferSequence>::value
  1209. >::type
  1210. publish(
  1211. packet_id_t packet_id,
  1212. buffer topic_name,
  1213. BufferSequence contents,
  1214. publish_options pubopts = {},
  1215. any life_keeper = {}
  1216. ) {
  1217. MQTT_LOG("mqtt_api", trace)
  1218. << MQTT_ADD_VALUE(address, this)
  1219. << "publish"
  1220. << " pid:" << packet_id
  1221. << " topic:" << topic_name
  1222. << " qos:" << pubopts.get_qos()
  1223. << " retain:" << pubopts.get_retain()
  1224. << " dup:" << pubopts.get_dup();
  1225. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  1226. auto topic_name_buf = as::buffer(topic_name);
  1227. std::vector<as::const_buffer> cbs;
  1228. {
  1229. auto b = MQTT_NS::buffer_sequence_begin(contents);
  1230. auto e = MQTT_NS::buffer_sequence_end(contents);
  1231. cbs.reserve(static_cast<std::size_t>(std::distance(b, e)));
  1232. for (; b != e; ++b) {
  1233. cbs.emplace_back(as::buffer(*b));
  1234. }
  1235. }
  1236. send_publish(
  1237. packet_id,
  1238. topic_name_buf,
  1239. force_move(cbs),
  1240. pubopts,
  1241. v5::properties{},
  1242. std::make_tuple(
  1243. force_move(life_keeper),
  1244. force_move(topic_name),
  1245. force_move(contents)
  1246. )
  1247. );
  1248. }
  1249. /**
  1250. * @brief Publish with already acquired packet identifier
  1251. * @param packet_id
  1252. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1253. * The ownership of the packet_id moves to the library.
  1254. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  1255. * @param topic_name
  1256. * A topic name to publish
  1257. * @param contents
  1258. * The contents or the range of the contents to publish
  1259. * @param pubopts
  1260. * qos, retain flag, and dup flag.
  1261. * @param props
  1262. * Properties<BR>
  1263. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  1264. * 3.3.2.3 PUBLISH Properties
  1265. * @param life_keeper
  1266. * An object that stays alive as long as the library holds a reference to any other parameters.
  1267. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  1268. * use this parameter to manage their lifetime.
  1269. *
  1270. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  1271. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  1272. * life_keeper parameter is important.
  1273. */
  1274. template <typename BufferSequence>
  1275. typename std::enable_if<
  1276. is_buffer_sequence<BufferSequence>::value
  1277. >::type
  1278. publish(
  1279. packet_id_t packet_id,
  1280. buffer topic_name,
  1281. BufferSequence contents,
  1282. publish_options pubopts,
  1283. v5::properties props,
  1284. any life_keeper = {}
  1285. ) {
  1286. MQTT_LOG("mqtt_api", trace)
  1287. << MQTT_ADD_VALUE(address, this)
  1288. << "publish"
  1289. << " pid:" << packet_id
  1290. << " topic:" << topic_name
  1291. << " qos:" << pubopts.get_qos()
  1292. << " retain:" << pubopts.get_retain()
  1293. << " dup:" << pubopts.get_dup();
  1294. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  1295. auto topic_name_buf = as::buffer(topic_name);
  1296. std::vector<as::const_buffer> cbs;
  1297. {
  1298. auto b = MQTT_NS::buffer_sequence_begin(contents);
  1299. auto e = MQTT_NS::buffer_sequence_end(contents);
  1300. cbs.reserve(static_cast<std::size_t>(std::distance(b, e)));
  1301. for (; b != e; ++b) {
  1302. cbs.emplace_back(as::buffer(*b));
  1303. }
  1304. }
  1305. send_publish(
  1306. packet_id,
  1307. topic_name_buf,
  1308. force_move(cbs),
  1309. pubopts,
  1310. force_move(props),
  1311. std::make_tuple(
  1312. force_move(life_keeper),
  1313. force_move(topic_name),
  1314. force_move(contents)
  1315. )
  1316. );
  1317. }
  1318. /**
  1319. * @brief Subscribe with already acquired packet identifier
  1320. * @param packet_id
  1321. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1322. * The ownership of the packet_id moves to the library.
  1323. * @param topic_filter
  1324. * A topic filter to subscribe
  1325. * @param option
  1326. * subscription options<BR>
  1327. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  1328. * 3.8.3.1 Subscription Options
  1329. * @param props
  1330. * Properties<BR>
  1331. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  1332. * 3.8.2.1 SUBSCRIBE Properties
  1333. * You can subscribe multiple topics all at once.<BR>
  1334. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161<BR>
  1335. */
  1336. void subscribe(
  1337. packet_id_t packet_id,
  1338. string_view topic_filter,
  1339. subscribe_options option,
  1340. v5::properties props = {}
  1341. ) {
  1342. MQTT_LOG("mqtt_api", info)
  1343. << MQTT_ADD_VALUE(address, this)
  1344. << "subscribe"
  1345. << " pid:" << packet_id
  1346. << " topic:" << topic_filter
  1347. << " qos:" << option.get_qos()
  1348. << " rh:" << option.get_retain_handling()
  1349. << " nl:" << option.get_nl()
  1350. << " rap:" << option.get_rap();
  1351. send_subscribe(
  1352. std::vector<std::tuple<as::const_buffer, subscribe_options>>{
  1353. { as::buffer(topic_filter.data(), topic_filter.size()), option }
  1354. },
  1355. packet_id,
  1356. force_move(props)
  1357. );
  1358. }
  1359. /**
  1360. * @brief Subscribe with already acquired packet identifier
  1361. * @param packet_id
  1362. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1363. * The ownership of the packet_id moves to the library.
  1364. * @param topic_filter
  1365. * A topic filter to subscribe
  1366. * @param option
  1367. * subscription options<BR>
  1368. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  1369. * 3.8.3.1 Subscription Options
  1370. * @param props
  1371. * Properties<BR>
  1372. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  1373. * 3.8.2.1 SUBSCRIBE Properties
  1374. * You can subscribe multiple topics all at once.<BR>
  1375. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161<BR>
  1376. */
  1377. void subscribe(
  1378. packet_id_t packet_id,
  1379. as::const_buffer topic_filter,
  1380. subscribe_options option,
  1381. v5::properties props = {}
  1382. ) {
  1383. MQTT_LOG("mqtt_api", info)
  1384. << MQTT_ADD_VALUE(address, this)
  1385. << "subscribe"
  1386. << " pid:" << packet_id
  1387. << " topic:" << string_view(get_pointer(topic_filter), get_size(topic_filter))
  1388. << " qos:" << option.get_qos()
  1389. << " rh:" << option.get_retain_handling()
  1390. << " nl:" << option.get_nl()
  1391. << " rap:" << option.get_rap();
  1392. send_subscribe(
  1393. std::vector<std::tuple<as::const_buffer, subscribe_options>>{ { topic_filter, option } },
  1394. packet_id,
  1395. force_move(props)
  1396. );
  1397. }
  1398. /**
  1399. * @brief Subscribe with already acquired packet identifier
  1400. * @param packet_id
  1401. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1402. * The ownership of the packet_id moves to the library.
  1403. * @param params a vector of the topic_filter and qos pair.
  1404. * @param props
  1405. * Properties<BR>
  1406. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  1407. * 3.8.2.1 SUBSCRIBE Properties
  1408. * You can subscribe multiple topics all at once.<BR>
  1409. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161<BR>
  1410. */
  1411. void subscribe(
  1412. packet_id_t packet_id,
  1413. std::vector<std::tuple<string_view, subscribe_options>> params,
  1414. v5::properties props = {}
  1415. ) {
  1416. MQTT_LOG("mqtt_api", info)
  1417. << MQTT_ADD_VALUE(address, this)
  1418. << "subscribe"
  1419. << " pid:" << packet_id;
  1420. std::vector<std::tuple<as::const_buffer, subscribe_options>> cb_params;
  1421. cb_params.reserve(params.size());
  1422. for (auto const& e : params) {
  1423. cb_params.emplace_back(as::buffer(std::get<0>(e).data(), std::get<0>(e).size()), std::get<1>(e));
  1424. }
  1425. send_subscribe(force_move(cb_params), packet_id, force_move(props));
  1426. }
  1427. /**
  1428. * @brief Subscribe with already acquired packet identifier
  1429. * @param packet_id
  1430. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1431. * The ownership of the packet_id moves to the library.
  1432. * @param params a vector of the subscribe_entry.
  1433. * @param props
  1434. * Properties<BR>
  1435. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  1436. * 3.8.2.1 SUBSCRIBE Properties
  1437. * You can subscribe multiple topics all at once.<BR>
  1438. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161<BR>
  1439. */
  1440. void subscribe(
  1441. packet_id_t packet_id,
  1442. std::vector<std::tuple<buffer, subscribe_options>> params,
  1443. v5::properties props = {}
  1444. ) {
  1445. MQTT_LOG("mqtt_api", info)
  1446. << MQTT_ADD_VALUE(address, this)
  1447. << "subscribe"
  1448. << " pid:" << packet_id;
  1449. std::vector<std::tuple<as::const_buffer, subscribe_options>> buffers;
  1450. buffers.reserve(params.size());
  1451. for (auto const& tup : params) {
  1452. buffers.emplace_back(as::buffer(std::get<0>(tup)), std::get<1>(tup));
  1453. }
  1454. send_subscribe(force_move(buffers), packet_id, force_move(props));
  1455. }
  1456. /**
  1457. * @brief Unsubscribe with already acquired packet identifier
  1458. * @param packet_id
  1459. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1460. * The ownership of the packet_id moves to the library.
  1461. * @param topic_filter
  1462. * A topic filter to unsubscribe
  1463. * @param props
  1464. * Properties<BR>
  1465. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  1466. * 3.10.2.1 UNSUBSCRIBE Properties
  1467. * You can subscribe multiple topics all at once.<BR>
  1468. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  1469. */
  1470. void unsubscribe(
  1471. packet_id_t packet_id,
  1472. string_view topic_filter,
  1473. v5::properties props = {}
  1474. ) {
  1475. MQTT_LOG("mqtt_api", info)
  1476. << MQTT_ADD_VALUE(address, this)
  1477. << "unsubscribe"
  1478. << " pid:" << packet_id
  1479. << " topic:" << topic_filter;
  1480. send_unsubscribe(
  1481. std::vector<as::const_buffer> {
  1482. as::buffer(topic_filter.data(), topic_filter.size())
  1483. },
  1484. packet_id,
  1485. force_move(props)
  1486. );
  1487. }
  1488. /**
  1489. * @brief Unsubscribe with already acquired packet identifier
  1490. * @param packet_id
  1491. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1492. * The ownership of the packet_id moves to the library.
  1493. * @param topic_filter
  1494. * A topic filter to unsubscribe
  1495. * @param props
  1496. * Properties<BR>
  1497. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  1498. * 3.10.2.1 UNSUBSCRIBE Properties
  1499. * You can subscribe multiple topics all at once.<BR>
  1500. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  1501. */
  1502. void unsubscribe(
  1503. packet_id_t packet_id,
  1504. as::const_buffer topic_filter,
  1505. v5::properties props = {}
  1506. ) {
  1507. MQTT_LOG("mqtt_api", info)
  1508. << MQTT_ADD_VALUE(address, this)
  1509. << "unsubscribe"
  1510. << " pid:" << packet_id
  1511. << " topic:" << string_view(get_pointer(topic_filter), get_size(topic_filter));
  1512. send_unsubscribe(std::vector<as::const_buffer>{ topic_filter }, packet_id, force_move(props));
  1513. }
  1514. /**
  1515. * @brief Unsubscribe with already acquired packet identifier
  1516. * @param packet_id
  1517. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1518. * The ownership of the packet_id moves to the library.
  1519. * @param params a collection of topic_filter
  1520. * @param props
  1521. * Properties<BR>
  1522. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  1523. * 3.10.2.1 UNSUBSCRIBE Properties
  1524. * You can subscribe multiple topics all at once.<BR>
  1525. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  1526. */
  1527. void unsubscribe(
  1528. packet_id_t packet_id,
  1529. std::vector<string_view> params,
  1530. v5::properties props = {}
  1531. ) {
  1532. MQTT_LOG("mqtt_api", info)
  1533. << MQTT_ADD_VALUE(address, this)
  1534. << "unsubscribe"
  1535. << " pid:" << packet_id;
  1536. std::vector<as::const_buffer> cb_params;
  1537. cb_params.reserve(params.size());
  1538. for (auto&& e : params) {
  1539. cb_params.emplace_back(as::buffer(e.data(), e.size()));
  1540. }
  1541. send_unsubscribe(force_move(cb_params), packet_id, force_move(props));
  1542. }
  1543. /**
  1544. * @brief Unsubscribe with already acquired packet identifier
  1545. * @param packet_id
  1546. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1547. * The ownership of the packet_id moves to the library.
  1548. * @param params a collection of topic_filter
  1549. * @param props
  1550. * Properties<BR>
  1551. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  1552. * 3.10.2.1 UNSUBSCRIBE Properties
  1553. * You can subscribe multiple topics all at once.<BR>
  1554. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  1555. */
  1556. void unsubscribe(
  1557. packet_id_t packet_id,
  1558. std::vector<as::const_buffer> params,
  1559. v5::properties props = {}
  1560. ) {
  1561. MQTT_LOG("mqtt_api", info)
  1562. << MQTT_ADD_VALUE(address, this)
  1563. << "unsubscribe"
  1564. << " pid:" << packet_id;
  1565. std::vector<buffer> cb_params;
  1566. cb_params.reserve(params.size());
  1567. for (auto&& e : params) {
  1568. cb_params.emplace_back(buffer(string_view(get_pointer(e), get_size(e))));
  1569. }
  1570. send_unsubscribe(params, packet_id, force_move(props));
  1571. }
  1572. /**
  1573. * @brief Unsubscribe with already acquired packet identifier
  1574. * @param packet_id
  1575. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  1576. * The ownership of the packet_id moves to the library.
  1577. * @param params a collection of topic_filter
  1578. * @param props
  1579. * Properties<BR>
  1580. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  1581. * 3.10.2.1 UNSUBSCRIBE Properties
  1582. * You can subscribe multiple topics all at once.<BR>
  1583. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  1584. */
  1585. void unsubscribe(
  1586. packet_id_t packet_id,
  1587. std::vector<buffer> params,
  1588. v5::properties props = {}
  1589. ) {
  1590. MQTT_LOG("mqtt_api", info)
  1591. << MQTT_ADD_VALUE(address, this)
  1592. << "unsubscribe"
  1593. << " pid:" << packet_id;
  1594. std::vector<as::const_buffer> cb_params;
  1595. cb_params.reserve(params.size());
  1596. for (auto&& e : params) {
  1597. cb_params.emplace_back(as::buffer(e));
  1598. }
  1599. send_unsubscribe(force_move(cb_params), packet_id, force_move(props));
  1600. }
  1601. /**
  1602. * @brief Send pingreq packet.
  1603. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901195
  1604. */
  1605. void pingreq() {
  1606. // pingreq might frequently send, so SEV is set to trace
  1607. MQTT_LOG("mqtt_api", trace)
  1608. << MQTT_ADD_VALUE(address, this)
  1609. << "pingreq";
  1610. if (connected_ && mqtt_connected_) send_pingreq();
  1611. }
  1612. /**
  1613. * @brief Send pingresp packet. This function is for broker.
  1614. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901200
  1615. */
  1616. void pingresp() {
  1617. // pingresp might frequently send, so SEV is set to trace
  1618. MQTT_LOG("mqtt_api", trace)
  1619. << MQTT_ADD_VALUE(address, this)
  1620. << "pingrsp";
  1621. send_pingresp();
  1622. }
  1623. /**
  1624. * @brief Send auth packet.
  1625. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718086
  1626. * @param reason_code
  1627. * AUTH Reason Code<BR>
  1628. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901220<BR>
  1629. * 3.15.2.1 Authenticate Reason Code
  1630. * @param props
  1631. * Properties<BR>
  1632. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901221<BR>
  1633. * 3.15.2.2 AUTH Properties
  1634. */
  1635. void auth(
  1636. v5::auth_reason_code reason_code = v5::auth_reason_code::success,
  1637. v5::properties props = {}
  1638. ) {
  1639. MQTT_LOG("mqtt_api", info)
  1640. << MQTT_ADD_VALUE(address, this)
  1641. << "auth"
  1642. << " reason:" << reason_code;
  1643. send_auth(reason_code, force_move(props));
  1644. }
  1645. /**
  1646. * @brief Send connect packet.
  1647. * @param client_id
  1648. * The client id to use for this connection<BR>
  1649. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059<BR>
  1650. * 3.1.3.1 Client Identifier (ClientID)
  1651. * @param user_name
  1652. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901071<BR>
  1653. * 3.1.3.5 User Name
  1654. * @param password
  1655. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901072<BR>
  1656. * 3.1.3.6 Password
  1657. * @param w
  1658. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc479576982<BR>
  1659. * 3.1.2.5 Will Flag
  1660. * @param clean_session
  1661. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901039<BR>
  1662. * 3.1.2.4 Clean Start<BR>
  1663. * @param keep_alive_sec
  1664. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349238
  1665. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718028
  1666. * @param keep_alive_sec
  1667. * Keep Alive<BR>
  1668. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901045<BR>
  1669. * 3.1.2.10 Keep Alive
  1670. * @param props
  1671. * Properties<BR>
  1672. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901046<BR>
  1673. * 3.1.2.11 CONNECT Properties
  1674. */
  1675. void connect(
  1676. std::string const& client_id,
  1677. optional<std::string> const& user_name,
  1678. optional<std::string> const& password,
  1679. optional<will> w,
  1680. std::uint16_t keep_alive_sec,
  1681. v5::properties props = {}
  1682. ) {
  1683. MQTT_LOG("mqtt_api", info)
  1684. << MQTT_ADD_VALUE(address, this)
  1685. << "connect"
  1686. << " client_id:" << client_id
  1687. << " user_name:" << (user_name ? user_name.value() : "none")
  1688. << " keep_alive:" << std::dec << keep_alive_sec;
  1689. connect_requested_ = true;
  1690. send_connect(
  1691. buffer(string_view(client_id)),
  1692. [&] {
  1693. if (user_name) {
  1694. return buffer(string_view(user_name.value()));
  1695. }
  1696. else {
  1697. return buffer();
  1698. }
  1699. } (),
  1700. [&] {
  1701. if (password) {
  1702. return buffer(string_view(password.value()));
  1703. }
  1704. else {
  1705. return buffer();
  1706. }
  1707. } (),
  1708. force_move(w),
  1709. keep_alive_sec,
  1710. force_move(props)
  1711. );
  1712. }
  1713. /**
  1714. * @brief Send connect packet.
  1715. * @param client_id
  1716. * The client id to use for this connection<BR>
  1717. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059<BR>
  1718. * 3.1.3.1 Client Identifier (ClientID)
  1719. * @param user_name
  1720. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901071<BR>
  1721. * 3.1.3.5 User Name
  1722. * @param password
  1723. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901072<BR>
  1724. * 3.1.3.6 Password
  1725. * @param w
  1726. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc479576982<BR>
  1727. * 3.1.2.5 Will Flag
  1728. * @param clean_session
  1729. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901039<BR>
  1730. * 3.1.2.4 Clean Start<BR>
  1731. * @param keep_alive_sec
  1732. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349238
  1733. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718028
  1734. * @param keep_alive_sec
  1735. * Keep Alive<BR>
  1736. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901045<BR>
  1737. * 3.1.2.10 Keep Alive
  1738. * @param props
  1739. * Properties<BR>
  1740. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901046<BR>
  1741. * 3.1.2.11 CONNECT Properties
  1742. */
  1743. void connect(
  1744. buffer client_id,
  1745. optional<buffer> user_name,
  1746. optional<buffer> password,
  1747. optional<will> w,
  1748. std::uint16_t keep_alive_sec,
  1749. v5::properties props = {}
  1750. ) {
  1751. MQTT_LOG("mqtt_api", info)
  1752. << MQTT_ADD_VALUE(address, this)
  1753. << "connect"
  1754. << " client_id:" << client_id
  1755. << " user_name:" << (user_name ? string_view(user_name.value()) : string_view("none"))
  1756. << " keep_alive:" << std::dec << keep_alive_sec;
  1757. connect_requested_ = true;
  1758. send_connect(
  1759. force_move(client_id),
  1760. force_move(user_name),
  1761. force_move(password),
  1762. force_move(w),
  1763. keep_alive_sec,
  1764. force_move(props)
  1765. );
  1766. }
  1767. /**
  1768. * @brief Send connack packet. This function is for broker.
  1769. * @param session_present See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349255
  1770. * @param reason_code See reason_code.hpp and https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349256
  1771. * @param props
  1772. * Properties<BR>
  1773. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901080<BR>
  1774. * 3.2.2.3 CONNACK Properties
  1775. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718033
  1776. */
  1777. void connack(
  1778. bool session_present,
  1779. variant<connect_return_code, v5::connect_reason_code> reason_code,
  1780. v5::properties props = {}
  1781. ) {
  1782. MQTT_LOG("mqtt_api", info)
  1783. << MQTT_ADD_VALUE(address, this)
  1784. << "connack"
  1785. << " session_present:" << std::boolalpha << session_present
  1786. << " reason:" << reason_code;
  1787. send_connack(session_present, reason_code, force_move(props));
  1788. }
  1789. /**
  1790. * @brief Send puback packet.
  1791. * @param packet_id packet id corresponding to publish
  1792. * @param reason_code
  1793. * PUBACK Reason Code<BR>
  1794. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124<BR>
  1795. * 3.4.2.1 PUBACK Reason Code
  1796. * @param props
  1797. * Properties<BR>
  1798. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901125<BR>
  1799. * 3.4.2.2 PUBACK Properties
  1800. */
  1801. void puback(
  1802. packet_id_t packet_id,
  1803. v5::puback_reason_code reason_code = v5::puback_reason_code::success,
  1804. v5::properties props = {}
  1805. ) {
  1806. MQTT_LOG("mqtt_api", trace)
  1807. << MQTT_ADD_VALUE(address, this)
  1808. << "puback"
  1809. << " pid:" << packet_id
  1810. << " reason:" << reason_code;
  1811. send_puback(packet_id, reason_code, force_move(props));
  1812. }
  1813. /**
  1814. * @brief Send packet.
  1815. * @param packet_id packet id corresponding to publish
  1816. * @param reason_code
  1817. * Reason Code<BR>
  1818. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901134<BR>
  1819. * 3.5.2.1 Reason Code
  1820. * @param props
  1821. * Properties<BR>
  1822. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901135<BR>
  1823. * 3.5.2.2 Properties
  1824. */
  1825. void pubrec(
  1826. packet_id_t packet_id,
  1827. v5::pubrec_reason_code reason_code = v5::pubrec_reason_code::success,
  1828. v5::properties props = {}
  1829. ) {
  1830. MQTT_LOG("mqtt_api", trace)
  1831. << MQTT_ADD_VALUE(address, this)
  1832. << "pubrec"
  1833. << " pid:" << packet_id
  1834. << " reason:" << reason_code;
  1835. send_pubrec(packet_id, reason_code, force_move(props));
  1836. }
  1837. /**
  1838. * @brief Send pubrel packet.
  1839. * @param packet_id packet id corresponding to publish
  1840. * @param reason_code
  1841. * PUBREL Reason Code<BR>
  1842. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144<BR>
  1843. * 3.6.2.1 PUBREL Reason Code
  1844. * @param props
  1845. * Properties<BR>
  1846. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901145<BR>
  1847. * 3.6.2.2 PUBREL Properties
  1848. * @param life_keeper
  1849. * An object that stays alive as long as the library holds a reference to any other parameters.
  1850. * If your props are not using built-in lifetime management, (e.g. buffer)
  1851. * use this parameter to manage their lifetime.
  1852. *
  1853. * @note The library may store this message while it communicates with the server for several round trips.
  1854. * As such, the life_keeper paramter is important.
  1855. */
  1856. void pubrel(
  1857. packet_id_t packet_id,
  1858. v5::pubrel_reason_code reason_code = v5::pubrel_reason_code::success,
  1859. v5::properties props = {},
  1860. any life_keeper = {}
  1861. ) {
  1862. MQTT_LOG("mqtt_api", trace)
  1863. << MQTT_ADD_VALUE(address, this)
  1864. << "pubrel"
  1865. << " pid:" << packet_id
  1866. << " reason:" << reason_code;
  1867. send_pubrel(packet_id, reason_code, force_move(props), force_move(life_keeper));
  1868. }
  1869. /**
  1870. * @brief Send pubcomp packet.
  1871. * @param packet_id packet id corresponding to publish
  1872. * @param reason_code
  1873. * PUBCOMP Reason Code<BR>
  1874. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154<BR>
  1875. * 3.7.2.1 PUBCOMP Reason Code
  1876. * @param props
  1877. * Properties<BR>
  1878. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901155<BR>
  1879. * 3.7.2.2 PUBCOMP Properties
  1880. */
  1881. void pubcomp(
  1882. packet_id_t packet_id,
  1883. v5::pubcomp_reason_code reason_code = v5::pubcomp_reason_code::success,
  1884. v5::properties props = {}
  1885. ) {
  1886. MQTT_LOG("mqtt_api", trace)
  1887. << MQTT_ADD_VALUE(address, this)
  1888. << "pubcomp"
  1889. << " pid:" << packet_id
  1890. << " reason:" << reason_code;
  1891. send_pubcomp(packet_id, reason_code, force_move(props));
  1892. }
  1893. /**
  1894. * @brief Send suback packet. This function is for broker.
  1895. * @param packet_id packet id corresponding to subscribe
  1896. * @param reason
  1897. * reason_code<BR>
  1898. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178<BR>
  1899. * 3.9.3 SUBACK Payload
  1900. * @param props
  1901. * Properties<BR>
  1902. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901174<BR>
  1903. * 3.9.2.1 SUBACK Properties
  1904. */
  1905. void suback(
  1906. packet_id_t packet_id,
  1907. variant<suback_return_code, v5::suback_reason_code> reason,
  1908. v5::properties props = {}
  1909. ) {
  1910. MQTT_LOG("mqtt_api", info)
  1911. << MQTT_ADD_VALUE(address, this)
  1912. << "suback"
  1913. << " pid:" << packet_id
  1914. << " reason:" < reason;
  1915. if (variant_idx(reason) == 0) {
  1916. send_suback(std::vector<suback_return_code>{ variant_get<suback_return_code>(reason) }, packet_id, force_move(props));
  1917. }
  1918. else {
  1919. send_suback(std::vector<v5::suback_reason_code>{ variant_get<v5::suback_reason_code>(reason) }, packet_id, force_move(props));
  1920. }
  1921. }
  1922. /**
  1923. * @brief Send suback packet. This function is for broker.
  1924. * @param packet_id packet id corresponding to subscribe
  1925. * @param reasons
  1926. * a collection of reason_code<BR>
  1927. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178<BR>
  1928. * 3.9.3 SUBACK Payload
  1929. * @param props
  1930. * Properties<BR>
  1931. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901174<BR>
  1932. * 3.9.2.1 SUBACK Properties
  1933. */
  1934. void suback(
  1935. packet_id_t packet_id,
  1936. variant<std::vector<suback_return_code>, std::vector<v5::suback_reason_code>> reasons,
  1937. v5::properties props = {}
  1938. ) {
  1939. MQTT_LOG("mqtt_api", info)
  1940. << MQTT_ADD_VALUE(address, this)
  1941. << "suback"
  1942. << " pid:" << packet_id;
  1943. send_suback(force_move(reasons), packet_id, force_move(props));
  1944. }
  1945. /**
  1946. * @brief Send unsuback packet. This function is for broker.
  1947. * @param packet_id packet id corresponding to subscribe
  1948. */
  1949. void unsuback(
  1950. packet_id_t packet_id
  1951. ) {
  1952. MQTT_LOG("mqtt_api", info)
  1953. << MQTT_ADD_VALUE(address, this)
  1954. << "unsuback"
  1955. << " pid:" << packet_id;
  1956. send_unsuback(packet_id);
  1957. }
  1958. /**
  1959. * @brief Send unsuback packet. This function is for broker.
  1960. * @param packet_id packet id corresponding to subscribe
  1961. * @param reason
  1962. * reason_code<BR>
  1963. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194<BR>
  1964. * 3.11.3 UNSUBACK Payload
  1965. * @param props
  1966. * Properties<BR>
  1967. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901190<BR>
  1968. * 3.11.2.1 UNSUBACK Properties
  1969. */
  1970. void unsuback(
  1971. packet_id_t packet_id,
  1972. v5::unsuback_reason_code reason,
  1973. v5::properties props = {}
  1974. ) {
  1975. MQTT_LOG("mqtt_api", info)
  1976. << MQTT_ADD_VALUE(address, this)
  1977. << "unsuback"
  1978. << " pid:" << packet_id
  1979. << " reason:" << reason;
  1980. send_unsuback(std::vector<v5::unsuback_reason_code>{ reason }, packet_id, force_move(props));
  1981. }
  1982. /**
  1983. * @brief Send unsuback packet. This function is for broker.
  1984. * @param packet_id packet id corresponding to subscribe
  1985. * @param reasons
  1986. * a collection of reason_code<BR>
  1987. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194<BR>
  1988. * 3.11.3 UNSUBACK Payload
  1989. * @param props
  1990. * Properties<BR>
  1991. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901190<BR>
  1992. * 3.11.2.1 UNSUBACK Properties
  1993. */
  1994. void unsuback(
  1995. packet_id_t packet_id,
  1996. std::vector<v5::unsuback_reason_code> reasons,
  1997. v5::properties props = {}
  1998. ) {
  1999. MQTT_LOG("mqtt_api", info)
  2000. << MQTT_ADD_VALUE(address, this)
  2001. << "unsuback"
  2002. << " pid:" << packet_id;
  2003. send_unsuback(force_move(reasons), packet_id, force_move(props));
  2004. }
  2005. /**
  2006. * @brief Publish
  2007. * @param topic_name
  2008. * A topic name to publish
  2009. * @param contents
  2010. * The contents to publish
  2011. * @param pubopts
  2012. * qos, retain flag, and dup flag.
  2013. * @param props
  2014. * Properties<BR>
  2015. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  2016. * 3.3.2.3 PUBLISH Properties
  2017. * @param life_keeper
  2018. * An object that stays alive as long as the library holds a reference to any other parameters.
  2019. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  2020. * use this parameter to manage their lifetime.
  2021. *
  2022. * @return packet_id. If qos is set to at_most_once, return 0.
  2023. * packet_id is automatically generated.
  2024. *
  2025. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  2026. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  2027. * life_keeper parameter is important.
  2028. */
  2029. template <typename T, typename... Params>
  2030. std::enable_if_t< ! std::is_convertible<std::decay_t<T>, packet_id_t>::value >
  2031. async_publish(T&& t, Params&&... params) {
  2032. if(detail::should_generate_packet_id(params...)) {
  2033. packet_id_t packet_id = acquire_unique_packet_id();
  2034. async_publish(packet_id, std::forward<T>(t), std::forward<Params>(params)...);
  2035. }
  2036. else {
  2037. async_publish(0, std::forward<T>(t), std::forward<Params>(params)...);
  2038. }
  2039. }
  2040. /**
  2041. * @brief Disconnect
  2042. * @param func
  2043. * functor object who's operator() will be called when the async operation completes.
  2044. * Send a disconnect packet to the connected broker. It is a clean disconnecting sequence.
  2045. * The broker disconnects the endpoint after receives the disconnect packet.<BR>
  2046. * When the endpoint disconnects using disconnect(), a will won't send.<BR>
  2047. */
  2048. void async_disconnect(
  2049. async_handler_t func = {}
  2050. ) {
  2051. MQTT_LOG("mqtt_api", info)
  2052. << MQTT_ADD_VALUE(address, this)
  2053. << "async_disconnect";
  2054. if (connected_ && mqtt_connected_) {
  2055. disconnect_requested_ = true;
  2056. // The reason code and property vector are only used if we're using mqttv5.
  2057. async_send_disconnect(v5::disconnect_reason_code::normal_disconnection,
  2058. v5::properties{},
  2059. force_move(func));
  2060. }
  2061. else {
  2062. socket_->post(
  2063. [func = force_move(func)] {
  2064. if (func) func(boost::system::errc::make_error_code(boost::system::errc::success));
  2065. }
  2066. );
  2067. }
  2068. }
  2069. /**
  2070. * @brief Disconnect
  2071. * @param reason
  2072. * DISCONNECT Reason Code<BR>
  2073. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901208<BR>
  2074. * 3.14.2.1 Disconnect Reason Code
  2075. * @param props
  2076. * Properties<BR>
  2077. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901209<BR>
  2078. * 3.14.2.2 DISCONNECT Properties
  2079. * @param func
  2080. * functor object who's operator() will be called when the async operation completes.
  2081. * Send a disconnect packet to the connected broker. It is a clean disconnecting sequence.
  2082. * The broker disconnects the endpoint after receives the disconnect packet.<BR>
  2083. * When the endpoint disconnects using disconnect(), a will won't send.<BR>
  2084. */
  2085. void async_disconnect(
  2086. v5::disconnect_reason_code reason,
  2087. v5::properties props = {},
  2088. async_handler_t func = {}
  2089. ) {
  2090. MQTT_LOG("mqtt_api", info)
  2091. << MQTT_ADD_VALUE(address, this)
  2092. << "async_disconnect"
  2093. << " reason:" << reason;
  2094. if (connected_ && mqtt_connected_) {
  2095. disconnect_requested_ = true;
  2096. async_send_disconnect(reason, force_move(props), force_move(func));
  2097. }
  2098. else {
  2099. socket_->post(
  2100. [func = force_move(func)] {
  2101. if (func) func(boost::system::errc::make_error_code(boost::system::errc::success));
  2102. }
  2103. );
  2104. }
  2105. }
  2106. /**
  2107. * @brief Disconnect by endpoint
  2108. * @param func
  2109. * functor object who's operator() will be called when the async operation completes.
  2110. * Force disconnect. It is not a clean disconnect sequence.<BR>
  2111. * When the endpoint disconnects using force_disconnect(), a will will send.<BR>
  2112. */
  2113. void async_force_disconnect(
  2114. async_handler_t func = {}
  2115. ) {
  2116. MQTT_LOG("mqtt_api", info)
  2117. << MQTT_ADD_VALUE(address, this)
  2118. << "async_force_disconnect";
  2119. socket_->post(
  2120. [this, self = this->shared_from_this(), func = force_move(func)] () mutable {
  2121. async_shutdown(socket(), force_move(func));
  2122. }
  2123. );
  2124. }
  2125. // packet_id manual setting version
  2126. /**
  2127. * @brief Subscribe
  2128. * @param topic_name
  2129. * A topic name to subscribe
  2130. * @param option
  2131. * subscription options<BR>
  2132. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2133. * 3.8.3.1 Subscription Options
  2134. * @param func
  2135. * functor object who's operator() will be called when the async operation completes.
  2136. * packet_id is automatically generated.<BR>
  2137. * You can subscribe multiple topics all at once.<BR>
  2138. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2139. */
  2140. template <typename T, typename... Params>
  2141. std::enable_if_t< ! std::is_convertible<std::decay_t<T>, packet_id_t>::value >
  2142. async_subscribe(T&& t, Params&&... params) {
  2143. packet_id_t packet_id = acquire_unique_packet_id();
  2144. async_subscribe(packet_id, std::forward<T>(t), std::forward<Params>(params)...);
  2145. }
  2146. /**
  2147. * @brief Unsubscribe
  2148. * @param topic_name
  2149. * A topic name to unsubscribe
  2150. * @param func
  2151. * functor object who's operator() will be called when the async operation completes.
  2152. * packet_id is automatically generated.<BR>
  2153. * You can subscribe multiple topics all at once.<BR>
  2154. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  2155. */
  2156. template <typename T, typename... Params>
  2157. std::enable_if_t< ! std::is_convertible<std::decay_t<T>, packet_id_t>::value >
  2158. async_unsubscribe(T&& t, Params&&... params) {
  2159. packet_id_t packet_id = acquire_unique_packet_id();
  2160. async_unsubscribe(packet_id, std::forward<T>(t), std::forward<Params>(params)...);
  2161. }
  2162. /**
  2163. * @brief Publish with a manual set packet identifier
  2164. * @param packet_id
  2165. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2166. * The ownership of the packet_id moves to the library.
  2167. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  2168. * @param topic_name
  2169. * A topic name to publish
  2170. * @param contents
  2171. * The contents to publish
  2172. * @param pubopts
  2173. * qos, retain flag, and dup flag.
  2174. * @param func
  2175. * functor object who's operator() will be called when the async operation completes.
  2176. */
  2177. void async_publish(
  2178. packet_id_t packet_id,
  2179. std::string topic_name,
  2180. std::string contents,
  2181. publish_options pubopts = {},
  2182. async_handler_t func = {}
  2183. ) {
  2184. MQTT_LOG("mqtt_api", trace)
  2185. << MQTT_ADD_VALUE(address, this)
  2186. << "async_publish"
  2187. << " pid:" << packet_id
  2188. << " topic:" << topic_name
  2189. << " qos:" << pubopts.get_qos()
  2190. << " retain:" << pubopts.get_retain()
  2191. << " dup:" << pubopts.get_dup();
  2192. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  2193. auto sp_topic_name = std::make_shared<std::string>(force_move(topic_name));
  2194. auto sp_contents = std::make_shared<std::string>(force_move(contents));
  2195. auto topic_name_buf = as::buffer(*sp_topic_name);
  2196. auto contents_buf = as::buffer(*sp_contents);
  2197. async_send_publish(
  2198. packet_id,
  2199. topic_name_buf,
  2200. contents_buf,
  2201. pubopts,
  2202. v5::properties{},
  2203. std::make_pair(force_move(sp_topic_name), force_move(sp_contents)),
  2204. force_move(func)
  2205. );
  2206. }
  2207. /**
  2208. * @brief Publish with a manual set packet identifier
  2209. * @param packet_id
  2210. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2211. * The ownership of the packet_id moves to the library.
  2212. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  2213. * @param topic_name
  2214. * A topic name to publish
  2215. * @param contents
  2216. * The contents to publish
  2217. * @param pubopts
  2218. * qos, retain flag, and dup flag.
  2219. * @param props
  2220. * Properties<BR>
  2221. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  2222. * 3.3.2.3 PUBLISH Properties
  2223. * @param life_keeper
  2224. * An object that stays alive as long as the library holds a reference to any other parameters.
  2225. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  2226. * use this parameter to manage their lifetime.
  2227. * @param func
  2228. * functor object who's operator() will be called when the async operation completes.
  2229. *
  2230. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  2231. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  2232. * life_keeper parameter is important.
  2233. */
  2234. void async_publish(
  2235. packet_id_t packet_id,
  2236. std::string topic_name,
  2237. std::string contents,
  2238. publish_options pubopts,
  2239. v5::properties props,
  2240. any life_keeper = {},
  2241. async_handler_t func = {}
  2242. ) {
  2243. MQTT_LOG("mqtt_api", trace)
  2244. << MQTT_ADD_VALUE(address, this)
  2245. << "async_publish"
  2246. << " pid:" << packet_id
  2247. << " topic:" << topic_name
  2248. << " qos:" << pubopts.get_qos()
  2249. << " retain:" << pubopts.get_retain()
  2250. << " dup:" << pubopts.get_dup();
  2251. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  2252. auto sp_topic_name = std::make_shared<std::string>(force_move(topic_name));
  2253. auto sp_contents = std::make_shared<std::string>(force_move(contents));
  2254. auto topic_name_buf = as::buffer(*sp_topic_name);
  2255. auto contents_buf = as::buffer(*sp_contents);
  2256. async_send_publish(
  2257. packet_id,
  2258. topic_name_buf,
  2259. contents_buf,
  2260. pubopts,
  2261. force_move(props),
  2262. std::make_tuple(
  2263. force_move(life_keeper),
  2264. force_move(sp_topic_name),
  2265. force_move(sp_contents)
  2266. ),
  2267. force_move(func)
  2268. );
  2269. }
  2270. /**
  2271. * @brief Publish with a manual set packet identifier
  2272. * @param packet_id
  2273. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2274. * The ownership of the packet_id moves to the library.
  2275. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  2276. * @param topic_name
  2277. * A topic name to publish
  2278. * @param contents
  2279. * The contents or the range of the contents to publish
  2280. * @param pubopts
  2281. * qos, retain flag, and dup flag.
  2282. * @param life_keeper
  2283. * An object that stays alive as long as the library holds a reference to any other parameters.
  2284. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  2285. * use this parameter to manage their lifetime.
  2286. * @param func
  2287. * functor object who's operator() will be called when the async operation completes.
  2288. *
  2289. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  2290. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  2291. * life_keeper parameter is important.
  2292. */
  2293. template <typename ConstBufferSequence>
  2294. typename std::enable_if<
  2295. as::is_const_buffer_sequence<ConstBufferSequence>::value
  2296. >::type
  2297. async_publish(
  2298. packet_id_t packet_id,
  2299. as::const_buffer topic_name,
  2300. ConstBufferSequence contents,
  2301. publish_options pubopts = {},
  2302. any life_keeper = {},
  2303. async_handler_t func = {}
  2304. ) {
  2305. MQTT_LOG("mqtt_api", trace)
  2306. << MQTT_ADD_VALUE(address, this)
  2307. << "async_publish"
  2308. << " pid:" << packet_id
  2309. << " topic:" << string_view(get_pointer(topic_name), get_size(topic_name))
  2310. << " qos:" << pubopts.get_qos()
  2311. << " retain:" << pubopts.get_retain()
  2312. << " dup:" << pubopts.get_dup();
  2313. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  2314. async_send_publish(
  2315. packet_id,
  2316. topic_name,
  2317. force_move(contents),
  2318. pubopts,
  2319. v5::properties{},
  2320. force_move(life_keeper),
  2321. force_move(func)
  2322. );
  2323. }
  2324. /**
  2325. * @brief Publish with a manual set packet identifier
  2326. * @param packet_id
  2327. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2328. * The ownership of the packet_id moves to the library.
  2329. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  2330. * @param topic_name
  2331. * A topic name to publish
  2332. * @param contents
  2333. * The contents or the range of the contents to publish
  2334. * @param pubopts
  2335. * qos, retain flag, and dup flag.
  2336. * @param props
  2337. * Properties<BR>
  2338. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  2339. * 3.3.2.3 PUBLISH Properties
  2340. * @param life_keeper
  2341. * An object that stays alive as long as the library holds a reference to any other parameters.
  2342. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  2343. * use this parameter to manage their lifetime.
  2344. * @param func
  2345. * functor object who's operator() will be called when the async operation completes.
  2346. */
  2347. template <typename ConstBufferSequence>
  2348. typename std::enable_if<
  2349. as::is_const_buffer_sequence<ConstBufferSequence>::value
  2350. >::type
  2351. async_publish(
  2352. packet_id_t packet_id,
  2353. as::const_buffer topic_name,
  2354. ConstBufferSequence contents,
  2355. publish_options pubopts,
  2356. v5::properties props,
  2357. any life_keeper = {},
  2358. async_handler_t func = {}
  2359. ) {
  2360. MQTT_LOG("mqtt_api", trace)
  2361. << MQTT_ADD_VALUE(address, this)
  2362. << "async_publish"
  2363. << " pid:" << packet_id
  2364. << " topic:" << string_view(get_pointer(topic_name), get_size(topic_name))
  2365. << " qos:" << pubopts.get_qos()
  2366. << " retain:" << pubopts.get_retain()
  2367. << " dup:" << pubopts.get_dup();
  2368. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  2369. async_send_publish(
  2370. packet_id,
  2371. topic_name,
  2372. force_move(contents),
  2373. pubopts,
  2374. force_move(props),
  2375. force_move(life_keeper),
  2376. force_move(func)
  2377. );
  2378. }
  2379. /**
  2380. * @brief Publish with a manual set packet identifier
  2381. * @param packet_id
  2382. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2383. * The ownership of the packet_id moves to the library.
  2384. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  2385. * @param topic_name
  2386. * A topic name to publish
  2387. * @param contents
  2388. * The contents or the range of the contents to publish
  2389. * @param pubopts
  2390. * qos, retain flag, and dup flag.
  2391. * @param life_keeper
  2392. * An object that stays alive as long as the library holds a reference to any other parameters.
  2393. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  2394. * use this parameter to manage their lifetime.
  2395. * @param func
  2396. * functor object who's operator() will be called when the async operation completes.
  2397. */
  2398. template <typename BufferSequence>
  2399. typename std::enable_if<
  2400. is_buffer_sequence<BufferSequence>::value
  2401. >::type
  2402. async_publish(
  2403. packet_id_t packet_id,
  2404. buffer topic_name,
  2405. BufferSequence contents,
  2406. publish_options pubopts = {},
  2407. any life_keeper = {},
  2408. async_handler_t func = {}
  2409. ) {
  2410. MQTT_LOG("mqtt_api", trace)
  2411. << MQTT_ADD_VALUE(address, this)
  2412. << "async_publish"
  2413. << " pid:" << packet_id
  2414. << " topic:" << topic_name
  2415. << " qos:" << pubopts.get_qos()
  2416. << " retain:" << pubopts.get_retain()
  2417. << " dup:" << pubopts.get_dup();
  2418. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  2419. auto topic_name_buf = as::buffer(topic_name);
  2420. std::vector<as::const_buffer> cbs;
  2421. {
  2422. auto b = MQTT_NS::buffer_sequence_begin(contents);
  2423. auto e = MQTT_NS::buffer_sequence_end(contents);
  2424. cbs.reserve(static_cast<std::size_t>(std::distance(b, e)));
  2425. for (; b != e; ++b) {
  2426. cbs.emplace_back(as::buffer(*b));
  2427. }
  2428. }
  2429. async_send_publish(
  2430. packet_id,
  2431. topic_name_buf,
  2432. force_move(cbs),
  2433. pubopts,
  2434. v5::properties{},
  2435. std::make_tuple(
  2436. force_move(life_keeper),
  2437. force_move(topic_name),
  2438. force_move(contents)
  2439. ),
  2440. force_move(func)
  2441. );
  2442. }
  2443. /**
  2444. * @brief Publish with a manual set packet identifier
  2445. * @param packet_id
  2446. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2447. * The ownership of the packet_id moves to the library.
  2448. * If qos == qos::at_most_once, packet_id must be 0. But not checked in release mode due to performance.
  2449. * @param topic_name
  2450. * A topic name to publish
  2451. * @param contents
  2452. * The contents or the range of the contents to publish
  2453. * @param pubopts
  2454. * qos, retain flag, and dup flag.
  2455. * @param props
  2456. * Properties<BR>
  2457. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901109<BR>
  2458. * 3.3.2.3 PUBLISH Properties
  2459. * @param life_keeper
  2460. * An object that stays alive as long as the library holds a reference to any other parameters.
  2461. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  2462. * use this parameter to manage their lifetime.
  2463. * @param func
  2464. * functor object who's operator() will be called when the async operation completes.
  2465. *
  2466. * @note If your QOS level is exactly_once or at_least_once, then the library will store this publish
  2467. * internally until the broker has confirmed delivery, which may involve resends, and as such the
  2468. * life_keeper parameter is important.
  2469. */
  2470. template <typename BufferSequence>
  2471. typename std::enable_if<
  2472. is_buffer_sequence<BufferSequence>::value
  2473. >::type
  2474. async_publish(
  2475. packet_id_t packet_id,
  2476. buffer topic_name,
  2477. BufferSequence contents,
  2478. publish_options pubopts,
  2479. v5::properties props,
  2480. any life_keeper = {},
  2481. async_handler_t func = {}
  2482. ) {
  2483. MQTT_LOG("mqtt_api", trace)
  2484. << MQTT_ADD_VALUE(address, this)
  2485. << "async_publish"
  2486. << " pid:" << packet_id
  2487. << " topic:" << topic_name
  2488. << " qos:" << pubopts.get_qos()
  2489. << " retain:" << pubopts.get_retain()
  2490. << " dup:" << pubopts.get_dup();
  2491. BOOST_ASSERT((pubopts.get_qos() == qos::at_most_once && packet_id == 0) || (pubopts.get_qos() != qos::at_most_once && packet_id != 0));
  2492. auto topic_name_buf = as::buffer(topic_name);
  2493. std::vector<as::const_buffer> cbs;
  2494. {
  2495. auto b = MQTT_NS::buffer_sequence_begin(contents);
  2496. auto e = MQTT_NS::buffer_sequence_end(contents);
  2497. cbs.reserve(static_cast<std::size_t>(std::distance(b, e)));
  2498. for (; b != e; ++b) {
  2499. cbs.emplace_back(as::buffer(*b));
  2500. }
  2501. }
  2502. async_send_publish(
  2503. packet_id,
  2504. topic_name_buf,
  2505. force_move(cbs),
  2506. pubopts,
  2507. force_move(props),
  2508. std::make_tuple(
  2509. force_move(life_keeper),
  2510. force_move(topic_name),
  2511. force_move(contents)
  2512. ),
  2513. force_move(func)
  2514. );
  2515. }
  2516. /**
  2517. * @brief Subscribe
  2518. * @param packet_id
  2519. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2520. * The ownership of the packet_id moves to the library.
  2521. * @param topic_filter
  2522. * A topic filter to subscribe
  2523. * @param option
  2524. * subscription options<BR>
  2525. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2526. * 3.8.3.1 Subscription Options
  2527. * @param props
  2528. * Properties<BR>
  2529. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  2530. * 3.8.2.1 SUBSCRIBE Properties
  2531. * @param func
  2532. * functor object who's operator() will be called when the async operation completes.
  2533. * You can subscribe multiple topics all at once.<BR>
  2534. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2535. */
  2536. void async_subscribe(
  2537. packet_id_t packet_id,
  2538. std::string topic_filter,
  2539. subscribe_options option,
  2540. async_handler_t func = {}
  2541. ) {
  2542. MQTT_LOG("mqtt_api", info)
  2543. << MQTT_ADD_VALUE(address, this)
  2544. << "async_subscribe"
  2545. << " pid:" << packet_id
  2546. << " topic:" << topic_filter
  2547. << " qos:" << option.get_qos()
  2548. << " rh:" << option.get_retain_handling()
  2549. << " nl:" << option.get_nl()
  2550. << " rap:" << option.get_rap();
  2551. auto sp_topic_filter = std::make_shared<std::string>(force_move(topic_filter));
  2552. auto topic_filter_buf = as::buffer(*sp_topic_filter);
  2553. async_send_subscribe(
  2554. std::vector<std::tuple<as::const_buffer, subscribe_options>>{ { topic_filter_buf, option } },
  2555. packet_id,
  2556. v5::properties{},
  2557. [life_keeper = force_move(sp_topic_filter), func = force_move(func)]
  2558. (error_code ec) {
  2559. if(func) func(ec);
  2560. }
  2561. );
  2562. }
  2563. /**
  2564. * @brief Subscribe
  2565. * @param packet_id
  2566. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2567. * The ownership of the packet_id moves to the library.
  2568. * @param topic_filter
  2569. * A topic filter to subscribe
  2570. * @param option
  2571. * subscription options<BR>
  2572. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2573. * 3.8.3.1 Subscription Options
  2574. * @param props
  2575. * Properties<BR>
  2576. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  2577. * 3.8.2.1 SUBSCRIBE Properties
  2578. * @param func
  2579. * functor object who's operator() will be called when the async operation completes.
  2580. * You can subscribe multiple topics all at once.<BR>
  2581. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2582. */
  2583. void async_subscribe(
  2584. packet_id_t packet_id,
  2585. std::string topic_filter,
  2586. subscribe_options option,
  2587. v5::properties props,
  2588. async_handler_t func = {}
  2589. ) {
  2590. MQTT_LOG("mqtt_api", info)
  2591. << MQTT_ADD_VALUE(address, this)
  2592. << "async_subscribe"
  2593. << " pid:" << packet_id
  2594. << " topic:" << topic_filter
  2595. << " qos:" << option.get_qos()
  2596. << " rh:" << option.get_retain_handling()
  2597. << " nl:" << option.get_nl()
  2598. << " rap:" << option.get_rap();
  2599. auto sp_topic_filter = std::make_shared<std::string>(force_move(topic_filter));
  2600. auto topic_filter_buf = as::buffer(*sp_topic_filter);
  2601. async_send_subscribe(
  2602. std::vector<std::tuple<as::const_buffer, subscribe_options>>{ { topic_filter_buf, option } },
  2603. packet_id,
  2604. force_move(props),
  2605. [life_keeper = force_move(sp_topic_filter), func = force_move(func)]
  2606. (error_code ec) {
  2607. if(func) func(ec);
  2608. }
  2609. );
  2610. }
  2611. /**
  2612. * @brief Subscribe
  2613. * @param packet_id
  2614. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2615. * The ownership of the packet_id moves to the library.
  2616. * @param topic_filter
  2617. * A topic filter to subscribe
  2618. * @param option
  2619. * subscription options<BR>
  2620. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2621. * 3.8.3.1 Subscription Options
  2622. * @param func
  2623. * functor object who's operator() will be called when the async operation completes.
  2624. * This object should hold the lifetime of the buffers for topic_filter.
  2625. * You can subscribe multiple topics all at once.<BR>
  2626. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2627. */
  2628. void async_subscribe(
  2629. packet_id_t packet_id,
  2630. as::const_buffer topic_filter,
  2631. subscribe_options option,
  2632. async_handler_t func
  2633. ) {
  2634. MQTT_LOG("mqtt_api", info)
  2635. << MQTT_ADD_VALUE(address, this)
  2636. << "async_subscribe"
  2637. << " pid:" << packet_id
  2638. << " topic:" << string_view(get_pointer(topic_filter), get_size(topic_filter))
  2639. << " qos:" << option.get_qos()
  2640. << " rh:" << option.get_retain_handling()
  2641. << " nl:" << option.get_nl()
  2642. << " rap:" << option.get_rap();
  2643. async_send_subscribe(
  2644. std::vector<std::tuple<as::const_buffer, subscribe_options>>{ { topic_filter, option } },
  2645. packet_id,
  2646. v5::properties{},
  2647. force_move(func)
  2648. );
  2649. }
  2650. /**
  2651. * @brief Subscribe
  2652. * @param packet_id
  2653. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2654. * The ownership of the packet_id moves to the library.
  2655. * @param topic_filter
  2656. * A topic filter to subscribe
  2657. * @param option
  2658. * subscription options<BR>
  2659. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2660. * 3.8.3.1 Subscription Options
  2661. * @param props
  2662. * Properties<BR>
  2663. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  2664. * 3.8.2.1 SUBSCRIBE Properties
  2665. * @param func
  2666. * functor object who's operator() will be called when the async operation completes.
  2667. * This object should hold the lifetime of the buffers for topic_filter, and properties.
  2668. * You can subscribe multiple topics all at once.<BR>
  2669. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2670. */
  2671. void async_subscribe(
  2672. packet_id_t packet_id,
  2673. as::const_buffer topic_filter,
  2674. subscribe_options option,
  2675. v5::properties props,
  2676. async_handler_t func
  2677. ) {
  2678. MQTT_LOG("mqtt_api", info)
  2679. << MQTT_ADD_VALUE(address, this)
  2680. << "async_subscribe"
  2681. << " pid:" << packet_id
  2682. << " topic:" << string_view(get_pointer(topic_filter), get_size(topic_filter))
  2683. << " qos:" << option.get_qos()
  2684. << " rh:" << option.get_retain_handling()
  2685. << " nl:" << option.get_nl()
  2686. << " rap:" << option.get_rap();
  2687. async_send_subscribe(
  2688. std::vector<std::tuple<as::const_buffer, subscribe_options>>{ { topic_filter, option } },
  2689. packet_id,
  2690. force_move(props),
  2691. force_move(func)
  2692. );
  2693. }
  2694. /**
  2695. * @brief Subscribe
  2696. * @param packet_id
  2697. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2698. * The ownership of the packet_id moves to the library.
  2699. * @param topic_filter
  2700. * A topic filter to subscribe
  2701. * @param option
  2702. * subscription options<BR>
  2703. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2704. * 3.8.3.1 Subscription Options
  2705. * @param func
  2706. * functor object who's operator() will be called when the async operation completes.
  2707. * You can subscribe multiple topics all at once.<BR>
  2708. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2709. */
  2710. void async_subscribe(
  2711. packet_id_t packet_id,
  2712. buffer topic_filter,
  2713. subscribe_options option,
  2714. async_handler_t func = {}
  2715. ) {
  2716. MQTT_LOG("mqtt_api", info)
  2717. << MQTT_ADD_VALUE(address, this)
  2718. << "async_subscribe"
  2719. << " pid:" << packet_id
  2720. << " topic:" << topic_filter
  2721. << " qos:" << option.get_qos()
  2722. << " rh:" << option.get_retain_handling()
  2723. << " nl:" << option.get_nl()
  2724. << " rap:" << option.get_rap();
  2725. auto topic_filter_buf = as::buffer(topic_filter);
  2726. async_send_subscribe(
  2727. std::vector<std::tuple<as::const_buffer, subscribe_options>>{ { topic_filter_buf, option } },
  2728. packet_id,
  2729. v5::properties{},
  2730. [life_keeper = force_move(topic_filter), func = force_move(func)]
  2731. (error_code ec) {
  2732. if(func) func(ec);
  2733. }
  2734. );
  2735. }
  2736. /**
  2737. * @brief Subscribe
  2738. * @param packet_id
  2739. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2740. * The ownership of the packet_id moves to the library.
  2741. * @param topic_filter
  2742. * A topic filter to subscribe
  2743. * @param option
  2744. * subscription options<BR>
  2745. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2746. * 3.8.3.1 Subscription Options
  2747. * @param props
  2748. * Properties<BR>
  2749. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  2750. * 3.8.2.1 SUBSCRIBE Properties
  2751. * @param func
  2752. * functor object who's operator() will be called when the async operation completes.
  2753. * You can subscribe multiple topics all at once.<BR>
  2754. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2755. */
  2756. void async_subscribe(
  2757. packet_id_t packet_id,
  2758. buffer topic_filter,
  2759. subscribe_options option,
  2760. v5::properties props,
  2761. async_handler_t func = {}
  2762. ) {
  2763. MQTT_LOG("mqtt_api", info)
  2764. << MQTT_ADD_VALUE(address, this)
  2765. << "async_subscribe"
  2766. << " pid:" << packet_id
  2767. << " topic:" << topic_filter
  2768. << " qos:" << option.get_qos()
  2769. << " rh:" << option.get_retain_handling()
  2770. << " nl:" << option.get_nl()
  2771. << " rap:" << option.get_rap();
  2772. auto topic_filter_buf = as::buffer(topic_filter);
  2773. async_send_subscribe(
  2774. std::vector<std::tuple<as::const_buffer, subscribe_options>>{ { topic_filter_buf, option } },
  2775. packet_id,
  2776. force_move(props),
  2777. [life_keeper = force_move(topic_filter), func = force_move(func)]
  2778. (error_code ec) {
  2779. if(func) func(ec);
  2780. }
  2781. );
  2782. }
  2783. /**
  2784. * @brief Subscribe
  2785. * @param packet_id
  2786. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2787. * The ownership of the packet_id moves to the library.
  2788. * @param params
  2789. * A collection of the pair of topic_filter and option to subscribe.<BR>
  2790. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2791. * 3.8.3.1 Subscription Options
  2792. * @param func
  2793. * functor object who's operator() will be called when the async operation completes.
  2794. * You can subscribe multiple topics all at once.<BR>
  2795. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2796. */
  2797. void async_subscribe(
  2798. packet_id_t packet_id,
  2799. std::vector<std::tuple<std::string, subscribe_options>> params,
  2800. async_handler_t func = {}
  2801. ) {
  2802. MQTT_LOG("mqtt_api", info)
  2803. << MQTT_ADD_VALUE(address, this)
  2804. << "async_subscribe"
  2805. << " pid:" << packet_id;
  2806. std::vector<std::tuple<as::const_buffer, subscribe_options>> cb_params;
  2807. cb_params.reserve(params.size());
  2808. std::vector<std::shared_ptr<std::string>> life_keepers;
  2809. life_keepers.reserve(params.size());
  2810. for (auto&& e : params) {
  2811. auto sp_topic_filter = std::make_shared<std::string>(force_move(std::get<0>(e)));
  2812. cb_params.emplace_back(as::buffer(*sp_topic_filter), std::get<1>(e));
  2813. life_keepers.emplace_back(force_move(sp_topic_filter));
  2814. }
  2815. async_send_subscribe(
  2816. force_move(cb_params),
  2817. packet_id,
  2818. v5::properties{},
  2819. [life_keeper = force_move(life_keepers), func = force_move(func)]
  2820. (error_code ec) {
  2821. if(func) func(ec);
  2822. }
  2823. );
  2824. }
  2825. /**
  2826. * @brief Subscribe
  2827. * @param packet_id
  2828. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2829. * The ownership of the packet_id moves to the library.
  2830. * @param params
  2831. * A collection of the pair of topic_filter and option to subscribe.<BR>
  2832. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2833. * 3.8.3.1 Subscription Options
  2834. * @param props
  2835. * Properties<BR>
  2836. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901164<BR>
  2837. * 3.8.2.1 SUBSCRIBE Properties
  2838. * @param func
  2839. * functor object who's operator() will be called when the async operation completes.
  2840. * You can subscribe multiple topics all at once.<BR>
  2841. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2842. */
  2843. void async_subscribe(
  2844. packet_id_t packet_id,
  2845. std::vector<std::tuple<std::string, subscribe_options>> params,
  2846. v5::properties props,
  2847. async_handler_t func = {}
  2848. ) {
  2849. MQTT_LOG("mqtt_api", info)
  2850. << MQTT_ADD_VALUE(address, this)
  2851. << "async_subscribe"
  2852. << " pid:" << packet_id;
  2853. std::vector<std::tuple<as::const_buffer, subscribe_options>> cb_params;
  2854. cb_params.reserve(params.size());
  2855. std::vector<std::shared_ptr<std::string>> life_keepers;
  2856. life_keepers.reserve(params.size());
  2857. for (auto&& e : params) {
  2858. auto sp_topic_filter = std::make_shared<std::string>(force_move(std::get<0>(e)));
  2859. cb_params.emplace_back(as::buffer(*sp_topic_filter), std::get<1>(e));
  2860. life_keepers.emplace_back(force_move(sp_topic_filter));
  2861. }
  2862. async_send_subscribe(
  2863. force_move(cb_params),
  2864. packet_id,
  2865. force_move(props),
  2866. [life_keeper = force_move(life_keepers), func = force_move(func)]
  2867. (error_code ec) {
  2868. if(func) func(ec);
  2869. }
  2870. );
  2871. }
  2872. /**
  2873. * @brief Subscribe
  2874. * @param packet_id
  2875. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2876. * The ownership of the packet_id moves to the library.
  2877. * @param params A collection of the pair of topic_filter and qos to subscribe.
  2878. * @param func
  2879. * functor object who's operator() will be called when the async operation completes.
  2880. * This object should hold the lifetime of the buffers for params.
  2881. * You can subscribe multiple topics all at once.<BR>
  2882. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2883. */
  2884. void async_subscribe(
  2885. packet_id_t packet_id,
  2886. std::vector<std::tuple<as::const_buffer, subscribe_options>> params,
  2887. async_handler_t func
  2888. ) {
  2889. MQTT_LOG("mqtt_api", info)
  2890. << MQTT_ADD_VALUE(address, this)
  2891. << "async_subscribe"
  2892. << " pid:" << packet_id;
  2893. async_send_subscribe(
  2894. force_move(params),
  2895. packet_id,
  2896. v5::properties{},
  2897. force_move(func)
  2898. );
  2899. }
  2900. /**
  2901. * @brief Subscribe
  2902. * @param packet_id
  2903. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2904. * The ownership of the packet_id moves to the library.
  2905. * @param params
  2906. * A collection of the pair of topic_filter and option to subscribe.<BR>
  2907. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2908. * 3.8.3.1 Subscription Options
  2909. * @param func
  2910. * functor object who's operator() will be called when the async operation completes.
  2911. * This object should hold the lifetime of the buffers for params.
  2912. * You can subscribe multiple topics all at once.<BR>
  2913. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2914. */
  2915. void async_subscribe(
  2916. packet_id_t packet_id,
  2917. std::vector<std::tuple<as::const_buffer, subscribe_options>> params,
  2918. v5::properties props,
  2919. async_handler_t func
  2920. ) {
  2921. MQTT_LOG("mqtt_api", info)
  2922. << MQTT_ADD_VALUE(address, this)
  2923. << "async_subscribe"
  2924. << " pid:" << packet_id;
  2925. async_send_subscribe(
  2926. force_move(params),
  2927. packet_id,
  2928. force_move(props),
  2929. force_move(func)
  2930. );
  2931. }
  2932. /**
  2933. * @brief Subscribe
  2934. * @param packet_id
  2935. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2936. * The ownership of the packet_id moves to the library.
  2937. * @param params A collection of the pair of topic_filter and qos to subscribe.
  2938. * @param func
  2939. * functor object who's operator() will be called when the async operation completes.
  2940. * You can subscribe multiple topics all at once.<BR>
  2941. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2942. */
  2943. void async_subscribe(
  2944. packet_id_t packet_id,
  2945. std::vector<std::tuple<buffer, subscribe_options>> params,
  2946. async_handler_t func = {}
  2947. ) {
  2948. MQTT_LOG("mqtt_api", info)
  2949. << MQTT_ADD_VALUE(address, this)
  2950. << "async_subscribe"
  2951. << " pid:" << packet_id;
  2952. std::vector<std::tuple<as::const_buffer, subscribe_options>> cb_params;
  2953. cb_params.reserve(params.size());
  2954. for (auto&& e : params) {
  2955. cb_params.emplace_back(
  2956. as::buffer(std::get<0>(e)),
  2957. std::get<1>(e)
  2958. );
  2959. }
  2960. async_send_subscribe(
  2961. force_move(cb_params),
  2962. packet_id,
  2963. v5::properties{},
  2964. [life_keeper = force_move(params), func = force_move(func)]
  2965. (error_code ec) {
  2966. if(func) func(ec);
  2967. }
  2968. );
  2969. }
  2970. /**
  2971. * @brief Subscribe
  2972. * @param packet_id
  2973. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  2974. * The ownership of the packet_id moves to the library.
  2975. * @param params
  2976. * A collection of the pair of topic_filter and option to subscribe.<BR>
  2977. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169<BR>
  2978. * 3.8.3.1 Subscription Options
  2979. * @param func
  2980. * functor object who's operator() will be called when the async operation completes.
  2981. * You can subscribe multiple topics all at once.<BR>
  2982. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  2983. */
  2984. void async_subscribe(
  2985. packet_id_t packet_id,
  2986. std::vector<std::tuple<buffer, subscribe_options>> params,
  2987. v5::properties props,
  2988. async_handler_t func = {}
  2989. ) {
  2990. MQTT_LOG("mqtt_api", info)
  2991. << MQTT_ADD_VALUE(address, this)
  2992. << "async_subscribe"
  2993. << " pid:" << packet_id;
  2994. std::vector<std::tuple<as::const_buffer, subscribe_options>> cb_params;
  2995. cb_params.reserve(params.size());
  2996. for (auto&& e : params) {
  2997. cb_params.emplace_back(
  2998. as::buffer(std::get<0>(e)),
  2999. std::get<1>(e)
  3000. );
  3001. }
  3002. async_send_subscribe(
  3003. force_move(cb_params),
  3004. packet_id,
  3005. force_move(props),
  3006. [life_keeper = force_move(params), func = force_move(func)]
  3007. (error_code ec) {
  3008. if(func) func(ec);
  3009. }
  3010. );
  3011. }
  3012. /**
  3013. * @brief Unsubscribe
  3014. * @param packet_id
  3015. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3016. * The ownership of the packet_id moves to the library.
  3017. * @param topic_filter topic_filter
  3018. * @param func
  3019. * functor object who's operator() will be called when the async operation completes.
  3020. * You can subscribe multiple topics all at once.<BR>
  3021. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  3022. */
  3023. void async_unsubscribe(
  3024. packet_id_t packet_id,
  3025. std::string topic_filter,
  3026. async_handler_t func = {}
  3027. ) {
  3028. MQTT_LOG("mqtt_api", info)
  3029. << MQTT_ADD_VALUE(address, this)
  3030. << "async_unsubscribe"
  3031. << " pid:" << packet_id
  3032. << " topic:" << topic_filter;
  3033. auto sp_topic_filter = std::make_shared<std::string>(force_move(topic_filter));
  3034. auto topic_filter_buf = as::buffer(*sp_topic_filter);
  3035. async_send_unsubscribe(
  3036. std::vector<as::const_buffer>{ topic_filter_buf },
  3037. packet_id,
  3038. v5::properties{},
  3039. [life_keeper = force_move(sp_topic_filter), func = force_move(func)]
  3040. (error_code ec) {
  3041. if(func) func(ec);
  3042. }
  3043. );
  3044. }
  3045. /**
  3046. * @brief Unsubscribe
  3047. * @param packet_id
  3048. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3049. * The ownership of the packet_id moves to the library.
  3050. * @param topic_filter topic_filter
  3051. * @param func
  3052. * functor object who's operator() will be called when the async operation completes.
  3053. * This object should hold the lifetime of the buffer for topic_filter.
  3054. * You can subscribe multiple topics all at once.<BR>
  3055. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  3056. */
  3057. void async_unsubscribe(
  3058. packet_id_t packet_id,
  3059. as::const_buffer topic_filter,
  3060. async_handler_t func
  3061. ) {
  3062. MQTT_LOG("mqtt_api", info)
  3063. << MQTT_ADD_VALUE(address, this)
  3064. << "async_unsubscribe"
  3065. << " pid:" << packet_id
  3066. << " topic:" << string_view(get_pointer(topic_filter), get_size(topic_filter));
  3067. async_send_unsubscribe(std::vector<as::const_buffer>{ topic_filter }, packet_id, v5::properties{}, force_move(func));
  3068. }
  3069. /**
  3070. * @brief Unsubscribe
  3071. * @param packet_id
  3072. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3073. * The ownership of the packet_id moves to the library.
  3074. * @param topic_filter topic_filter
  3075. * @param func
  3076. * functor object who's operator() will be called when the async operation completes.
  3077. * You can subscribe multiple topics all at once.<BR>
  3078. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  3079. */
  3080. void async_unsubscribe(
  3081. packet_id_t packet_id,
  3082. buffer topic_filter,
  3083. async_handler_t func = {}
  3084. ) {
  3085. MQTT_LOG("mqtt_api", info)
  3086. << MQTT_ADD_VALUE(address, this)
  3087. << "async_unsubscribe"
  3088. << " pid:" << packet_id
  3089. << " topic:" << topic_filter;
  3090. auto topic_filter_buf = as::buffer(topic_filter);
  3091. async_send_unsubscribe(std::vector<as::const_buffer>{ topic_filter_buf },
  3092. packet_id,
  3093. v5::properties{},
  3094. [life_keeper = force_move(topic_filter), func = force_move(func)]
  3095. (error_code ec) {
  3096. if(func) func(ec);
  3097. });
  3098. }
  3099. /**
  3100. * @brief Unsubscribe
  3101. * @param packet_id
  3102. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3103. * The ownership of the packet_id moves to the library.
  3104. * @param topic_filter topic_filter
  3105. * @param props
  3106. * Properties<BR>
  3107. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  3108. * 3.10.2.1 UNSUBSCRIBE Properties
  3109. * @param func
  3110. * functor object who's operator() will be called when the async operation completes.
  3111. * You can subscribe multiple topics all at once.<BR>
  3112. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
  3113. */
  3114. void async_unsubscribe(
  3115. packet_id_t packet_id,
  3116. buffer topic_filter,
  3117. v5::properties props,
  3118. async_handler_t func = {}
  3119. ) {
  3120. MQTT_LOG("mqtt_api", info)
  3121. << MQTT_ADD_VALUE(address, this)
  3122. << "async_unsubscribe"
  3123. << " pid:" << packet_id
  3124. << " topic:" << topic_filter;
  3125. auto topic_filter_buf = as::buffer(topic_filter);
  3126. async_send_unsubscribe(std::vector<as::const_buffer>{ topic_filter_buf },
  3127. packet_id,
  3128. force_move(props),
  3129. [life_keeper = force_move(topic_filter), func = force_move(func)]
  3130. (error_code ec) {
  3131. if(func) func(ec);
  3132. });
  3133. }
  3134. /**
  3135. * @brief Unsubscribe
  3136. * @param packet_id
  3137. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3138. * The ownership of the packet_id moves to the library.
  3139. * @param params
  3140. * A collection of the topic filter to unsubscribe
  3141. * @param func
  3142. * functor object who's operator() will be called when the async operation completes.
  3143. * You can subscribe multiple topics all at once.<BR>
  3144. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  3145. */
  3146. void async_unsubscribe(
  3147. packet_id_t packet_id,
  3148. std::vector<std::string> params,
  3149. async_handler_t func = {}
  3150. ) {
  3151. MQTT_LOG("mqtt_api", info)
  3152. << MQTT_ADD_VALUE(address, this)
  3153. << "async_unsubscribe"
  3154. << " pid:" << packet_id;
  3155. std::vector<as::const_buffer> cb_params;
  3156. cb_params.reserve(params.size());
  3157. std::vector<std::shared_ptr<std::string>> life_keepers;
  3158. life_keepers.reserve(params.size());
  3159. for (auto&& e : params) {
  3160. life_keepers.emplace_back(std::make_shared<std::string>(force_move(e)));
  3161. cb_params.emplace_back(as::buffer(*life_keepers.back()));
  3162. }
  3163. async_send_unsubscribe(
  3164. force_move(cb_params),
  3165. packet_id,
  3166. v5::properties{},
  3167. [life_keeper = force_move(life_keepers), func = force_move(func)]
  3168. (error_code ec) {
  3169. if(func) func(ec);
  3170. }
  3171. );
  3172. }
  3173. /**
  3174. * @brief Unsubscribe
  3175. * @param packet_id
  3176. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3177. * The ownership of the packet_id moves to the library.
  3178. * @param params
  3179. * A collection of the topic filter to unsubscribe
  3180. * @param props
  3181. * Properties<BR>
  3182. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  3183. * 3.10.2.1 UNSUBSCRIBE Properties
  3184. * @param func
  3185. * functor object who's operator() will be called when the async operation completes.
  3186. * You can subscribe multiple topics all at once.<BR>
  3187. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  3188. */
  3189. void async_unsubscribe(
  3190. packet_id_t packet_id,
  3191. std::vector<std::string> params,
  3192. v5::properties props,
  3193. async_handler_t func = {}
  3194. ) {
  3195. MQTT_LOG("mqtt_api", info)
  3196. << MQTT_ADD_VALUE(address, this)
  3197. << "async_unsubscribe"
  3198. << " pid:" << packet_id;
  3199. std::vector<as::const_buffer> cb_params;
  3200. cb_params.reserve(params.size());
  3201. // TOOD: Theoretically, std::vector's storage remains stationary
  3202. // as long as it's never copied...
  3203. // Perhaps a wrapper that disables copies, and forces move only?
  3204. // that would allow us to avoid the std::shared_ptr<std::string> vector.
  3205. // TODO: Does vector do short-buffer-optimization? If so, this is an invalid idea.
  3206. std::vector<std::shared_ptr<std::string>> life_keepers;
  3207. life_keepers.reserve(params.size());
  3208. for (auto&& e : params) {
  3209. life_keepers.emplace_back(std::make_shared<std::string>(force_move(e)));
  3210. cb_params.emplace_back(as::buffer(*life_keepers.back()));
  3211. }
  3212. async_send_unsubscribe(
  3213. force_move(cb_params),
  3214. packet_id,
  3215. force_move(props),
  3216. [life_keeper = force_move(life_keepers), func = force_move(func)]
  3217. (error_code ec) {
  3218. if(func) func(ec);
  3219. }
  3220. );
  3221. }
  3222. /**
  3223. * @brief Unsubscribe
  3224. * @param packet_id
  3225. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3226. * The ownership of the packet_id moves to the library.
  3227. * @param params
  3228. * A collection of the topic filter to unsubscribe
  3229. * @param func
  3230. * functor object who's operator() will be called when the async operation completes.
  3231. * This object may hold the lifetime of the buffers for topic_filter and contents.
  3232. * You can subscribe multiple topics all at once.<BR>
  3233. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  3234. */
  3235. void async_unsubscribe(
  3236. packet_id_t packet_id,
  3237. std::vector<as::const_buffer> params,
  3238. async_handler_t func
  3239. ) {
  3240. MQTT_LOG("mqtt_api", info)
  3241. << MQTT_ADD_VALUE(address, this)
  3242. << "async_unsubscribe"
  3243. << " pid:" << packet_id;
  3244. async_send_unsubscribe(
  3245. force_move(params),
  3246. packet_id,
  3247. v5::properties{},
  3248. force_move(func)
  3249. );
  3250. }
  3251. /**
  3252. * @brief Unsubscribe
  3253. * @param packet_id
  3254. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3255. * The ownership of the packet_id moves to the library.
  3256. * @param params
  3257. * A collection of the topic filter to unsubscribe
  3258. * @param props
  3259. * Properties<BR>
  3260. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  3261. * 3.10.2.1 UNSUBSCRIBE Properties
  3262. * @param func
  3263. * functor object who's operator() will be called when the async operation completes.
  3264. * This object should hold the lifetime of the buffers for params.
  3265. * You can subscribe multiple topics all at once.<BR>
  3266. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  3267. */
  3268. void async_unsubscribe(
  3269. packet_id_t packet_id,
  3270. std::vector<as::const_buffer> params,
  3271. v5::properties props,
  3272. async_handler_t func
  3273. ) {
  3274. MQTT_LOG("mqtt_api", info)
  3275. << MQTT_ADD_VALUE(address, this)
  3276. << "async_unsubscribe"
  3277. << " pid:" << packet_id;
  3278. async_send_unsubscribe(
  3279. force_move(params),
  3280. packet_id,
  3281. force_move(props),
  3282. force_move(func)
  3283. );
  3284. }
  3285. /**
  3286. * @brief Unsubscribe
  3287. * @param packet_id
  3288. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3289. * The ownership of the packet_id moves to the library.
  3290. * @param params
  3291. * A collection of the topic filter to unsubscribe
  3292. * @param func
  3293. * functor object who's operator() will be called when the async operation completes.
  3294. * You can subscribe multiple topics all at once.<BR>
  3295. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  3296. */
  3297. void async_unsubscribe(
  3298. packet_id_t packet_id,
  3299. std::vector<buffer> params,
  3300. async_handler_t func = {}
  3301. ) {
  3302. MQTT_LOG("mqtt_api", info)
  3303. << MQTT_ADD_VALUE(address, this)
  3304. << "async_unsubscribe"
  3305. << " pid:" << packet_id;
  3306. std::vector<as::const_buffer> cb_params;
  3307. cb_params.reserve(params.size());
  3308. for (auto const& buf : params) {
  3309. cb_params.emplace_back(as::buffer(buf));
  3310. }
  3311. async_send_unsubscribe(
  3312. force_move(cb_params),
  3313. packet_id,
  3314. v5::properties{},
  3315. [life_keeper = force_move(params), func = force_move(func)]
  3316. (error_code ec) {
  3317. if(func) func(ec);
  3318. }
  3319. );
  3320. }
  3321. /**
  3322. * @brief Unsubscribe
  3323. * @param packet_id
  3324. * packet identifier. It should be acquired by acquire_unique_packet_id, or register_packet_id.
  3325. * The ownership of the packet_id moves to the library.
  3326. * @param params
  3327. * A collection of the topic filter to unsubscribe
  3328. * @param props
  3329. * Properties<BR>
  3330. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901182<BR>
  3331. * 3.10.2.1 UNSUBSCRIBE Properties
  3332. * @param func
  3333. * functor object who's operator() will be called when the async operation completes.
  3334. * You can subscribe multiple topics all at once.<BR>
  3335. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
  3336. */
  3337. void async_unsubscribe(
  3338. packet_id_t packet_id,
  3339. std::vector<buffer> params,
  3340. v5::properties props,
  3341. async_handler_t func = {}
  3342. ) {
  3343. MQTT_LOG("mqtt_api", info)
  3344. << MQTT_ADD_VALUE(address, this)
  3345. << "async_unsubscribe"
  3346. << " pid:" << packet_id;
  3347. std::vector<as::const_buffer> cb_params;
  3348. cb_params.reserve(params.size());
  3349. for (auto const& buf : params) {
  3350. cb_params.emplace_back(as::buffer(buf));
  3351. }
  3352. async_send_unsubscribe(
  3353. force_move(cb_params),
  3354. packet_id,
  3355. force_move(props),
  3356. [life_keeper = force_move(params), func = force_move(func)]
  3357. (error_code ec) {
  3358. if(func) func(ec);
  3359. }
  3360. );
  3361. }
  3362. /**
  3363. * @brief Send pingreq packet.
  3364. * @param func
  3365. * functor object who's operator() will be called when the async operation completes.
  3366. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901195
  3367. */
  3368. void async_pingreq(async_handler_t func = {}) {
  3369. MQTT_LOG("mqtt_api", trace)
  3370. << MQTT_ADD_VALUE(address, this)
  3371. << "async_pingreq";
  3372. if (connected_ && mqtt_connected_) async_send_pingreq(force_move(func));
  3373. }
  3374. /**
  3375. * @brief Send pingresp packet. This function is for broker.
  3376. * @param func
  3377. * functor object who's operator() will be called when the async operation completes.
  3378. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901200
  3379. */
  3380. void async_pingresp(async_handler_t func = {}) {
  3381. MQTT_LOG("mqtt_api", trace)
  3382. << MQTT_ADD_VALUE(address, this)
  3383. << "async_pingrsp";
  3384. async_send_pingresp(force_move(func));
  3385. }
  3386. /**
  3387. * @brief Send auth packet.
  3388. * @param reason_code
  3389. * AUTH Reason Code<BR>
  3390. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901220<BR>
  3391. * 3.15.2.1 Authenticate Reason Code
  3392. * @param props
  3393. * Properties<BR>
  3394. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901221<BR>
  3395. * 3.15.2.2 AUTH Properties
  3396. * @param func
  3397. * functor object who's operator() will be called when the async operation completes.
  3398. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718086
  3399. */
  3400. void async_auth(
  3401. v5::auth_reason_code reason_code = v5::auth_reason_code::success,
  3402. v5::properties props = {},
  3403. async_handler_t func = {}
  3404. ) {
  3405. MQTT_LOG("mqtt_api", info)
  3406. << MQTT_ADD_VALUE(address, this)
  3407. << "async_auth"
  3408. << " reason:" << reason_code;
  3409. async_send_auth(reason_code, force_move(props), force_move(func));
  3410. }
  3411. /**
  3412. * @brief Send connect packet.
  3413. * @param client_id
  3414. * The client id to use for this connection<BR>
  3415. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059<BR>
  3416. * 3.1.3.1 Client Identifier (ClientID)
  3417. * @param user_name
  3418. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901071<BR>
  3419. * 3.1.3.5 User Name
  3420. * @param password
  3421. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901072<BR>
  3422. * 3.1.3.6 Password
  3423. * @param w
  3424. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc479576982<BR>
  3425. * 3.1.2.5 Will Flag
  3426. * @param keep_alive_sec
  3427. * Keep Alive<BR>
  3428. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901045<BR>
  3429. * 3.1.2.10 Keep Alive
  3430. * @param func
  3431. * functor object who's operator() will be called when the async operation completes.
  3432. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718028
  3433. */
  3434. void async_connect(
  3435. buffer client_id,
  3436. optional<buffer> user_name,
  3437. optional<buffer> password,
  3438. optional<will> w,
  3439. std::uint16_t keep_alive_sec,
  3440. async_handler_t func = {}
  3441. ) {
  3442. async_connect(
  3443. force_move(client_id),
  3444. force_move(user_name),
  3445. force_move(password),
  3446. force_move(w),
  3447. keep_alive_sec,
  3448. v5::properties{},
  3449. force_move(func));
  3450. }
  3451. /**
  3452. * @brief Send connect packet.
  3453. * @param client_id
  3454. * The client id to use for this connection<BR>
  3455. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059<BR>
  3456. * 3.1.3.1 Client Identifier (ClientID)
  3457. * @param user_name
  3458. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901071<BR>
  3459. * 3.1.3.5 User Name
  3460. * @param password
  3461. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901072<BR>
  3462. * 3.1.3.6 Password
  3463. * @param w
  3464. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc479576982<BR>
  3465. * 3.1.2.5 Will Flag
  3466. * @param keep_alive_sec
  3467. * Keep Alive<BR>
  3468. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901045<BR>
  3469. * 3.1.2.10 Keep Alive
  3470. * @param props
  3471. * Properties<BR>
  3472. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901046<BR>
  3473. * 3.1.2.11 CONNECT Properties
  3474. * @param func
  3475. * functor object who's operator() will be called when the async operation completes.
  3476. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718028
  3477. */
  3478. void async_connect(
  3479. buffer client_id,
  3480. optional<buffer> user_name,
  3481. optional<buffer> password,
  3482. optional<will> w,
  3483. std::uint16_t keep_alive_sec,
  3484. v5::properties props,
  3485. async_handler_t func = {}
  3486. ) {
  3487. MQTT_LOG("mqtt_api", info)
  3488. << MQTT_ADD_VALUE(address, this)
  3489. << "async_connect"
  3490. << " client_id:" << client_id
  3491. << " user_name:" << (user_name ? string_view(user_name.value()) : string_view("none"))
  3492. << " keep_alive:" << std::dec << keep_alive_sec;
  3493. connect_requested_ = true;
  3494. async_send_connect(
  3495. force_move(client_id),
  3496. force_move(user_name),
  3497. force_move(password),
  3498. force_move(w),
  3499. keep_alive_sec,
  3500. force_move(props),
  3501. force_move(func));
  3502. }
  3503. /**
  3504. * @brief Send connack packet. This function is for broker.
  3505. * @param session_present See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349255
  3506. * @param return_code See connect_return_code.hpp and https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349256
  3507. * @param func
  3508. * functor object who's operator() will be called when the async operation completes.
  3509. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718033
  3510. */
  3511. void async_connack(
  3512. bool session_present,
  3513. variant<connect_return_code, v5::connect_reason_code> reason_code,
  3514. async_handler_t func = {}
  3515. ) {
  3516. MQTT_LOG("mqtt_api", info)
  3517. << MQTT_ADD_VALUE(address, this)
  3518. << "async_connack"
  3519. << " session_present:" << std::boolalpha << session_present
  3520. << " reason:" << reason_code;
  3521. async_send_connack(session_present, force_move(reason_code), v5::properties{}, force_move(func));
  3522. }
  3523. /**
  3524. * @brief Send connack packet. This function is for broker.
  3525. * @param session_present See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349255
  3526. * @param return_code See connect_return_code.hpp and https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc385349256
  3527. * @param props
  3528. * Properties<BR>
  3529. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901080<BR>
  3530. * 3.2.2.3 CONNACK Properties
  3531. * @param func
  3532. * functor object who's operator() will be called when the async operation completes.
  3533. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718033
  3534. */
  3535. void async_connack(
  3536. bool session_present,
  3537. variant<connect_return_code, v5::connect_reason_code> reason_code,
  3538. v5::properties props,
  3539. async_handler_t func = {}
  3540. ) {
  3541. MQTT_LOG("mqtt_api", info)
  3542. << MQTT_ADD_VALUE(address, this)
  3543. << "async_connack"
  3544. << " session_present:" << std::boolalpha << session_present
  3545. << " reason:" << reason_code;
  3546. async_send_connack(session_present, force_move(reason_code), force_move(props), force_move(func));
  3547. }
  3548. /**
  3549. * @brief Send puback packet.
  3550. * @param packet_id packet id corresponding to publish
  3551. * @param func
  3552. * functor object who's operator() will be called when the async operation completes.
  3553. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3554. */
  3555. void async_puback(
  3556. packet_id_t packet_id,
  3557. async_handler_t func = {}
  3558. ) {
  3559. MQTT_LOG("mqtt_api", trace)
  3560. << MQTT_ADD_VALUE(address, this)
  3561. << "async_puback"
  3562. << " pid:" << packet_id;
  3563. async_send_puback(packet_id, v5::puback_reason_code::success, v5::properties{}, force_move(func));
  3564. }
  3565. /**
  3566. * @brief Send puback packet.
  3567. * @param packet_id packet id corresponding to publish
  3568. * @param reason_code
  3569. * PUBACK Reason Code<BR>
  3570. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124<BR>
  3571. * 3.4.2.1 PUBACK Reason Code
  3572. * @param props
  3573. * Properties<BR>
  3574. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901125<BR>
  3575. * 3.4.2.2 PUBACK Properties
  3576. * @param func
  3577. * functor object who's operator() will be called when the async operation completes.
  3578. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3579. */
  3580. void async_puback(
  3581. packet_id_t packet_id,
  3582. v5::puback_reason_code reason_code,
  3583. v5::properties props,
  3584. async_handler_t func = {}
  3585. ) {
  3586. MQTT_LOG("mqtt_api", trace)
  3587. << MQTT_ADD_VALUE(address, this)
  3588. << "async_puback"
  3589. << " pid:" << packet_id
  3590. << " reason:" << reason_code;
  3591. async_send_puback(packet_id, reason_code, force_move(props), force_move(func));
  3592. }
  3593. /**
  3594. * @brief Send pubrec packet.
  3595. * @param packet_id packet id corresponding to publish
  3596. * @param func
  3597. * functor object who's operator() will be called when the async operation completes.
  3598. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3599. */
  3600. void async_pubrec(
  3601. packet_id_t packet_id,
  3602. async_handler_t func = {}
  3603. ) {
  3604. MQTT_LOG("mqtt_api", trace)
  3605. << MQTT_ADD_VALUE(address, this)
  3606. << "async_pubrec"
  3607. << " pid:" << packet_id;
  3608. async_send_pubrec(packet_id, v5::pubrec_reason_code::success, v5::properties{}, force_move(func));
  3609. }
  3610. /**
  3611. * @brief Send pubrec packet.
  3612. * @param packet_id packet id corresponding to publish
  3613. * @param reason_code
  3614. * PUBREC Reason Code<BR>
  3615. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901134<BR>
  3616. * 3.5.2.1 PUBREC Reason Code
  3617. * @param props
  3618. * Properties<BR>
  3619. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901135<BR>
  3620. * 3.5.2.2 PUBREC Properties
  3621. * @param func
  3622. * functor object who's operator() will be called when the async operation completes.
  3623. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3624. */
  3625. void async_pubrec(
  3626. packet_id_t packet_id,
  3627. v5::pubrec_reason_code reason_code,
  3628. v5::properties props,
  3629. async_handler_t func = {}
  3630. ) {
  3631. MQTT_LOG("mqtt_api", trace)
  3632. << MQTT_ADD_VALUE(address, this)
  3633. << "async_pubrec"
  3634. << " pid:" << packet_id
  3635. << " reason:" << reason_code;
  3636. async_send_pubrec(packet_id, reason_code, force_move(props), force_move(func));
  3637. }
  3638. /**
  3639. * @brief Send pubrel packet.
  3640. * @param packet_id packet id corresponding to publish
  3641. * @param func
  3642. * functor object who's operator() will be called when the async operation completes.
  3643. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3644. */
  3645. void async_pubrel(
  3646. packet_id_t packet_id,
  3647. async_handler_t func = {}
  3648. ) {
  3649. MQTT_LOG("mqtt_api", trace)
  3650. << MQTT_ADD_VALUE(address, this)
  3651. << "async_pubrel"
  3652. << " pid:" << packet_id;
  3653. async_send_pubrel(packet_id, v5::pubrel_reason_code::success, v5::properties{}, any(), force_move(func));
  3654. }
  3655. /**
  3656. * @brief Send pubrel packet.
  3657. * @param packet_id packet id corresponding to publish
  3658. * @param reason_code
  3659. * PUBREL Reason Code<BR>
  3660. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144<BR>
  3661. * 3.6.2.1 PUBREL Reason Code
  3662. * @param props
  3663. * Properties<BR>
  3664. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901145<BR>
  3665. * 3.6.2.2 PUBREL Properties
  3666. * @param func
  3667. * functor object who's operator() will be called when the async operation completes.
  3668. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3669. *
  3670. * @note The library may store this message while it communicates with the server for several round trips.
  3671. * As such, the life_keeper paramter is important.
  3672. */
  3673. template <typename Func>
  3674. std::enable_if_t<
  3675. std::is_convertible<Func, async_handler_t>::value
  3676. >
  3677. async_pubrel(
  3678. packet_id_t packet_id,
  3679. v5::pubrel_reason_code reason_code,
  3680. v5::properties props = {},
  3681. Func&& func = {}
  3682. ) {
  3683. MQTT_LOG("mqtt_api", trace)
  3684. << MQTT_ADD_VALUE(address, this)
  3685. << "async_pubrel"
  3686. << " pid:" << packet_id
  3687. << " reason:" << reason_code;
  3688. async_send_pubrel(packet_id, reason_code, force_move(props), any(), std::forward<Func>(func));
  3689. }
  3690. /**
  3691. * @brief Send pubrel packet.
  3692. * @param packet_id packet id corresponding to publish
  3693. * @param reason_code
  3694. * PUBREL Reason Code<BR>
  3695. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144<BR>
  3696. * 3.6.2.1 PUBREL Reason Code
  3697. * @param props
  3698. * Properties<BR>
  3699. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901145<BR>
  3700. * 3.6.2.2 PUBREL Properties
  3701. * @param func
  3702. * functor object who's operator() will be called when the async operation completes.
  3703. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3704. *
  3705. * @param life_keeper
  3706. * An object that stays alive as long as the library holds a reference to any other parameters.
  3707. * If topic_name, contents, or props do not have built-in lifetime management, (e.g. buffer)
  3708. * use this parameter to manage their lifetime.
  3709. *
  3710. * @note The library may store this message while it communicates with the server for several round trips.
  3711. * As such, the life_keeper paramter is important.
  3712. */
  3713. void async_pubrel(
  3714. packet_id_t packet_id,
  3715. v5::pubrel_reason_code reason_code,
  3716. v5::properties props = {},
  3717. any life_keeper = {},
  3718. async_handler_t func = {}
  3719. ) {
  3720. MQTT_LOG("mqtt_api", trace)
  3721. << MQTT_ADD_VALUE(address, this)
  3722. << "async_pubrel"
  3723. << " pid:" << packet_id
  3724. << " reason:" << reason_code;
  3725. async_send_pubrel(packet_id, reason_code, force_move(props), force_move(life_keeper), force_move(func));
  3726. }
  3727. /**
  3728. * @brief Send pubcomp packet.
  3729. * @param packet_id packet id corresponding to publish
  3730. * @param func
  3731. * functor object who's operator() will be called when the async operation completes.
  3732. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3733. */
  3734. void async_pubcomp(
  3735. packet_id_t packet_id,
  3736. async_handler_t func = {}
  3737. ) {
  3738. MQTT_LOG("mqtt_api", trace)
  3739. << MQTT_ADD_VALUE(address, this)
  3740. << "async_pubcomp"
  3741. << " pid:" << packet_id;
  3742. async_send_pubcomp(packet_id, v5::pubcomp_reason_code::success, v5::properties{}, force_move(func));
  3743. }
  3744. /**
  3745. * @brief Send pubcomp packet.
  3746. * @param packet_id packet id corresponding to publish
  3747. * @param reason_code
  3748. * PUBCOMP Reason Code<BR>
  3749. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154<BR>
  3750. * 3.7.2.1 PUBCOMP Reason Code
  3751. * @param props
  3752. * Properties<BR>
  3753. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901155<BR>
  3754. * 3.7.2.2 PUBCOMP Properties
  3755. * @param func
  3756. * functor object who's operator() will be called when the async operation completes.
  3757. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718043
  3758. */
  3759. void async_pubcomp(
  3760. packet_id_t packet_id,
  3761. v5::pubcomp_reason_code reason_code,
  3762. v5::properties props,
  3763. async_handler_t func = {}
  3764. ) {
  3765. MQTT_LOG("mqtt_api", trace)
  3766. << MQTT_ADD_VALUE(address, this)
  3767. << "async_pubcomp"
  3768. << " pid:" << packet_id
  3769. << " reason:" << reason_code;
  3770. async_send_pubcomp(packet_id, reason_code, force_move(props), force_move(func));
  3771. }
  3772. /**
  3773. * @brief Send suback packet. This function is for broker.
  3774. * @param packet_id packet id corresponding to subscribe
  3775. * @param reason
  3776. * reason_code<BR>
  3777. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178<BR>
  3778. * 3.9.3 SUBACK Payload
  3779. * @param func
  3780. * functor object who's operator() will be called when the async operation completes.
  3781. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3782. */
  3783. void async_suback(
  3784. packet_id_t packet_id,
  3785. variant<suback_return_code, v5::suback_reason_code> reason,
  3786. async_handler_t func = {}
  3787. ) {
  3788. MQTT_LOG("mqtt_api", info)
  3789. << MQTT_ADD_VALUE(address, this)
  3790. << "async_suback"
  3791. << " pid:" << packet_id
  3792. << " reason:" < reason;
  3793. if (variant_idx(reason) == 0) {
  3794. async_send_suback(std::vector<suback_return_code>{ variant_get<suback_return_code>(reason) }, packet_id, v5::properties{}, force_move(func));
  3795. }
  3796. else {
  3797. async_send_suback(std::vector<v5::suback_reason_code>{ variant_get<v5::suback_reason_code>(reason) }, packet_id, v5::properties{}, force_move(func));
  3798. }
  3799. }
  3800. /**
  3801. * @brief Send suback packet. This function is for broker.
  3802. * @param packet_id packet id corresponding to subscribe
  3803. * @param reason
  3804. * reason_code<BR>
  3805. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178<BR>
  3806. * 3.9.3 SUBACK Payload
  3807. * @param props
  3808. * Properties<BR>
  3809. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901174<BR>
  3810. * 3.9.2.1 SUBACK Properties
  3811. * @param func
  3812. * functor object who's operator() will be called when the async operation completes.
  3813. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3814. */
  3815. void async_suback(
  3816. packet_id_t packet_id,
  3817. variant<suback_return_code, v5::suback_reason_code> reason,
  3818. v5::properties props,
  3819. async_handler_t func = {}
  3820. ) {
  3821. MQTT_LOG("mqtt_api", info)
  3822. << MQTT_ADD_VALUE(address, this)
  3823. << "async_suback"
  3824. << " pid:" << packet_id
  3825. << " reason:" < reason;
  3826. if (variant_idx(reason) == 0) {
  3827. async_send_suback(std::vector<suback_return_code>{ variant_get<suback_return_code>(reason) }, packet_id, force_move(props), force_move(func));
  3828. }
  3829. else {
  3830. async_send_suback(std::vector<v5::suback_reason_code>{ variant_get<v5::suback_reason_code>(reason) }, packet_id, force_move(props), force_move(func));
  3831. }
  3832. }
  3833. /**
  3834. * @brief Send suback packet. This function is for broker.
  3835. * @param packet_id packet id corresponding to subscribe
  3836. * @param reason
  3837. * a collection of reason_code<BR>
  3838. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178<BR>
  3839. * 3.9.3 SUBACK Payload
  3840. * @param func
  3841. * functor object who's operator() will be called when the async operation completes.
  3842. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3843. */
  3844. void async_suback(
  3845. packet_id_t packet_id,
  3846. variant<std::vector<suback_return_code>, std::vector<v5::suback_reason_code>> reasons,
  3847. async_handler_t func = {}
  3848. ) {
  3849. MQTT_LOG("mqtt_api", info)
  3850. << MQTT_ADD_VALUE(address, this)
  3851. << "async_suback"
  3852. << " pid:" << packet_id;
  3853. async_send_suback(force_move(reasons), packet_id, v5::properties{}, force_move(func));
  3854. }
  3855. /**
  3856. * @brief Send suback packet. This function is for broker.
  3857. * @param packet_id packet id corresponding to subscribe
  3858. * @param reason
  3859. * a collection of reason_code<BR>
  3860. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178<BR>
  3861. * 3.9.3 SUBACK Payload
  3862. * @param props
  3863. * Properties<BR>
  3864. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901174<BR>
  3865. * 3.9.2.1 SUBACK Properties
  3866. * @param func
  3867. * functor object who's operator() will be called when the async operation completes.
  3868. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3869. */
  3870. void async_suback(
  3871. packet_id_t packet_id,
  3872. variant<std::vector<suback_return_code>, std::vector<v5::suback_reason_code>> reasons,
  3873. v5::properties props,
  3874. async_handler_t func = {}
  3875. ) {
  3876. MQTT_LOG("mqtt_api", info)
  3877. << MQTT_ADD_VALUE(address, this)
  3878. << "async_suback"
  3879. << " pid:" << packet_id;
  3880. async_send_suback(force_move(reasons), packet_id, force_move(props), force_move(func));
  3881. }
  3882. /**
  3883. * @brief Send unsuback packet. This function is for broker.
  3884. * @param packet_id packet id corresponding to subscribe
  3885. * @param reason
  3886. * reason_code<BR>
  3887. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194<BR>
  3888. * 3.11.3 UNSUBACK Payload
  3889. * @param func
  3890. * functor object who's operator() will be called when the async operation completes.
  3891. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3892. */
  3893. void async_unsuback(
  3894. packet_id_t packet_id,
  3895. v5::unsuback_reason_code reason,
  3896. async_handler_t func = {}
  3897. ) {
  3898. MQTT_LOG("mqtt_api", info)
  3899. << MQTT_ADD_VALUE(address, this)
  3900. << "async_unsuback"
  3901. << " pid:" << packet_id
  3902. << " reason:" < reason;
  3903. async_send_unsuback(std::vector<v5::unsuback_reason_code>{ reason }, packet_id, force_move(func));
  3904. }
  3905. /**
  3906. * @brief Send unsuback packet. This function is for broker.
  3907. * @param packet_id packet id corresponding to subscribe
  3908. * @param reason
  3909. * reason_code<BR>
  3910. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194<BR>
  3911. * 3.11.3 UNSUBACK Payload
  3912. * @param props
  3913. * Properties<BR>
  3914. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901190<BR>
  3915. * 3.11.2.1 UNSUBACK Properties
  3916. * @param func
  3917. * functor object who's operator() will be called when the async operation completes.
  3918. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3919. */
  3920. void async_unsuback(
  3921. packet_id_t packet_id,
  3922. v5::unsuback_reason_code reason,
  3923. v5::properties props,
  3924. async_handler_t func = {}
  3925. ) {
  3926. MQTT_LOG("mqtt_api", info)
  3927. << MQTT_ADD_VALUE(address, this)
  3928. << "async_unsuback"
  3929. << " pid:" << packet_id
  3930. << " reason:" < reason;
  3931. async_send_unsuback(std::vector<v5::unsuback_reason_code>{ reason }, packet_id, force_move(props), force_move(func));
  3932. }
  3933. /**
  3934. * @brief Send unsuback packet. This function is for broker.
  3935. * @param packet_id packet id corresponding to subscribe
  3936. * @param reasons
  3937. * a collection of reason_code<BR>
  3938. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194<BR>
  3939. * 3.11.3 UNSUBACK Payload
  3940. * @param func
  3941. * functor object who's operator() will be called when the async operation completes.
  3942. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3943. */
  3944. void async_unsuback(
  3945. packet_id_t packet_id,
  3946. std::vector<v5::unsuback_reason_code> reasons,
  3947. async_handler_t func = {}
  3948. ) {
  3949. MQTT_LOG("mqtt_api", info)
  3950. << MQTT_ADD_VALUE(address, this)
  3951. << "async_unsuback"
  3952. << " pid:" << packet_id;
  3953. async_send_unsuback(force_move(reasons), packet_id, v5::properties{}, force_move(func));
  3954. }
  3955. /**
  3956. * @brief Send unsuback packet. This function is for broker.
  3957. * @param packet_id packet id corresponding to subscribe
  3958. * @param reasons
  3959. * a collection of reason_code<BR>
  3960. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194<BR>
  3961. * 3.11.3 UNSUBACK Payload
  3962. * @param props
  3963. * Properties<BR>
  3964. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901190<BR>
  3965. * 3.11.2.1 UNSUBACK Properties
  3966. * @param func
  3967. * functor object who's operator() will be called when the async operation completes.
  3968. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718068
  3969. */
  3970. void async_unsuback(
  3971. packet_id_t packet_id,
  3972. std::vector<v5::unsuback_reason_code> reasons,
  3973. v5::properties props,
  3974. async_handler_t func = {}
  3975. ) {
  3976. MQTT_LOG("mqtt_api", info)
  3977. << MQTT_ADD_VALUE(address, this)
  3978. << "async_unsuback"
  3979. << " pid:" << packet_id;
  3980. async_send_unsuback(force_move(reasons), packet_id, force_move(props), force_move(func));
  3981. }
  3982. /**
  3983. * @brief Send ununsuback packet. This function is for broker.
  3984. * @param packet_id
  3985. * packet id corresponding to unsubscribe
  3986. * @param func
  3987. * functor object who's operator() will be called when the async operation completes.
  3988. * See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc398718077
  3989. */
  3990. void async_unsuback(
  3991. packet_id_t packet_id,
  3992. async_handler_t func = {}
  3993. ) {
  3994. MQTT_LOG("mqtt_api", info)
  3995. << MQTT_ADD_VALUE(address, this)
  3996. << "async_unsuback"
  3997. << " pid:" << packet_id;
  3998. async_send_unsuback(packet_id, force_move(func));
  3999. }
  4000. /**
  4001. * @brief Clear stored publish message that has packet_id.
  4002. * @param packet_id packet id corresponding to stored publish
  4003. */
  4004. void clear_stored_publish(packet_id_t packet_id) {
  4005. LockGuard<Mutex> lck (store_mtx_);
  4006. store_.erase(packet_id);
  4007. pid_man_.release_id(packet_id);
  4008. }
  4009. /**
  4010. * @brief Apply f to stored messages.
  4011. * @param f applying function. f should be void(char const*, std::size_t)
  4012. */
  4013. void for_each_store(std::function<void(char const*, std::size_t)> const& f) {
  4014. MQTT_LOG("mqtt_api", info)
  4015. << MQTT_ADD_VALUE(address, this)
  4016. << "for_each_store(ptr, size)";
  4017. LockGuard<Mutex> lck (store_mtx_);
  4018. store_.for_each(
  4019. [f](
  4020. basic_store_message_variant<PacketIdBytes> const& message,
  4021. any const& /*life_keeper*/
  4022. ) {
  4023. auto cb = continuous_buffer(message);
  4024. f(cb.data(), cb.size());
  4025. return false; // no erase
  4026. }
  4027. );
  4028. }
  4029. /**
  4030. * @brief Apply f to stored messages.
  4031. * @param f applying function. f should be void(store_message_variant)
  4032. */
  4033. void for_each_store(std::function<void(basic_store_message_variant<PacketIdBytes>)> const& f) {
  4034. MQTT_LOG("mqtt_api", info)
  4035. << MQTT_ADD_VALUE(address, this)
  4036. << "for_each_store(store_message_variant)";
  4037. LockGuard<Mutex> lck (store_mtx_);
  4038. store_.for_each(
  4039. [f](
  4040. basic_store_message_variant<PacketIdBytes> const& message,
  4041. any const& /*life_keeper*/
  4042. ) {
  4043. f(message);
  4044. return false; // no erase
  4045. }
  4046. );
  4047. }
  4048. /**
  4049. * @brief Apply f to stored messages.
  4050. * @param f applying function. f should be void(store_message_variant, any)
  4051. */
  4052. void for_each_store_with_life_keeper(std::function<void(basic_store_message_variant<PacketIdBytes>, any)> const& f) {
  4053. MQTT_LOG("mqtt_api", info)
  4054. << MQTT_ADD_VALUE(address, this)
  4055. << "for_each_store(store_message_variant, life_keeper)";
  4056. LockGuard<Mutex> lck (store_mtx_);
  4057. store_.for_each(
  4058. [f](
  4059. basic_store_message_variant<PacketIdBytes> const& message,
  4060. any const& life_keeper
  4061. ) {
  4062. f(message, life_keeper);
  4063. return false; // no erase
  4064. }
  4065. );
  4066. }
  4067. /**
  4068. * @brief Get processed but not released QoS2 packet ids
  4069. * This function should be called after disconnection
  4070. * @return set of packet_ids
  4071. */
  4072. std::set<packet_id_t> get_qos2_publish_handled_pids() const {
  4073. return qos2_publish_handled_;
  4074. }
  4075. /**
  4076. * @brief Restore processed but not released QoS2 packet ids
  4077. * This function should be called before receive the first publish
  4078. * @param pids packet ids
  4079. */
  4080. void restore_qos2_publish_handled_pids(std::set<packet_id_t> pids) {
  4081. qos2_publish_handled_ = force_move(pids);
  4082. }
  4083. // manual packet_id management for advanced users
  4084. /**
  4085. * @brief Acquire the new unique packet id.
  4086. * If all packet ids are already in use, then throw packet_id_exhausted_error exception.
  4087. * After acquiring the packet id, you can call acquired_* functions.
  4088. * The ownership of packet id is moved to the library.
  4089. * Or you can call release_packet_id to release it.
  4090. * @return packet id
  4091. */
  4092. packet_id_t acquire_unique_packet_id() {
  4093. if (auto pid = acquire_unique_packet_id_no_except()) return pid.value();
  4094. throw packet_id_exhausted_error();
  4095. }
  4096. /**
  4097. * @brief Acquire the new unique packet id.
  4098. * If all packet ids are already in use, then returns nullopt
  4099. * After acquiring the packet id, you can call acquired_* functions.
  4100. * The ownership of packet id is moved to the library.
  4101. * Or you can call release_packet_id to release it.
  4102. * @return packet id
  4103. */
  4104. optional<packet_id_t> acquire_unique_packet_id_no_except() {
  4105. LockGuard<Mutex> lck (store_mtx_);
  4106. return pid_man_.acquire_unique_id();
  4107. }
  4108. /**
  4109. * @brief Register packet_id to the library.
  4110. * After registering the packet_id, you can call acquired_* functions.
  4111. * The ownership of packet id is moved to the library.
  4112. * Or you can call release_packet_id to release it.
  4113. * @return If packet_id is successfully registerd then return true, otherwise return false.
  4114. */
  4115. bool register_packet_id(packet_id_t packet_id) {
  4116. LockGuard<Mutex> lck (store_mtx_);
  4117. return pid_man_.register_id(packet_id);
  4118. }
  4119. /**
  4120. * @brief Release packet_id.
  4121. * @param packet_id packet id to release.
  4122. * only the packet_id gotten by acquire_unique_packet_id, or
  4123. * register_packet_id is permitted.
  4124. */
  4125. void release_packet_id(packet_id_t packet_id) {
  4126. LockGuard<Mutex> lck (store_mtx_);
  4127. pid_man_.release_id(packet_id);
  4128. }
  4129. /**
  4130. * @brief Restore serialized publish and pubrel messages.
  4131. * This function should be called before connect.
  4132. * @param b iterator begin of the message
  4133. * @param e iterator end of the message
  4134. */
  4135. template <typename Iterator>
  4136. std::enable_if_t< std::is_convertible<typename Iterator::value_type, char>::value >
  4137. restore_serialized_message(Iterator b, Iterator e) {
  4138. BOOST_ASSERT(version_ == protocol_version::v3_1_1);
  4139. static_assert(
  4140. std::is_same<
  4141. typename std::iterator_traits<Iterator>::iterator_category,
  4142. std::random_access_iterator_tag
  4143. >::value,
  4144. "Iterators provided to restore_serialized_message() must be random access iterators."
  4145. );
  4146. MQTT_LOG("mqtt_api", info)
  4147. << MQTT_ADD_VALUE(address, this)
  4148. << "restore_serialized_message(b, e)";
  4149. if (b == e) return;
  4150. auto fixed_header = static_cast<std::uint8_t>(*b);
  4151. auto cpt_opt = get_control_packet_type_with_check(fixed_header);
  4152. if (!cpt_opt) {
  4153. MQTT_LOG("mqtt_api", error)
  4154. << MQTT_ADD_VALUE(address, this)
  4155. << "invalid fixed_header ignored. "
  4156. << std::hex << static_cast<int>(fixed_header);
  4157. throw malformed_packet_error();
  4158. }
  4159. switch (cpt_opt.value()) {
  4160. case control_packet_type::publish: {
  4161. auto buf = allocate_buffer(b, e);
  4162. restore_serialized_message(
  4163. basic_publish_message<PacketIdBytes>(
  4164. buf
  4165. ),
  4166. buf
  4167. );
  4168. } break;
  4169. case control_packet_type::pubrel: {
  4170. restore_serialized_message(
  4171. basic_pubrel_message<PacketIdBytes>(
  4172. // basic_pubrel_message have no member variable that type is buffer.
  4173. // When creating basic_pubrel_message, the constructor just read buffer
  4174. // and convert to some values.
  4175. // So the argument buffer(...) doesn't need to hold the lifetime.
  4176. buffer(string_view(&*b, static_cast<std::size_t>(std::distance(b, e))))
  4177. )
  4178. );
  4179. } break;
  4180. default:
  4181. MQTT_LOG("mqtt_api", error)
  4182. << MQTT_ADD_VALUE(address, this)
  4183. << "invalid control packet type. "
  4184. << std::hex << static_cast<int>(fixed_header);
  4185. throw protocol_error();
  4186. break;
  4187. }
  4188. }
  4189. /**
  4190. * @brief Restore serialized publish message.
  4191. * This function should be called before connect.
  4192. * @param msg publish message.
  4193. * @param life_keeper
  4194. * An object that stays alive (but is moved with force_move()) until the stored message is sent.
  4195. */
  4196. void restore_serialized_message(basic_publish_message<PacketIdBytes> msg, any life_keeper = {}) {
  4197. BOOST_ASSERT(version_ == protocol_version::v3_1_1);
  4198. auto packet_id = msg.packet_id();
  4199. qos qos_value = msg.get_qos();
  4200. LockGuard<Mutex> lck (store_mtx_);
  4201. if (pid_man_.register_id(packet_id)) {
  4202. store_.insert_or_update(
  4203. packet_id,
  4204. ((qos_value == qos::at_least_once) ? control_packet_type::puback
  4205. : control_packet_type::pubrec),
  4206. force_move(msg),
  4207. force_move(life_keeper)
  4208. );
  4209. }
  4210. }
  4211. /**
  4212. * @brief Restore serialized pubrel message.
  4213. * This function should be called before connect.
  4214. * @param msg pubrel message.
  4215. */
  4216. void restore_serialized_message(basic_pubrel_message<PacketIdBytes> msg, any life_keeper = {}) {
  4217. BOOST_ASSERT(version_ == protocol_version::v3_1_1);
  4218. auto packet_id = msg.packet_id();
  4219. LockGuard<Mutex> lck (store_mtx_);
  4220. if (pid_man_.register_id(packet_id)) {
  4221. store_.insert_or_update(
  4222. packet_id,
  4223. control_packet_type::pubcomp,
  4224. force_move(msg),
  4225. force_move(life_keeper)
  4226. );
  4227. }
  4228. }
  4229. /**
  4230. * @brief Restore serialized publish and pubrel messages.
  4231. * This function shouold be called before connect.
  4232. * @param b iterator begin of the message
  4233. * @param e iterator end of the message
  4234. * Empty topic_name on MQTT v5 publish message is prohibited.
  4235. */
  4236. template <typename Iterator>
  4237. std::enable_if_t< std::is_convertible<typename Iterator::value_type, char>::value >
  4238. restore_v5_serialized_message(Iterator b, Iterator e) {
  4239. BOOST_ASSERT(version_ == protocol_version::v5);
  4240. if (b == e) return;
  4241. auto fixed_header = static_cast<std::uint8_t>(*b);
  4242. auto cpt_opt = get_control_packet_type_with_check(fixed_header);
  4243. if (!cpt_opt) {
  4244. MQTT_LOG("mqtt_api", error)
  4245. << MQTT_ADD_VALUE(address, this)
  4246. << "invalid fixed_header ignored. "
  4247. << std::hex << static_cast<int>(fixed_header);
  4248. throw malformed_packet_error();
  4249. }
  4250. switch (cpt_opt.value()) {
  4251. case control_packet_type::publish: {
  4252. auto buf = allocate_buffer(b, e);
  4253. restore_v5_serialized_message(
  4254. v5::basic_publish_message<PacketIdBytes>(buf),
  4255. buf
  4256. );
  4257. } break;
  4258. case control_packet_type::pubrel: {
  4259. auto buf = allocate_buffer(b, e);
  4260. restore_v5_serialized_message(
  4261. v5::basic_pubrel_message<PacketIdBytes>(buf),
  4262. buf
  4263. );
  4264. } break;
  4265. default:
  4266. MQTT_LOG("mqtt_api", error)
  4267. << MQTT_ADD_VALUE(address, this)
  4268. << "invalid control packet type. "
  4269. << std::hex << static_cast<int>(fixed_header);
  4270. throw protocol_error();
  4271. break;
  4272. }
  4273. }
  4274. /**
  4275. * @brief Restore serialized publish message.
  4276. * This function shouold be called before connect.
  4277. * @param msg publish message. Empty topic_name is prohibited.
  4278. * @param life_keeper
  4279. * An object that stays alive (but is moved with force_move()) until the stored message is sent.
  4280. */
  4281. void restore_v5_serialized_message(v5::basic_publish_message<PacketIdBytes> msg, any life_keeper = {}) {
  4282. BOOST_ASSERT(version_ == protocol_version::v5);
  4283. BOOST_ASSERT(!msg.topic().empty());
  4284. auto packet_id = msg.packet_id();
  4285. auto qos = msg.get_qos();
  4286. LockGuard<Mutex> lck (store_mtx_);
  4287. if (pid_man_.register_id(packet_id)) {
  4288. store_.insert_or_update(
  4289. packet_id,
  4290. qos == qos::at_least_once ? control_packet_type::puback
  4291. : control_packet_type::pubrec,
  4292. force_move(msg),
  4293. force_move(life_keeper)
  4294. );
  4295. }
  4296. }
  4297. /**
  4298. * @brief Restore serialized pubrel message.
  4299. * This function shouold be called before connect.
  4300. * @param msg pubrel message.
  4301. * @param life_keeper
  4302. * An object that stays alive (but is moved with force_move()) until the stored message is sent.
  4303. */
  4304. void restore_v5_serialized_message(v5::basic_pubrel_message<PacketIdBytes> msg, any life_keeper = {}) {
  4305. BOOST_ASSERT(version_ == protocol_version::v5);
  4306. auto packet_id = msg.packet_id();
  4307. LockGuard<Mutex> lck (store_mtx_);
  4308. if (pid_man_.register_id(packet_id)) {
  4309. store_.insert_or_update(
  4310. packet_id,
  4311. control_packet_type::pubcomp,
  4312. force_move(msg),
  4313. force_move(life_keeper)
  4314. );
  4315. }
  4316. }
  4317. private:
  4318. struct restore_basic_message_variant_visitor {
  4319. restore_basic_message_variant_visitor(this_type& ep, any life_keeper):ep_(ep), life_keeper_(force_move(life_keeper)) {}
  4320. void operator()(basic_publish_message<PacketIdBytes>&& msg) {
  4321. ep_.restore_serialized_message(force_move(msg), force_move(life_keeper_));
  4322. }
  4323. void operator()(basic_pubrel_message<PacketIdBytes>&& msg) {
  4324. ep_.restore_serialized_message(force_move(msg), force_move(life_keeper_));
  4325. }
  4326. void operator()(v5::basic_publish_message<PacketIdBytes>&& msg) {
  4327. ep_.restore_v5_serialized_message(force_move(msg), force_move(life_keeper_));
  4328. }
  4329. void operator()(v5::basic_pubrel_message<PacketIdBytes>&& msg) {
  4330. ep_.restore_v5_serialized_message(force_move(msg), force_move(life_keeper_));
  4331. }
  4332. template <typename T>
  4333. void operator()(T&&) const {
  4334. throw restore_type_error();
  4335. }
  4336. private:
  4337. this_type& ep_;
  4338. any life_keeper_;
  4339. };
  4340. public:
  4341. void restore_serialized_message(basic_store_message_variant<PacketIdBytes> msg, any life_keeper = {}) {
  4342. MQTT_NS::visit(restore_basic_message_variant_visitor(*this, force_move(life_keeper)), force_move(msg));
  4343. }
  4344. void send_store_message(basic_store_message_variant<PacketIdBytes> msg, any life_keeper) {
  4345. auto publish_proc =
  4346. [&](auto msg, auto&& serialize, auto&& receive_maximum_proc) {
  4347. auto msg_lk = apply_topic_alias(msg, life_keeper);
  4348. if (maximum_packet_size_send_ < size<PacketIdBytes>(std::get<0>(msg_lk))) {
  4349. throw packet_size_error();
  4350. }
  4351. if (preprocess_publish_message(
  4352. msg,
  4353. life_keeper,
  4354. std::forward<decltype(serialize)>(serialize),
  4355. std::forward<decltype(receive_maximum_proc)>(receive_maximum_proc),
  4356. true // register packet_id
  4357. )
  4358. ) {
  4359. do_sync_write(force_move(std::get<0>(msg_lk)));
  4360. }
  4361. };
  4362. auto pubrel_proc =
  4363. [&](auto msg, auto const& serialize) {
  4364. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  4365. throw packet_size_error();
  4366. }
  4367. auto packet_id = msg.packet_id();
  4368. LockGuard<Mutex> lck (store_mtx_);
  4369. pid_man_.register_id(packet_id);
  4370. auto ret = store_.insert(
  4371. packet_id,
  4372. control_packet_type::pubcomp,
  4373. msg,
  4374. force_move(life_keeper)
  4375. );
  4376. (void)ret;
  4377. BOOST_ASSERT(ret);
  4378. (this->*serialize)(msg);
  4379. do_sync_write(force_move(msg));
  4380. };
  4381. MQTT_NS::visit(
  4382. make_lambda_visitor(
  4383. [this, &publish_proc](v3_1_1::basic_publish_message<PacketIdBytes>& m) {
  4384. MQTT_LOG("mqtt_api", info)
  4385. << MQTT_ADD_VALUE(address, this)
  4386. << "send_store_message publish v3.1.1";
  4387. publish_proc(
  4388. force_move(m),
  4389. &endpoint::on_serialize_publish_message,
  4390. [] (auto&&) { return true; }
  4391. );
  4392. },
  4393. [this, &pubrel_proc](v3_1_1::basic_pubrel_message<PacketIdBytes>& m) {
  4394. MQTT_LOG("mqtt_api", info)
  4395. << MQTT_ADD_VALUE(address, this)
  4396. << "send_store_message pubrel v3.1.1";
  4397. pubrel_proc(force_move(m), &endpoint::on_serialize_pubrel_message);
  4398. },
  4399. [this, &publish_proc](v5::basic_publish_message<PacketIdBytes>& m) {
  4400. MQTT_LOG("mqtt_api", info)
  4401. << MQTT_ADD_VALUE(address, this)
  4402. << "send_store_message publish v5";
  4403. publish_proc(
  4404. force_move(m),
  4405. &endpoint::on_serialize_v5_publish_message,
  4406. [this] (v5::basic_publish_message<PacketIdBytes>&& msg) {
  4407. if (publish_send_count_.load() == publish_send_max_) {
  4408. LockGuard<Mutex> lck (publish_send_queue_mtx_);
  4409. publish_send_queue_.emplace_back(force_move(msg), false);
  4410. return false;
  4411. }
  4412. else {
  4413. MQTT_LOG("mqtt_impl", trace)
  4414. << MQTT_ADD_VALUE(address, this)
  4415. << "increment publish_send_count_:" << publish_send_count_.load();
  4416. ++publish_send_count_;
  4417. }
  4418. return true;
  4419. }
  4420. );
  4421. },
  4422. [this, &pubrel_proc](v5::basic_pubrel_message<PacketIdBytes>& m) {
  4423. MQTT_LOG("mqtt_api", info)
  4424. << MQTT_ADD_VALUE(address, this)
  4425. << "send_store_message pubrel v5";
  4426. {
  4427. LockGuard<Mutex> lck (resend_pubrel_mtx_);
  4428. resend_pubrel_.insert(m.packet_id());
  4429. }
  4430. pubrel_proc(force_move(m), &endpoint::on_serialize_v5_pubrel_message);
  4431. }
  4432. ),
  4433. msg
  4434. );
  4435. }
  4436. void async_send_store_message(basic_store_message_variant<PacketIdBytes> msg, any life_keeper, async_handler_t func) {
  4437. auto publish_proc =
  4438. [&](auto msg, auto&& serialize, auto&& receive_maximum_proc) {
  4439. auto msg_lk = apply_topic_alias(msg, life_keeper);
  4440. if (maximum_packet_size_send_ < size<PacketIdBytes>(std::get<0>(msg_lk))) {
  4441. socket_->post(
  4442. [func = force_move(func)] {
  4443. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  4444. }
  4445. );
  4446. return;
  4447. }
  4448. if (preprocess_publish_message(
  4449. msg,
  4450. life_keeper,
  4451. std::forward<decltype(serialize)>(serialize),
  4452. std::forward<decltype(receive_maximum_proc)>(receive_maximum_proc),
  4453. true // register packet_id
  4454. )
  4455. ) {
  4456. do_async_write(
  4457. force_move(std::get<0>(msg_lk)),
  4458. [func = force_move(func), life_keeper = force_move(std::get<1>(msg_lk))]
  4459. (error_code ec) {
  4460. if (func) func(ec);
  4461. }
  4462. );
  4463. }
  4464. };
  4465. auto pubrel_proc =
  4466. [&](auto msg, auto const& serialize) {
  4467. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  4468. socket_->post(
  4469. [func = force_move(func)] {
  4470. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  4471. }
  4472. );
  4473. return;
  4474. }
  4475. auto packet_id = msg.packet_id();
  4476. LockGuard<Mutex> lck (store_mtx_);
  4477. pid_man_.register_id(packet_id);
  4478. auto ret = store_.insert(
  4479. packet_id,
  4480. control_packet_type::pubcomp,
  4481. msg,
  4482. force_move(life_keeper)
  4483. );
  4484. (void)ret;
  4485. BOOST_ASSERT(ret);
  4486. (this->*serialize)(msg);
  4487. do_async_write(force_move(msg), force_move(func));
  4488. };
  4489. MQTT_NS::visit(
  4490. make_lambda_visitor(
  4491. [this, &publish_proc](v3_1_1::basic_publish_message<PacketIdBytes>& m) {
  4492. MQTT_LOG("mqtt_api", info)
  4493. << MQTT_ADD_VALUE(address, this)
  4494. << "async_send_store_message publish v3.1.1";
  4495. publish_proc(
  4496. force_move(m),
  4497. &endpoint::on_serialize_publish_message,
  4498. [] (auto&&) { return true; }
  4499. );
  4500. },
  4501. [this, &pubrel_proc](v3_1_1::basic_pubrel_message<PacketIdBytes>& m) {
  4502. MQTT_LOG("mqtt_api", info)
  4503. << MQTT_ADD_VALUE(address, this)
  4504. << "async_send_store_message pubrel v3.1.1";
  4505. pubrel_proc(force_move(m), &endpoint::on_serialize_pubrel_message);
  4506. },
  4507. [this, &publish_proc, &func](v5::basic_publish_message<PacketIdBytes>& m) {
  4508. MQTT_LOG("mqtt_api", info)
  4509. << MQTT_ADD_VALUE(address, this)
  4510. << "async_send_store_message publish v5";
  4511. publish_proc(
  4512. force_move(m),
  4513. &endpoint::on_serialize_v5_publish_message,
  4514. [this, func] (v5::basic_publish_message<PacketIdBytes>&& msg) mutable {
  4515. if (publish_send_count_.load() == publish_send_max_) {
  4516. {
  4517. LockGuard<Mutex> lck (publish_send_queue_mtx_);
  4518. publish_send_queue_.emplace_back(force_move(msg), true);
  4519. }
  4520. socket_->post(
  4521. [func = force_move(func)] {
  4522. // message has already been stored so func should be called with success here
  4523. if (func) func(boost::system::errc::make_error_code(boost::system::errc::success));
  4524. }
  4525. );
  4526. return false;
  4527. }
  4528. else {
  4529. MQTT_LOG("mqtt_impl", trace)
  4530. << MQTT_ADD_VALUE(address, this)
  4531. << "increment publish_send_count_:" << publish_send_count_.load();
  4532. ++publish_send_count_;
  4533. }
  4534. return true;
  4535. }
  4536. );
  4537. },
  4538. [this, &pubrel_proc](v5::basic_pubrel_message<PacketIdBytes>& m) {
  4539. MQTT_LOG("mqtt_api", info)
  4540. << MQTT_ADD_VALUE(address, this)
  4541. << "async_send_store_message pubrel v5";
  4542. {
  4543. LockGuard<Mutex> lck (resend_pubrel_mtx_);
  4544. resend_pubrel_.insert(m.packet_id());
  4545. }
  4546. pubrel_proc(force_move(m), &endpoint::on_serialize_v5_pubrel_message);
  4547. }
  4548. ),
  4549. msg
  4550. );
  4551. }
  4552. /**
  4553. * @brief Check connection status
  4554. * @return current connection status
  4555. */
  4556. bool connected() const {
  4557. return connected_ && mqtt_connected_;
  4558. }
  4559. /**
  4560. * @brief Check underlying layer connection status
  4561. * @return current connection status
  4562. */
  4563. bool underlying_connected() const {
  4564. return connected_;
  4565. }
  4566. /**
  4567. * @brief Trigger next mqtt message manually.
  4568. * If you call this function, you need to set manual receive mode
  4569. * using set_auto_next_read(false);
  4570. */
  4571. void async_read_next_message(any session_life_keeper) {
  4572. async_read_control_packet_type(force_move(session_life_keeper));
  4573. }
  4574. /**
  4575. * @brief Set maximum number of queued message sending.
  4576. * When async message sending function called during asynchronous
  4577. * processing, the message is enqueued. When current asynchronous
  4578. * message is processed, then concatenate queued messages and
  4579. * send it.
  4580. * This value limits the maximum number of concatenating messages.
  4581. * The default value is 1.
  4582. *
  4583. * @param count maximum number of queued message sending. 0 means infinity.
  4584. *
  4585. */
  4586. void set_max_queue_send_count(std::size_t count) {
  4587. max_queue_send_count_ = count;
  4588. }
  4589. /**
  4590. * @brief Set maximum size of queued message sending.
  4591. * When async message sending function called during asynchronous
  4592. * processing, the message is enqueued. When current asynchronous
  4593. * message is processed, then concatenate queued messages and
  4594. * send it.
  4595. * This value limits the maximum size of concatenating messages.
  4596. * The default value is 0.
  4597. *
  4598. * @param size maximum size of queued message sending. 0 means infinity.
  4599. *
  4600. */
  4601. void set_max_queue_send_size(std::size_t size) {
  4602. max_queue_send_size_ = size;
  4603. }
  4604. protocol_version get_protocol_version() const {
  4605. return version_;
  4606. }
  4607. MQTT_NS::socket const& socket() const {
  4608. return *socket_;
  4609. }
  4610. MQTT_NS::socket& socket() {
  4611. return *socket_;
  4612. }
  4613. auto get_executor() {
  4614. return socket_->get_executor();
  4615. }
  4616. /**
  4617. * @brief Set pingresp timeout
  4618. * @param tim timeout value
  4619. *
  4620. * If tim is not zero, when the client sends PINGREQ, set a timer.
  4621. * The timer cancels when PINGRESP is received. If the timer is fired, then force_disconnect
  4622. * from the client side.<BR>
  4623. * https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901045<BR>
  4624. * 3.1.2.10 Keep Alive
  4625. */
  4626. void set_pingresp_timeout(std::chrono::steady_clock::duration tim) {
  4627. pingresp_timeout_ = force_move(tim);
  4628. }
  4629. /**
  4630. * @brief Set maximum packet size that endpoint can receive
  4631. * If the endpoint is client, then it sends as CONNECT packet property.
  4632. * If the endpoint is server, then it sends as CONNACK packet property.
  4633. * If property is manually set, then maximum_packet_size_recv_ is overwritten by the property.
  4634. *
  4635. * @param size maximum packet size
  4636. */
  4637. void set_maximum_packet_size_recv(std::size_t size) {
  4638. BOOST_ASSERT(size > 0 && size <= packet_size_no_limit);
  4639. maximum_packet_size_recv_ = size;
  4640. }
  4641. /**
  4642. * @brief Set receive maximum that endpoint can receive
  4643. * If the endpoint is client, then it sends as CONNECT packet property.
  4644. * If the endpoint is server, then it sends as CONNACK packet property.
  4645. * If property is manually set, then publish_recv_max_ is overwritten by the property.
  4646. *
  4647. * @param size maximum packet size
  4648. */
  4649. void set_receive_maximum(receive_maximum_t val) {
  4650. BOOST_ASSERT(val > 0);
  4651. publish_recv_max_ = val;
  4652. }
  4653. protected:
  4654. /**
  4655. * @brief Get shared_ptr of socket
  4656. * @return reference of std::shared_ptr<socket>
  4657. */
  4658. std::shared_ptr<MQTT_NS::socket>& socket_sp_ref() {
  4659. return socket_;
  4660. }
  4661. void async_read_control_packet_type(any session_life_keeper) {
  4662. socket_->async_read(
  4663. as::buffer(buf_.data(), 1),
  4664. [this, self = this->shared_from_this(), session_life_keeper = force_move(session_life_keeper)](
  4665. error_code ec,
  4666. std::size_t bytes_transferred) mutable {
  4667. this->total_bytes_received_ += bytes_transferred;
  4668. if (!check_error_and_transferred_length(ec, bytes_transferred, 1)) return;
  4669. handle_control_packet_type(force_move(session_life_keeper), force_move(self));
  4670. }
  4671. );
  4672. }
  4673. bool handle_close_or_error(error_code ec) {
  4674. auto call_handler =
  4675. [this, ec] () mutable {
  4676. MQTT_LOG("mqtt_impl", trace)
  4677. << MQTT_ADD_VALUE(address, this)
  4678. << "handle_close_or_error call_handler";
  4679. connect_requested_ = false;
  4680. clean_sub_unsub_inflight();
  4681. if (disconnect_requested_) {
  4682. on_close();
  4683. disconnect_requested_ = false;
  4684. }
  4685. else {
  4686. if (!ec) ec = boost::system::errc::make_error_code(boost::system::errc::not_connected);
  4687. on_error(ec);
  4688. }
  4689. };
  4690. if (connected_) {
  4691. if (!ec) return false;
  4692. MQTT_LOG("mqtt_impl", trace)
  4693. << MQTT_ADD_VALUE(address, this)
  4694. << "handle_close_or_error call shutdown";
  4695. if (async_operation_) {
  4696. async_shutdown(
  4697. socket(),
  4698. [call_handler](error_code) mutable {
  4699. call_handler();
  4700. }
  4701. );
  4702. }
  4703. else {
  4704. sync_shutdown(socket());
  4705. call_handler();
  4706. }
  4707. }
  4708. else {
  4709. call_handler();
  4710. }
  4711. return true;
  4712. }
  4713. void set_connect() {
  4714. connected_ = true;
  4715. }
  4716. void set_protocol_version(protocol_version version) {
  4717. version_ = version;
  4718. }
  4719. void clear_session_data() {
  4720. LockGuard<Mutex> lck (store_mtx_);
  4721. store_.clear();
  4722. pid_man_.clear();
  4723. }
  4724. private:
  4725. enum class connection_type {
  4726. client,
  4727. server
  4728. };
  4729. void update_values_and_props_on_start_connection(v5::properties& props) {
  4730. // Check properties and overwrite the values by properties
  4731. std::size_t topic_alias_maximum_count = 0;
  4732. std::size_t maximum_packet_size_count = 0;
  4733. std::size_t receive_maximum_count = 0;
  4734. v5::visit_props(
  4735. props,
  4736. [&](v5::property::topic_alias_maximum const& p) {
  4737. if (++topic_alias_maximum_count == 2) {
  4738. throw protocol_error();
  4739. return;
  4740. }
  4741. LockGuard<Mutex> lck (topic_alias_recv_mtx_);
  4742. if (p.val() == 0) {
  4743. topic_alias_recv_ = nullopt;
  4744. }
  4745. else {
  4746. topic_alias_recv_.emplace(p.val());
  4747. }
  4748. },
  4749. [&](v5::property::maximum_packet_size const& p) {
  4750. if (++maximum_packet_size_count == 2) {
  4751. throw protocol_error();
  4752. return;
  4753. }
  4754. if (p.val() == 0) {
  4755. throw protocol_error();
  4756. return;
  4757. }
  4758. maximum_packet_size_recv_ = p.val();
  4759. },
  4760. [&](v5::property::receive_maximum const& p) {
  4761. if (++receive_maximum_count == 2) {
  4762. throw protocol_error();
  4763. return;
  4764. }
  4765. if (p.val() == 0) {
  4766. throw protocol_error();
  4767. return;
  4768. }
  4769. publish_recv_max_ = p.val();
  4770. },
  4771. [](auto&&) {
  4772. }
  4773. );
  4774. // If property is not set, then set property automatically.
  4775. if (topic_alias_maximum_count == 0) {
  4776. LockGuard<Mutex> lck (topic_alias_recv_mtx_);
  4777. if (topic_alias_recv_ && topic_alias_recv_.value().max() != 0) {
  4778. props.emplace_back(
  4779. MQTT_NS::v5::property::topic_alias_maximum(topic_alias_recv_.value().max())
  4780. );
  4781. }
  4782. }
  4783. if (maximum_packet_size_count == 0) {
  4784. if (maximum_packet_size_recv_ != packet_size_no_limit) {
  4785. props.emplace_back(
  4786. MQTT_NS::v5::property::maximum_packet_size(static_cast<std::uint32_t>(maximum_packet_size_recv_))
  4787. );
  4788. }
  4789. }
  4790. if (receive_maximum_count == 0) {
  4791. if (publish_recv_max_ != receive_maximum_max) {
  4792. props.emplace_back(
  4793. MQTT_NS::v5::property::receive_maximum(static_cast<receive_maximum_t>(publish_recv_max_))
  4794. );
  4795. }
  4796. }
  4797. }
  4798. bool set_values_from_props_on_connection(connection_type type, v5::properties const& props) {
  4799. #define MQTT_SEND_ERROR(rc) \
  4800. switch (type) { \
  4801. case connection_type::client: \
  4802. send_error_disconnect(v5::disconnect_reason_code::rc); \
  4803. break; \
  4804. case connection_type::server: \
  4805. send_error_connack(v5::connect_reason_code::rc); \
  4806. break; \
  4807. default: \
  4808. BOOST_ASSERT(false); \
  4809. break; \
  4810. }
  4811. bool ret = true;
  4812. std::size_t topic_alias_maximum_count = 0;
  4813. std::size_t maximum_packet_size_count = 0;
  4814. std::size_t receive_maximum_count = 0;
  4815. std::size_t assigned_client_identifier_count = 0;
  4816. v5::visit_props(
  4817. props,
  4818. [&](v5::property::topic_alias_maximum const& p) {
  4819. if (++topic_alias_maximum_count == 2) {
  4820. MQTT_SEND_ERROR(protocol_error);
  4821. ret = false;
  4822. return;
  4823. }
  4824. if (topic_alias_maximum_count > 2) {
  4825. ret = false;
  4826. return;
  4827. }
  4828. if (p.val() > 0) {
  4829. LockGuard<Mutex> lck (topic_alias_send_mtx_);
  4830. topic_alias_send_.emplace(p.val());
  4831. }
  4832. },
  4833. [&](v5::property::maximum_packet_size const& p) {
  4834. if (++maximum_packet_size_count == 2) {
  4835. MQTT_SEND_ERROR(protocol_error);
  4836. ret = false;
  4837. return;
  4838. }
  4839. if (maximum_packet_size_count > 2) {
  4840. ret = false;
  4841. return;
  4842. }
  4843. if (p.val() == 0) {
  4844. MQTT_SEND_ERROR(protocol_error);
  4845. ret = false;
  4846. return;
  4847. }
  4848. maximum_packet_size_send_ = p.val();
  4849. },
  4850. [&](v5::property::receive_maximum const& p) {
  4851. if (++receive_maximum_count == 2) {
  4852. MQTT_SEND_ERROR(protocol_error);
  4853. ret = false;
  4854. return;
  4855. }
  4856. if (receive_maximum_count > 2) {
  4857. ret = false;
  4858. return;
  4859. }
  4860. if (p.val() == 0) {
  4861. MQTT_SEND_ERROR(protocol_error);
  4862. ret = false;
  4863. return;
  4864. }
  4865. publish_send_max_ = p.val();
  4866. },
  4867. [&](v5::property::assigned_client_identifier const& p) {
  4868. if (type != connection_type::client) {
  4869. MQTT_SEND_ERROR(protocol_error);
  4870. ret = false;
  4871. return;
  4872. }
  4873. if (++assigned_client_identifier_count == 2) {
  4874. MQTT_SEND_ERROR(protocol_error);
  4875. ret = false;
  4876. return;
  4877. }
  4878. if (assigned_client_identifier_count > 2) {
  4879. ret = false;
  4880. return;
  4881. }
  4882. set_client_id(std::string(p.val()));
  4883. },
  4884. [](auto&&) {
  4885. }
  4886. );
  4887. #undef MQTT_SEND_ERROR
  4888. return ret;
  4889. }
  4890. bool check_transferred_length(
  4891. std::size_t bytes_transferred,
  4892. std::size_t bytes_expected) {
  4893. if (bytes_transferred != bytes_expected) {
  4894. call_bad_message_error_handlers();
  4895. return false;
  4896. }
  4897. return true;
  4898. }
  4899. bool check_error_and_transferred_length(
  4900. error_code ec,
  4901. std::size_t bytes_transferred,
  4902. std::size_t bytes_expected) {
  4903. if (handle_close_or_error(ec)) return false;
  4904. if (!check_transferred_length(bytes_transferred, bytes_expected)) return false;
  4905. return true;
  4906. }
  4907. void call_bad_message_error_handlers() {
  4908. clean_sub_unsub_inflight_on_error(boost::system::errc::make_error_code(boost::system::errc::bad_message));
  4909. }
  4910. void call_protocol_error_handlers() {
  4911. clean_sub_unsub_inflight_on_error(boost::system::errc::make_error_code(boost::system::errc::protocol_error));
  4912. }
  4913. void shutdown(MQTT_NS::socket& s) {
  4914. if (async_operation_) {
  4915. async_shutdown(s, [](auto){});
  4916. }
  4917. else {
  4918. sync_shutdown(s);
  4919. }
  4920. }
  4921. void sync_shutdown(MQTT_NS::socket& s) {
  4922. MQTT_LOG("mqtt_impl", trace)
  4923. << MQTT_ADD_VALUE(address, this)
  4924. << "sync_shutdown";
  4925. if (shutdown_requested_) {
  4926. MQTT_LOG("mqtt_impl", trace)
  4927. << MQTT_ADD_VALUE(address, this)
  4928. << "already shutdowned";
  4929. return;
  4930. }
  4931. shutdown_requested_ = true;
  4932. mqtt_connected_ = false;
  4933. error_code ec;
  4934. MQTT_LOG("mqtt_impl", trace)
  4935. << MQTT_ADD_VALUE(address, this)
  4936. << "clean_shutdown_and_close";
  4937. s.clean_shutdown_and_close(ec);
  4938. MQTT_LOG("mqtt_impl", trace)
  4939. << MQTT_ADD_VALUE(address, this)
  4940. << "clean_shutdown_and_close ec:"
  4941. << ec.message();
  4942. connected_ = false;
  4943. }
  4944. void async_shutdown(MQTT_NS::socket& s, async_handler_t func) {
  4945. MQTT_LOG("mqtt_impl", trace)
  4946. << MQTT_ADD_VALUE(address, this)
  4947. << "shutdown";
  4948. if (shutdown_requested_) {
  4949. MQTT_LOG("mqtt_impl", trace)
  4950. << MQTT_ADD_VALUE(address, this)
  4951. << "already shutdowned";
  4952. if (async_shutdown_handler_called_) {
  4953. MQTT_LOG("mqtt_impl", trace)
  4954. << MQTT_ADD_VALUE(address, this)
  4955. << "async_shutdown handler immediately called";
  4956. if (func) func(boost::system::errc::make_error_code(boost::system::errc::success));
  4957. }
  4958. else {
  4959. MQTT_LOG("mqtt_impl", trace)
  4960. << MQTT_ADD_VALUE(address, this)
  4961. << "enqueue async_shutdown handler";
  4962. async_shutdown_handler_queue_.emplace_back(force_move(func));
  4963. }
  4964. return;
  4965. }
  4966. shutdown_requested_ = true;
  4967. mqtt_connected_ = false;
  4968. async_shutdown_handler_called_ = false;
  4969. MQTT_LOG("mqtt_impl", trace)
  4970. << MQTT_ADD_VALUE(address, this)
  4971. << "enqueue async_shutdown handler";
  4972. async_shutdown_handler_queue_.emplace_back(force_move(func));
  4973. MQTT_LOG("mqtt_impl", trace)
  4974. << MQTT_ADD_VALUE(address, this)
  4975. << "async_clean_shutdown_and_close";
  4976. auto call_handlers =
  4977. [this] {
  4978. std::vector<async_handler_t> handlers;
  4979. handlers.reserve(async_shutdown_handler_queue_.size());
  4980. std::move(
  4981. async_shutdown_handler_queue_.begin(),
  4982. async_shutdown_handler_queue_.end(),
  4983. std::back_inserter(handlers)
  4984. );
  4985. async_shutdown_handler_queue_.clear();
  4986. for (auto const& h : handlers) {
  4987. if (h) h(boost::system::errc::make_error_code(boost::system::errc::success));
  4988. }
  4989. async_shutdown_handler_called_ = true;
  4990. };
  4991. s.async_clean_shutdown_and_close(
  4992. [
  4993. this,
  4994. sp = this->shared_from_this(),
  4995. ssp = socket_sp_ref(),
  4996. call_handlers
  4997. ]
  4998. (error_code ec) { // *1
  4999. MQTT_LOG("mqtt_impl", trace)
  5000. << MQTT_ADD_VALUE(address, this)
  5001. << "async_clean_shutdown_and_close ec:"
  5002. << ec.message();
  5003. {
  5004. LockGuard<Mutex> lck (mtx_tim_shutdown_);
  5005. tim_shutdown_.cancel();
  5006. }
  5007. connected_ = false;
  5008. call_handlers();
  5009. }
  5010. );
  5011. // timeout timer set
  5012. LockGuard<Mutex> lck (mtx_tim_shutdown_);
  5013. tim_shutdown_.expires_after(shutdown_timeout);
  5014. std::weak_ptr<this_type> wp(std::static_pointer_cast<this_type>(this->shared_from_this()));
  5015. tim_shutdown_.async_wait(
  5016. [
  5017. this,
  5018. wp = force_move(wp),
  5019. ssp = socket_sp_ref(),
  5020. call_handlers = force_move(call_handlers)
  5021. ]
  5022. (error_code ec) mutable {
  5023. if (auto sp = wp.lock()) {
  5024. MQTT_LOG("mqtt_impl", trace)
  5025. << MQTT_ADD_VALUE(address, this)
  5026. << "async_shutdown timer ec:"
  5027. << ec.message();
  5028. if (!ec) {
  5029. // timeout
  5030. // tcp_shutdown indirectly cancel stream.async_shutdown()
  5031. // and handler is called with error.
  5032. // So captured sp at *1 is released.
  5033. // post is for applying strand
  5034. MQTT_LOG("mqtt_impl", trace)
  5035. << MQTT_ADD_VALUE(address, this)
  5036. << "post force_shutdown_and_close";
  5037. sp->socket().post(
  5038. [this, sp, call_handlers = force_move(call_handlers)] {
  5039. error_code ec;
  5040. socket().force_shutdown_and_close(ec);
  5041. MQTT_LOG("mqtt_impl", trace)
  5042. << MQTT_ADD_VALUE(address, this)
  5043. << "force_shutdown_and_close ec:"
  5044. << ec.message();
  5045. call_handlers();
  5046. connected_ = false;
  5047. }
  5048. );
  5049. }
  5050. }
  5051. }
  5052. );
  5053. }
  5054. void send_error_disconnect(v5::disconnect_reason_code rc) {
  5055. if (async_operation_) {
  5056. auto sp = this->shared_from_this();
  5057. async_disconnect(
  5058. rc,
  5059. v5::properties{},
  5060. [sp = force_move(sp)] (error_code) mutable {
  5061. auto p = sp.get();
  5062. p->async_force_disconnect(
  5063. [sp = force_move(sp)](error_code) {
  5064. }
  5065. );
  5066. }
  5067. );
  5068. }
  5069. else {
  5070. disconnect(rc);
  5071. force_disconnect();
  5072. }
  5073. }
  5074. void send_error_connack(v5::connect_reason_code rc) {
  5075. if (async_operation_) {
  5076. auto sp = this->shared_from_this();
  5077. async_connack(
  5078. false,
  5079. rc,
  5080. [sp = force_move(sp)] (error_code) mutable {
  5081. auto p = sp.get();
  5082. p->async_force_disconnect(
  5083. [sp = force_move(sp)](error_code) {
  5084. }
  5085. );
  5086. }
  5087. );
  5088. }
  5089. else {
  5090. connack(false, rc);
  5091. force_disconnect();
  5092. }
  5093. }
  5094. class send_buffer {
  5095. public:
  5096. send_buffer():buf_(std::make_shared<std::string>(static_cast<int>(payload_position_), 0)) {}
  5097. std::shared_ptr<std::string> const& buf() const {
  5098. return buf_;
  5099. }
  5100. std::shared_ptr<std::string>& buf() {
  5101. return buf_;
  5102. }
  5103. std::pair<char*, std::size_t> finalize(std::uint8_t fixed_header) {
  5104. auto rb = remaining_bytes(buf_->size() - payload_position_);
  5105. std::size_t start_position = payload_position_ - rb.size() - 1;
  5106. (*buf_)[start_position] = fixed_header;
  5107. buf_->replace(start_position + 1, rb.size(), rb);
  5108. return std::make_pair(
  5109. &(*buf_)[start_position],
  5110. buf_->size() - start_position);
  5111. }
  5112. private:
  5113. static constexpr std::size_t payload_position_ = 5;
  5114. std::shared_ptr<std::string> buf_;
  5115. };
  5116. void handle_control_packet_type(any session_life_keeper, this_type_sp self) {
  5117. fixed_header_ = static_cast<std::uint8_t>(buf_.front());
  5118. remaining_length_ = 0;
  5119. remaining_length_multiplier_ = 1;
  5120. socket_->async_read(
  5121. as::buffer(buf_.data(), 1),
  5122. [this, self = force_move(self), session_life_keeper = force_move(session_life_keeper)] (
  5123. error_code ec,
  5124. std::size_t bytes_transferred) mutable {
  5125. this->total_bytes_received_ += bytes_transferred;
  5126. if (!check_error_and_transferred_length(ec, bytes_transferred, 1)) return;
  5127. handle_remaining_length(force_move(session_life_keeper), force_move(self));
  5128. }
  5129. );
  5130. }
  5131. bool calc_variable_length(std::size_t& v, std::size_t& multiplier, char buf) {
  5132. v += (buf & 0b01111111) * multiplier;
  5133. multiplier *= 128;
  5134. return multiplier <= 128 * 128 * 128 * 128;
  5135. }
  5136. void handle_remaining_length(any session_life_keeper, this_type_sp self) {
  5137. if (!calc_variable_length(remaining_length_, remaining_length_multiplier_, buf_.front())) {
  5138. call_bad_message_error_handlers();
  5139. return;
  5140. }
  5141. if (buf_.front() & variable_length_continue_flag) {
  5142. socket_->async_read(
  5143. as::buffer(buf_.data(), 1),
  5144. [this, self = force_move(self), session_life_keeper = force_move(session_life_keeper)](
  5145. error_code ec,
  5146. std::size_t bytes_transferred) mutable {
  5147. this->total_bytes_received_ += bytes_transferred;
  5148. if (handle_close_or_error(ec)) {
  5149. return;
  5150. }
  5151. if (bytes_transferred != 1) {
  5152. call_bad_message_error_handlers();
  5153. return;
  5154. }
  5155. handle_remaining_length(force_move(session_life_keeper), force_move(self));
  5156. }
  5157. );
  5158. }
  5159. else {
  5160. auto cpt_opt = get_control_packet_type_with_check(fixed_header_);
  5161. if (!cpt_opt) {
  5162. call_bad_message_error_handlers();
  5163. return;
  5164. }
  5165. auto cpt = cpt_opt.value();
  5166. auto check =
  5167. [&]() -> bool {
  5168. switch (version_) {
  5169. case protocol_version::v3_1_1:
  5170. switch (cpt) {
  5171. case control_packet_type::connect:
  5172. case control_packet_type::publish:
  5173. case control_packet_type::subscribe:
  5174. case control_packet_type::suback:
  5175. case control_packet_type::unsubscribe:
  5176. return check_is_valid_length(cpt, remaining_length_);
  5177. case control_packet_type::connack:
  5178. return remaining_length_ == 2;
  5179. case control_packet_type::puback:
  5180. case control_packet_type::pubrec:
  5181. case control_packet_type::pubrel:
  5182. case control_packet_type::pubcomp:
  5183. case control_packet_type::unsuback:
  5184. return remaining_length_ == sizeof(packet_id_t);
  5185. case control_packet_type::pingreq:
  5186. case control_packet_type::pingresp:
  5187. case control_packet_type::disconnect:
  5188. return remaining_length_ == 0;
  5189. // Even though there is no auth packet type in v3.1.1
  5190. // it's included in the switch case to provide a warning
  5191. // about missing enum values if any are missing.
  5192. case control_packet_type::auth:
  5193. return false;
  5194. }
  5195. return false;
  5196. case protocol_version::v5:
  5197. default:
  5198. switch (cpt) {
  5199. case control_packet_type::connect:
  5200. case control_packet_type::publish:
  5201. case control_packet_type::subscribe:
  5202. case control_packet_type::suback:
  5203. case control_packet_type::unsubscribe:
  5204. case control_packet_type::connack:
  5205. case control_packet_type::puback:
  5206. case control_packet_type::pubrec:
  5207. case control_packet_type::pubrel:
  5208. case control_packet_type::pubcomp:
  5209. case control_packet_type::unsuback:
  5210. case control_packet_type::disconnect:
  5211. case control_packet_type::auth:
  5212. return check_is_valid_length(cpt, remaining_length_);
  5213. case control_packet_type::pingreq:
  5214. case control_packet_type::pingresp:
  5215. return remaining_length_ == 0;
  5216. }
  5217. return false;
  5218. }
  5219. };
  5220. if (!check()) {
  5221. call_protocol_error_handlers();
  5222. return;
  5223. }
  5224. process_payload(force_move(session_life_keeper), force_move(self));
  5225. }
  5226. }
  5227. void process_payload(any session_life_keeper, this_type_sp self) {
  5228. auto control_packet_type = get_control_packet_type(fixed_header_);
  5229. switch (control_packet_type) {
  5230. case control_packet_type::connect:
  5231. (*std::make_shared<process_connect>(*this, remaining_length_ < packet_bulk_read_limit_))
  5232. (force_move(self), force_move(session_life_keeper));
  5233. break;
  5234. case control_packet_type::connack:
  5235. (*std::make_shared<process_connack>(*this, remaining_length_ < packet_bulk_read_limit_))
  5236. (force_move(self), force_move(session_life_keeper));
  5237. break;
  5238. case control_packet_type::publish:
  5239. if (mqtt_connected_) {
  5240. (*std::make_shared<process_publish>(*this, remaining_length_ < packet_bulk_read_limit_))
  5241. (force_move(self), force_move(session_life_keeper));
  5242. }
  5243. else {
  5244. call_protocol_error_handlers();
  5245. }
  5246. break;
  5247. case control_packet_type::puback:
  5248. if (mqtt_connected_) {
  5249. (*std::make_shared<process_puback>(*this, remaining_length_ < packet_bulk_read_limit_))
  5250. (force_move(self), force_move(session_life_keeper));
  5251. }
  5252. else {
  5253. call_protocol_error_handlers();
  5254. }
  5255. break;
  5256. case control_packet_type::pubrec:
  5257. if (mqtt_connected_) {
  5258. (*std::make_shared<process_pubrec>(*this, remaining_length_ < packet_bulk_read_limit_))
  5259. (force_move(self), force_move(session_life_keeper));
  5260. }
  5261. else {
  5262. call_protocol_error_handlers();
  5263. }
  5264. break;
  5265. case control_packet_type::pubrel:
  5266. if (mqtt_connected_) {
  5267. (*std::make_shared<process_pubrel>(*this, remaining_length_ < packet_bulk_read_limit_))
  5268. (force_move(self), force_move(session_life_keeper));
  5269. }
  5270. else {
  5271. call_protocol_error_handlers();
  5272. }
  5273. break;
  5274. case control_packet_type::pubcomp:
  5275. if (mqtt_connected_) {
  5276. (*std::make_shared<process_pubcomp>(*this, remaining_length_ < packet_bulk_read_limit_))
  5277. (force_move(self), force_move(session_life_keeper));
  5278. }
  5279. else {
  5280. call_protocol_error_handlers();
  5281. }
  5282. break;
  5283. case control_packet_type::subscribe:
  5284. if (mqtt_connected_) {
  5285. (*std::make_shared<process_subscribe>(*this, remaining_length_ < packet_bulk_read_limit_))
  5286. (force_move(self), force_move(session_life_keeper));
  5287. }
  5288. else {
  5289. call_protocol_error_handlers();
  5290. }
  5291. break;
  5292. case control_packet_type::suback:
  5293. if (mqtt_connected_) {
  5294. (*std::make_shared<process_suback>(*this, remaining_length_ < packet_bulk_read_limit_))
  5295. (force_move(self), force_move(session_life_keeper));
  5296. }
  5297. else {
  5298. call_protocol_error_handlers();
  5299. }
  5300. break;
  5301. case control_packet_type::unsubscribe:
  5302. if (mqtt_connected_) {
  5303. (*std::make_shared<process_unsubscribe>(*this, remaining_length_ < packet_bulk_read_limit_))
  5304. (force_move(self), force_move(session_life_keeper));
  5305. }
  5306. else {
  5307. call_protocol_error_handlers();
  5308. }
  5309. break;
  5310. case control_packet_type::unsuback:
  5311. if (mqtt_connected_) {
  5312. (*std::make_shared<process_unsuback>(*this, remaining_length_ < packet_bulk_read_limit_))
  5313. (force_move(self), force_move(session_life_keeper));
  5314. }
  5315. else {
  5316. call_protocol_error_handlers();
  5317. }
  5318. break;
  5319. case control_packet_type::pingreq:
  5320. if (mqtt_connected_) {
  5321. process_pingreq(force_move(session_life_keeper));
  5322. }
  5323. else {
  5324. call_protocol_error_handlers();
  5325. }
  5326. break;
  5327. case control_packet_type::pingresp:
  5328. if (mqtt_connected_) {
  5329. process_pingresp(force_move(session_life_keeper));
  5330. }
  5331. else {
  5332. call_protocol_error_handlers();
  5333. }
  5334. break;
  5335. case control_packet_type::disconnect:
  5336. (*std::make_shared<process_disconnect>(*this, remaining_length_ < packet_bulk_read_limit_))
  5337. (force_move(self), force_move(session_life_keeper));
  5338. break;
  5339. case control_packet_type::auth:
  5340. (*std::make_shared<process_auth>(*this, remaining_length_ < packet_bulk_read_limit_))
  5341. (force_move(self), force_move(session_life_keeper));
  5342. break;
  5343. default:
  5344. break;
  5345. }
  5346. }
  5347. using parse_handler_variant =
  5348. variant<
  5349. std::conditional_t<sizeof(std::size_t) == 4, std::nullptr_t, std::size_t>,
  5350. std::uint32_t,
  5351. std::uint16_t,
  5352. buffer,
  5353. v5::properties
  5354. >;
  5355. using parse_handler =
  5356. std::function<
  5357. void(
  5358. this_type_sp&& spep,
  5359. any&& session_life_keeper,
  5360. parse_handler_variant,
  5361. buffer
  5362. )
  5363. >;
  5364. // primitive read functions
  5365. void process_nbytes(
  5366. this_type_sp&& self,
  5367. any&& session_life_keeper,
  5368. buffer buf,
  5369. std::size_t size,
  5370. parse_handler&& handler
  5371. ) {
  5372. if (remaining_length_ < size) {
  5373. call_protocol_error_handlers();
  5374. return;
  5375. }
  5376. remaining_length_ -= size;
  5377. if (buf.empty()) {
  5378. auto spa = make_shared_ptr_array(size);
  5379. auto ptr = spa.get();
  5380. socket_->async_read(
  5381. as::buffer(ptr, size),
  5382. [
  5383. this,
  5384. self = force_move(self),
  5385. session_life_keeper = force_move(session_life_keeper),
  5386. handler = force_move(handler),
  5387. buf = buffer(string_view(ptr, size), force_move(spa))
  5388. ]
  5389. (error_code ec,
  5390. std::size_t bytes_transferred) mutable {
  5391. this->total_bytes_received_ += bytes_transferred;
  5392. if (!check_error_and_transferred_length(ec, bytes_transferred, buf.size())) return;
  5393. handler(
  5394. force_move(self),
  5395. force_move(session_life_keeper),
  5396. force_move(buf),
  5397. buffer()
  5398. );
  5399. }
  5400. );
  5401. }
  5402. else {
  5403. if (buf.size() < size) {
  5404. call_protocol_error_handlers();
  5405. return;
  5406. }
  5407. handler(
  5408. force_move(self),
  5409. force_move(session_life_keeper),
  5410. buf.substr(0, size),
  5411. buf.substr(size)
  5412. );
  5413. }
  5414. }
  5415. template <std::size_t Bytes>
  5416. void process_fixed_length(
  5417. this_type_sp&& self,
  5418. any&& session_life_keeper,
  5419. buffer buf,
  5420. parse_handler&& handler
  5421. ) {
  5422. if (remaining_length_ < Bytes) {
  5423. call_protocol_error_handlers();
  5424. return;
  5425. }
  5426. remaining_length_ -= Bytes;
  5427. if (buf.empty()) {
  5428. socket_->async_read(
  5429. as::buffer(buf_.data(), Bytes),
  5430. [
  5431. this,
  5432. self = force_move(self),
  5433. session_life_keeper = force_move(session_life_keeper),
  5434. handler = force_move(handler)
  5435. ]
  5436. (error_code ec,
  5437. std::size_t bytes_transferred) mutable {
  5438. this->total_bytes_received_ += bytes_transferred;
  5439. if (!check_error_and_transferred_length(ec, bytes_transferred, Bytes)) return;
  5440. handler(
  5441. force_move(self),
  5442. force_move(session_life_keeper),
  5443. make_two_or_four_byte<Bytes>::apply(
  5444. buf_.data(),
  5445. std::next(buf_.data(), boost::numeric_cast<buffer::difference_type>(Bytes))
  5446. ),
  5447. buffer()
  5448. );
  5449. }
  5450. );
  5451. }
  5452. else {
  5453. auto val =
  5454. make_two_or_four_byte<Bytes>::apply(
  5455. buf.data(),
  5456. std::next(buf.data(), boost::numeric_cast<buffer::difference_type>(Bytes))
  5457. );
  5458. buf.remove_prefix(Bytes);
  5459. handler(
  5460. force_move(self),
  5461. force_move(session_life_keeper),
  5462. val,
  5463. force_move(buf)
  5464. );
  5465. }
  5466. }
  5467. // This function isn't used for remaining lengh.
  5468. void process_variable_length(
  5469. this_type_sp&& self,
  5470. any&& session_life_keeper,
  5471. buffer buf,
  5472. parse_handler&& handler
  5473. ) {
  5474. process_variable_length_impl(
  5475. force_move(self),
  5476. force_move(session_life_keeper),
  5477. force_move(buf),
  5478. force_move(handler),
  5479. 0,
  5480. 1
  5481. );
  5482. }
  5483. void process_variable_length_impl(
  5484. this_type_sp&& self,
  5485. any&& session_life_keeper,
  5486. buffer buf,
  5487. parse_handler&& handler,
  5488. std::size_t size,
  5489. std::size_t multiplier
  5490. ) {
  5491. if (remaining_length_ == 0) {
  5492. call_protocol_error_handlers();
  5493. return;
  5494. }
  5495. --remaining_length_;
  5496. // I use rvalue reference parameter to reduce move constructor calling.
  5497. // This is a local lambda expression invoked from this function, so
  5498. // I can control all callers.
  5499. auto proc =
  5500. [this]
  5501. (
  5502. this_type_sp&& self,
  5503. any&& session_life_keeper,
  5504. buffer&& buf,
  5505. auto&& handler,
  5506. std::size_t size,
  5507. std::size_t multiplier
  5508. ) mutable {
  5509. if (!calc_variable_length(size, multiplier, buf.front())) {
  5510. call_protocol_error_handlers();
  5511. return;
  5512. }
  5513. if (buf.front() & variable_length_continue_flag) {
  5514. BOOST_ASSERT(!buf.empty());
  5515. buf.remove_prefix(1);
  5516. process_variable_length_impl(
  5517. force_move(self),
  5518. force_move(session_life_keeper),
  5519. force_move(buf),
  5520. std::forward<decltype(handler)>(handler),
  5521. size,
  5522. multiplier
  5523. );
  5524. }
  5525. else {
  5526. buf.remove_prefix(1);
  5527. handler(
  5528. force_move(self),
  5529. force_move(session_life_keeper),
  5530. size,
  5531. force_move(buf)
  5532. );
  5533. }
  5534. };
  5535. if (buf.empty()) {
  5536. socket_->async_read(
  5537. as::buffer(buf_.data(), 1),
  5538. [
  5539. this,
  5540. self = force_move(self),
  5541. session_life_keeper = force_move(session_life_keeper),
  5542. handler = force_move(handler),
  5543. size,
  5544. multiplier,
  5545. proc = force_move(proc)
  5546. ]
  5547. (error_code ec,
  5548. std::size_t bytes_transferred) mutable {
  5549. this->total_bytes_received_ += bytes_transferred;
  5550. if (!check_error_and_transferred_length(ec, bytes_transferred, 1)) return;
  5551. proc(
  5552. force_move(self),
  5553. force_move(session_life_keeper),
  5554. buffer(string_view(buf_.data(), 1)), // buf_'s lifetime is handled by `self`
  5555. force_move(handler),
  5556. size,
  5557. multiplier
  5558. );
  5559. }
  5560. );
  5561. }
  5562. else {
  5563. proc(
  5564. force_move(self),
  5565. force_move(session_life_keeper),
  5566. force_move(buf),
  5567. force_move(handler),
  5568. size,
  5569. multiplier
  5570. );
  5571. }
  5572. }
  5573. void process_packet_id(
  5574. this_type_sp&& self,
  5575. any&& session_life_keeper,
  5576. buffer buf,
  5577. parse_handler&& handler
  5578. ) {
  5579. process_fixed_length<sizeof(packet_id_t)>(
  5580. force_move(self),
  5581. force_move(session_life_keeper),
  5582. force_move(buf),
  5583. [
  5584. this,
  5585. handler = force_move(handler)
  5586. ]
  5587. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5588. auto packet_id = variant_get<packet_id_t>(var);
  5589. if (packet_id == 0) {
  5590. call_protocol_error_handlers();
  5591. return;
  5592. }
  5593. handler(
  5594. force_move(self),
  5595. force_move(session_life_keeper),
  5596. static_cast<packet_id_t>(packet_id),
  5597. force_move(buf)
  5598. );
  5599. }
  5600. );
  5601. }
  5602. void process_binary(
  5603. this_type_sp&& self,
  5604. any&& session_life_keeper,
  5605. buffer buf,
  5606. parse_handler&& handler
  5607. ) {
  5608. if (remaining_length_ < 2) {
  5609. call_protocol_error_handlers();
  5610. return;
  5611. }
  5612. process_fixed_length<2>(
  5613. force_move(self),
  5614. force_move(session_life_keeper),
  5615. force_move(buf),
  5616. [
  5617. this,
  5618. handler = force_move(handler)
  5619. ]
  5620. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5621. auto size = variant_get<typename two_or_four_byte_type<2>::type>(var);
  5622. if (remaining_length_ < size) {
  5623. call_protocol_error_handlers();
  5624. return;
  5625. }
  5626. process_nbytes(
  5627. force_move(self),
  5628. force_move(session_life_keeper),
  5629. force_move(buf),
  5630. size,
  5631. force_move(handler)
  5632. );
  5633. }
  5634. );
  5635. }
  5636. void process_string(
  5637. this_type_sp&& self,
  5638. any&& session_life_keeper,
  5639. buffer buf,
  5640. parse_handler&& handler
  5641. ) {
  5642. process_binary(
  5643. force_move(self),
  5644. force_move(session_life_keeper),
  5645. force_move(buf),
  5646. [this, handler = force_move(handler)]
  5647. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5648. auto& str = variant_get<buffer>(var);
  5649. auto r = utf8string::validate_contents(str);
  5650. if (r != utf8string::validation::well_formed) {
  5651. call_bad_message_error_handlers();
  5652. return;
  5653. }
  5654. handler(
  5655. force_move(self),
  5656. force_move(session_life_keeper),
  5657. force_move(str),
  5658. force_move(buf)
  5659. );
  5660. }
  5661. );
  5662. }
  5663. void process_properties(
  5664. this_type_sp&& self,
  5665. any&& session_life_keeper,
  5666. buffer buf,
  5667. parse_handler&& handler
  5668. ) {
  5669. process_variable_length(
  5670. force_move(self),
  5671. force_move(session_life_keeper),
  5672. force_move(buf),
  5673. [
  5674. this,
  5675. handler = force_move(handler)
  5676. ]
  5677. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5678. auto property_length = variant_get<std::size_t>(var);
  5679. if (property_length > remaining_length_) {
  5680. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  5681. call_protocol_error_handlers();
  5682. return;
  5683. }
  5684. if (property_length == 0) {
  5685. handler(
  5686. force_move(self),
  5687. force_move(session_life_keeper),
  5688. v5::properties(),
  5689. force_move(buf)
  5690. );
  5691. return;
  5692. }
  5693. if (buf.empty()) {
  5694. struct spa_address_len {
  5695. shared_ptr_array spa;
  5696. char* address;
  5697. std::size_t len;
  5698. };
  5699. auto result =
  5700. [&] () -> spa_address_len {
  5701. if (property_length < props_bulk_read_limit_) {
  5702. auto spa = make_shared_ptr_array(property_length);
  5703. auto ptr = spa.get();
  5704. return
  5705. {
  5706. force_move(spa),
  5707. ptr,
  5708. property_length
  5709. };
  5710. }
  5711. return
  5712. {
  5713. nullptr,
  5714. buf_.data(),
  5715. 1
  5716. };
  5717. } ();
  5718. socket_->async_read(
  5719. as::buffer(result.address, result.len),
  5720. [
  5721. this,
  5722. handler = force_move(handler),
  5723. self = force_move(self),
  5724. session_life_keeper = force_move(session_life_keeper),
  5725. property_length,
  5726. result
  5727. ]
  5728. (error_code ec, std::size_t bytes_transferred) mutable {
  5729. this->total_bytes_received_ += bytes_transferred;
  5730. if (!check_error_and_transferred_length(ec, bytes_transferred, result.len)) return;
  5731. process_property_id(
  5732. force_move(self),
  5733. force_move(session_life_keeper),
  5734. buffer(string_view(result.address, result.len), result.spa),
  5735. property_length,
  5736. v5::properties(),
  5737. force_move(handler)
  5738. );
  5739. }
  5740. );
  5741. }
  5742. else {
  5743. process_property_id(
  5744. force_move(self),
  5745. force_move(session_life_keeper),
  5746. force_move(buf),
  5747. property_length,
  5748. v5::properties(),
  5749. force_move(handler)
  5750. );
  5751. }
  5752. }
  5753. );
  5754. }
  5755. void process_property_id(
  5756. this_type_sp&& self,
  5757. any&& session_life_keeper,
  5758. buffer buf,
  5759. std::size_t property_length_rest,
  5760. v5::properties props,
  5761. parse_handler&& handler
  5762. ) {
  5763. if (property_length_rest == 0) {
  5764. handler(
  5765. force_move(self),
  5766. force_move(session_life_keeper),
  5767. force_move(props),
  5768. force_move(buf)
  5769. );
  5770. return;
  5771. }
  5772. --remaining_length_;
  5773. if (buf.empty()) {
  5774. socket_->async_read(
  5775. as::buffer(buf_.data(), 1),
  5776. [
  5777. this,
  5778. self = force_move(self),
  5779. session_life_keeper = force_move(session_life_keeper),
  5780. props = force_move(props),
  5781. handler = force_move(handler),
  5782. property_length_rest
  5783. ]
  5784. (error_code ec,
  5785. std::size_t bytes_transferred) mutable {
  5786. this->total_bytes_received_ += bytes_transferred;
  5787. if (!check_error_and_transferred_length(ec, bytes_transferred, 1)) return;
  5788. process_property_body(
  5789. force_move(self),
  5790. force_move(session_life_keeper),
  5791. buffer(),
  5792. static_cast<v5::property::id>(buf_.front()),
  5793. property_length_rest - 1,
  5794. force_move(props),
  5795. force_move(handler)
  5796. );
  5797. }
  5798. );
  5799. }
  5800. else {
  5801. auto id = static_cast<v5::property::id>(buf.front());
  5802. buf.remove_prefix(1);
  5803. process_property_body(
  5804. force_move(self),
  5805. force_move(session_life_keeper),
  5806. force_move(buf),
  5807. id,
  5808. property_length_rest - 1,
  5809. force_move(props),
  5810. force_move(handler)
  5811. );
  5812. }
  5813. }
  5814. void process_property_body(
  5815. this_type_sp&& self,
  5816. any&& session_life_keeper,
  5817. buffer buf,
  5818. v5::property::id id,
  5819. std::size_t property_length_rest,
  5820. v5::properties props,
  5821. parse_handler&& handler
  5822. ) {
  5823. static constexpr std::size_t length_bytes = 2;
  5824. if (property_length_rest == 0) {
  5825. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  5826. call_protocol_error_handlers();
  5827. return;
  5828. }
  5829. switch (id) {
  5830. case v5::property::id::payload_format_indicator: {
  5831. static constexpr std::size_t len = 1;
  5832. if (property_length_rest < len) {
  5833. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  5834. call_protocol_error_handlers();
  5835. return;
  5836. }
  5837. process_nbytes(
  5838. force_move(self),
  5839. force_move(session_life_keeper),
  5840. force_move(buf),
  5841. len,
  5842. [
  5843. this,
  5844. props = force_move(props),
  5845. handler = force_move(handler),
  5846. rest = property_length_rest - len
  5847. ]
  5848. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5849. auto& body = variant_get<buffer>(var);
  5850. props.emplace_back(
  5851. v5::property::payload_format_indicator(body.begin(), body.end())
  5852. );
  5853. process_property_id(
  5854. force_move(self),
  5855. force_move(session_life_keeper),
  5856. force_move(buf),
  5857. rest,
  5858. force_move(props),
  5859. force_move(handler)
  5860. );
  5861. }
  5862. );
  5863. } break;
  5864. case v5::property::id::message_expiry_interval: {
  5865. static constexpr std::size_t len = 4;
  5866. if (property_length_rest < len) {
  5867. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  5868. call_protocol_error_handlers();
  5869. return;
  5870. }
  5871. process_nbytes(
  5872. force_move(self),
  5873. force_move(session_life_keeper),
  5874. force_move(buf),
  5875. len,
  5876. [
  5877. this,
  5878. props = force_move(props),
  5879. handler = force_move(handler),
  5880. rest = property_length_rest - len
  5881. ]
  5882. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5883. auto& body = variant_get<buffer>(var);
  5884. props.emplace_back(
  5885. v5::property::message_expiry_interval(body.begin(), body.end())
  5886. );
  5887. process_property_id(
  5888. force_move(self),
  5889. force_move(session_life_keeper),
  5890. force_move(buf),
  5891. rest,
  5892. force_move(props),
  5893. force_move(handler)
  5894. );
  5895. }
  5896. );
  5897. } break;
  5898. case v5::property::id::content_type: {
  5899. process_string(
  5900. force_move(self),
  5901. force_move(session_life_keeper),
  5902. force_move(buf),
  5903. [
  5904. this,
  5905. props = force_move(props),
  5906. handler = force_move(handler),
  5907. property_length_rest
  5908. ]
  5909. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5910. auto& body = variant_get<buffer>(var);
  5911. auto rest = property_length_rest - length_bytes - body.size();
  5912. props.emplace_back(
  5913. v5::property::content_type(force_move(body), true)
  5914. );
  5915. process_property_id(
  5916. force_move(self),
  5917. force_move(session_life_keeper),
  5918. force_move(buf),
  5919. rest,
  5920. force_move(props),
  5921. force_move(handler)
  5922. );
  5923. }
  5924. );
  5925. } break;
  5926. case v5::property::id::response_topic: {
  5927. process_string(
  5928. force_move(self),
  5929. force_move(session_life_keeper),
  5930. force_move(buf),
  5931. [
  5932. this,
  5933. props = force_move(props),
  5934. handler = force_move(handler),
  5935. property_length_rest
  5936. ]
  5937. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5938. auto& body = variant_get<buffer>(var);
  5939. auto rest = property_length_rest - length_bytes - body.size();
  5940. props.emplace_back(
  5941. v5::property::response_topic(force_move(body), true)
  5942. );
  5943. process_property_id(
  5944. force_move(self),
  5945. force_move(session_life_keeper),
  5946. force_move(buf),
  5947. rest,
  5948. force_move(props),
  5949. force_move(handler)
  5950. );
  5951. }
  5952. );
  5953. } break;
  5954. case v5::property::id::correlation_data: {
  5955. process_binary(
  5956. force_move(self),
  5957. force_move(session_life_keeper),
  5958. force_move(buf),
  5959. [
  5960. this,
  5961. props = force_move(props),
  5962. handler = force_move(handler),
  5963. property_length_rest
  5964. ]
  5965. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5966. auto& body = variant_get<buffer>(var);
  5967. auto rest = property_length_rest - length_bytes - body.size();
  5968. props.emplace_back(
  5969. v5::property::correlation_data(force_move(body))
  5970. );
  5971. process_property_id(
  5972. force_move(self),
  5973. force_move(session_life_keeper),
  5974. force_move(buf),
  5975. rest,
  5976. force_move(props),
  5977. force_move(handler)
  5978. );
  5979. }
  5980. );
  5981. } break;
  5982. case v5::property::id::subscription_identifier: {
  5983. process_variable_length(
  5984. force_move(self),
  5985. force_move(session_life_keeper),
  5986. force_move(buf),
  5987. [
  5988. this,
  5989. props = force_move(props),
  5990. handler = force_move(handler),
  5991. property_length_rest,
  5992. remaining_length_before = remaining_length_
  5993. ]
  5994. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  5995. auto size = variant_get<std::size_t>(var);
  5996. auto consumed = remaining_length_before - remaining_length_;
  5997. auto rest = property_length_rest - consumed;
  5998. props.emplace_back(
  5999. v5::property::subscription_identifier(size)
  6000. );
  6001. process_property_id(
  6002. force_move(self),
  6003. force_move(session_life_keeper),
  6004. force_move(buf),
  6005. rest,
  6006. force_move(props),
  6007. force_move(handler)
  6008. );
  6009. }
  6010. );
  6011. } break;
  6012. case v5::property::id::session_expiry_interval: {
  6013. static constexpr std::size_t len = 4;
  6014. if (property_length_rest < len) {
  6015. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6016. call_protocol_error_handlers();
  6017. return;
  6018. }
  6019. process_nbytes(
  6020. force_move(self),
  6021. force_move(session_life_keeper),
  6022. force_move(buf),
  6023. len,
  6024. [
  6025. this,
  6026. props = force_move(props),
  6027. handler = force_move(handler),
  6028. rest = property_length_rest - len
  6029. ]
  6030. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6031. auto& body = variant_get<buffer>(var);
  6032. props.emplace_back(
  6033. v5::property::session_expiry_interval(body.begin(), body.end())
  6034. );
  6035. process_property_id(
  6036. force_move(self),
  6037. force_move(session_life_keeper),
  6038. force_move(buf),
  6039. rest,
  6040. force_move(props),
  6041. force_move(handler)
  6042. );
  6043. }
  6044. );
  6045. } break;
  6046. case v5::property::id::assigned_client_identifier: {
  6047. process_string(
  6048. force_move(self),
  6049. force_move(session_life_keeper),
  6050. force_move(buf),
  6051. [
  6052. this,
  6053. props = force_move(props),
  6054. handler = force_move(handler),
  6055. property_length_rest
  6056. ]
  6057. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6058. auto& body = variant_get<buffer>(var);
  6059. auto rest = property_length_rest - length_bytes - body.size();
  6060. props.emplace_back(
  6061. v5::property::assigned_client_identifier(force_move(body), true)
  6062. );
  6063. process_property_id(
  6064. force_move(self),
  6065. force_move(session_life_keeper),
  6066. force_move(buf),
  6067. rest,
  6068. force_move(props),
  6069. force_move(handler)
  6070. );
  6071. }
  6072. );
  6073. } break;
  6074. case v5::property::id::server_keep_alive: {
  6075. static constexpr std::size_t len = 2;
  6076. if (property_length_rest < len) {
  6077. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6078. call_protocol_error_handlers();
  6079. return;
  6080. }
  6081. process_nbytes(
  6082. force_move(self),
  6083. force_move(session_life_keeper),
  6084. force_move(buf),
  6085. len,
  6086. [
  6087. this,
  6088. props = force_move(props),
  6089. handler = force_move(handler),
  6090. rest = property_length_rest - len
  6091. ]
  6092. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6093. auto& body = variant_get<buffer>(var);
  6094. props.emplace_back(
  6095. v5::property::server_keep_alive(body.begin(), body.end())
  6096. );
  6097. process_property_id(
  6098. force_move(self),
  6099. force_move(session_life_keeper),
  6100. force_move(buf),
  6101. rest,
  6102. force_move(props),
  6103. force_move(handler)
  6104. );
  6105. }
  6106. );
  6107. } break;
  6108. case v5::property::id::authentication_method: {
  6109. process_string(
  6110. force_move(self),
  6111. force_move(session_life_keeper),
  6112. force_move(buf),
  6113. [
  6114. this,
  6115. props = force_move(props),
  6116. handler = force_move(handler),
  6117. property_length_rest
  6118. ]
  6119. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6120. auto& body = variant_get<buffer>(var);
  6121. auto rest = property_length_rest - length_bytes - body.size();
  6122. props.emplace_back(
  6123. v5::property::authentication_method(force_move(body), true)
  6124. );
  6125. process_property_id(
  6126. force_move(self),
  6127. force_move(session_life_keeper),
  6128. force_move(buf),
  6129. rest,
  6130. force_move(props),
  6131. force_move(handler)
  6132. );
  6133. }
  6134. );
  6135. } break;
  6136. case v5::property::id::authentication_data: {
  6137. process_binary(
  6138. force_move(self),
  6139. force_move(session_life_keeper),
  6140. force_move(buf),
  6141. [
  6142. this,
  6143. props = force_move(props),
  6144. handler = force_move(handler),
  6145. property_length_rest
  6146. ]
  6147. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6148. auto& body = variant_get<buffer>(var);
  6149. auto rest = property_length_rest - length_bytes - body.size();
  6150. props.emplace_back(
  6151. v5::property::authentication_data(force_move(body))
  6152. );
  6153. process_property_id(
  6154. force_move(self),
  6155. force_move(session_life_keeper),
  6156. force_move(buf),
  6157. rest,
  6158. force_move(props),
  6159. force_move(handler)
  6160. );
  6161. }
  6162. );
  6163. } break;
  6164. case v5::property::id::request_problem_information: {
  6165. static constexpr std::size_t len = 1;
  6166. if (property_length_rest < len) {
  6167. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6168. call_protocol_error_handlers();
  6169. return;
  6170. }
  6171. process_nbytes(
  6172. force_move(self),
  6173. force_move(session_life_keeper),
  6174. force_move(buf),
  6175. len,
  6176. [
  6177. this,
  6178. props = force_move(props),
  6179. handler = force_move(handler),
  6180. rest = property_length_rest - len
  6181. ]
  6182. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6183. auto& body = variant_get<buffer>(var);
  6184. props.emplace_back(
  6185. v5::property::request_problem_information(body.begin(), body.end())
  6186. );
  6187. process_property_id(
  6188. force_move(self),
  6189. force_move(session_life_keeper),
  6190. force_move(buf),
  6191. rest,
  6192. force_move(props),
  6193. force_move(handler)
  6194. );
  6195. }
  6196. );
  6197. } break;
  6198. case v5::property::id::will_delay_interval: {
  6199. static constexpr std::size_t len = 4;
  6200. if (property_length_rest < len) {
  6201. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6202. call_protocol_error_handlers();
  6203. return;
  6204. }
  6205. process_nbytes(
  6206. force_move(self),
  6207. force_move(session_life_keeper),
  6208. force_move(buf),
  6209. len,
  6210. [
  6211. this,
  6212. props = force_move(props),
  6213. handler = force_move(handler),
  6214. rest = property_length_rest - len
  6215. ]
  6216. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6217. auto& body = variant_get<buffer>(var);
  6218. props.emplace_back(
  6219. v5::property::will_delay_interval(body.begin(), body.end())
  6220. );
  6221. process_property_id(
  6222. force_move(self),
  6223. force_move(session_life_keeper),
  6224. force_move(buf),
  6225. rest,
  6226. force_move(props),
  6227. force_move(handler)
  6228. );
  6229. }
  6230. );
  6231. } break;
  6232. case v5::property::id::request_response_information: {
  6233. static constexpr std::size_t len = 1;
  6234. if (property_length_rest < len) {
  6235. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6236. call_protocol_error_handlers();
  6237. return;
  6238. }
  6239. process_nbytes(
  6240. force_move(self),
  6241. force_move(session_life_keeper),
  6242. force_move(buf),
  6243. len,
  6244. [
  6245. this,
  6246. props = force_move(props),
  6247. handler = force_move(handler),
  6248. rest = property_length_rest - len
  6249. ]
  6250. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6251. auto& body = variant_get<buffer>(var);
  6252. props.emplace_back(
  6253. v5::property::request_response_information(body.begin(), body.end())
  6254. );
  6255. process_property_id(
  6256. force_move(self),
  6257. force_move(session_life_keeper),
  6258. force_move(buf),
  6259. rest,
  6260. force_move(props),
  6261. force_move(handler)
  6262. );
  6263. }
  6264. );
  6265. } break;
  6266. case v5::property::id::response_information: {
  6267. process_string(
  6268. force_move(self),
  6269. force_move(session_life_keeper),
  6270. force_move(buf),
  6271. [
  6272. this,
  6273. props = force_move(props),
  6274. handler = force_move(handler),
  6275. property_length_rest
  6276. ]
  6277. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6278. auto& body = variant_get<buffer>(var);
  6279. auto rest = property_length_rest - length_bytes - body.size();
  6280. props.emplace_back(
  6281. v5::property::response_information(force_move(body), true)
  6282. );
  6283. process_property_id(
  6284. force_move(self),
  6285. force_move(session_life_keeper),
  6286. force_move(buf),
  6287. rest,
  6288. force_move(props),
  6289. force_move(handler)
  6290. );
  6291. }
  6292. );
  6293. } break;
  6294. case v5::property::id::server_reference: {
  6295. process_string(
  6296. force_move(self),
  6297. force_move(session_life_keeper),
  6298. force_move(buf),
  6299. [
  6300. this,
  6301. props = force_move(props),
  6302. handler = force_move(handler),
  6303. property_length_rest
  6304. ]
  6305. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6306. auto& body = variant_get<buffer>(var);
  6307. auto rest = property_length_rest - length_bytes - body.size();
  6308. props.emplace_back(
  6309. v5::property::server_reference(force_move(body), true)
  6310. );
  6311. process_property_id(
  6312. force_move(self),
  6313. force_move(session_life_keeper),
  6314. force_move(buf),
  6315. rest,
  6316. force_move(props),
  6317. force_move(handler)
  6318. );
  6319. }
  6320. );
  6321. } break;
  6322. case v5::property::id::reason_string: {
  6323. process_string(
  6324. force_move(self),
  6325. force_move(session_life_keeper),
  6326. force_move(buf),
  6327. [
  6328. this,
  6329. props = force_move(props),
  6330. handler = force_move(handler),
  6331. property_length_rest
  6332. ]
  6333. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6334. auto& body = variant_get<buffer>(var);
  6335. auto rest = property_length_rest - length_bytes - body.size();
  6336. props.emplace_back(
  6337. v5::property::reason_string(force_move(body), true)
  6338. );
  6339. process_property_id(
  6340. force_move(self),
  6341. force_move(session_life_keeper),
  6342. force_move(buf),
  6343. rest,
  6344. force_move(props),
  6345. force_move(handler)
  6346. );
  6347. }
  6348. );
  6349. } break;
  6350. case v5::property::id::receive_maximum: {
  6351. static constexpr std::size_t len = 2;
  6352. if (property_length_rest < len) {
  6353. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6354. call_protocol_error_handlers();
  6355. return;
  6356. }
  6357. process_nbytes(
  6358. force_move(self),
  6359. force_move(session_life_keeper),
  6360. force_move(buf),
  6361. len,
  6362. [
  6363. this,
  6364. props = force_move(props),
  6365. handler = force_move(handler),
  6366. rest = property_length_rest - len
  6367. ]
  6368. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6369. auto& body = variant_get<buffer>(var);
  6370. props.emplace_back(
  6371. v5::property::receive_maximum(body.begin(), body.end())
  6372. );
  6373. process_property_id(
  6374. force_move(self),
  6375. force_move(session_life_keeper),
  6376. force_move(buf),
  6377. rest,
  6378. force_move(props),
  6379. force_move(handler)
  6380. );
  6381. }
  6382. );
  6383. } break;
  6384. case v5::property::id::topic_alias_maximum: {
  6385. static constexpr std::size_t len = 2;
  6386. if (property_length_rest < len) {
  6387. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6388. call_protocol_error_handlers();
  6389. return;
  6390. }
  6391. process_nbytes(
  6392. force_move(self),
  6393. force_move(session_life_keeper),
  6394. force_move(buf),
  6395. len,
  6396. [
  6397. this,
  6398. props = force_move(props),
  6399. handler = force_move(handler),
  6400. rest = property_length_rest - len
  6401. ]
  6402. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6403. auto& body = variant_get<buffer>(var);
  6404. props.emplace_back(
  6405. v5::property::topic_alias_maximum(body.begin(), body.end())
  6406. );
  6407. process_property_id(
  6408. force_move(self),
  6409. force_move(session_life_keeper),
  6410. force_move(buf),
  6411. rest,
  6412. force_move(props),
  6413. force_move(handler)
  6414. );
  6415. }
  6416. );
  6417. } break;
  6418. case v5::property::id::topic_alias: {
  6419. static constexpr std::size_t len = 2;
  6420. if (property_length_rest < len) {
  6421. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6422. call_protocol_error_handlers();
  6423. return;
  6424. }
  6425. process_nbytes(
  6426. force_move(self),
  6427. force_move(session_life_keeper),
  6428. force_move(buf),
  6429. len,
  6430. [
  6431. this,
  6432. props = force_move(props),
  6433. handler = force_move(handler),
  6434. rest = property_length_rest - len
  6435. ]
  6436. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6437. auto& body = variant_get<buffer>(var);
  6438. props.emplace_back(
  6439. v5::property::topic_alias(body.begin(), body.end())
  6440. );
  6441. process_property_id(
  6442. force_move(self),
  6443. force_move(session_life_keeper),
  6444. force_move(buf),
  6445. rest,
  6446. force_move(props),
  6447. force_move(handler)
  6448. );
  6449. }
  6450. );
  6451. } break;
  6452. case v5::property::id::maximum_qos: {
  6453. static constexpr std::size_t len = 1;
  6454. if (property_length_rest < len) {
  6455. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6456. call_protocol_error_handlers();
  6457. return;
  6458. }
  6459. process_nbytes(
  6460. force_move(self),
  6461. force_move(session_life_keeper),
  6462. force_move(buf),
  6463. len,
  6464. [
  6465. this,
  6466. props = force_move(props),
  6467. handler = force_move(handler),
  6468. rest = property_length_rest - len
  6469. ]
  6470. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6471. auto& body = variant_get<buffer>(var);
  6472. props.emplace_back(
  6473. v5::property::maximum_qos(body.begin(), body.end())
  6474. );
  6475. process_property_id(
  6476. force_move(self),
  6477. force_move(session_life_keeper),
  6478. force_move(buf),
  6479. rest,
  6480. force_move(props),
  6481. force_move(handler)
  6482. );
  6483. }
  6484. );
  6485. } break;
  6486. case v5::property::id::retain_available: {
  6487. static constexpr std::size_t len = 1;
  6488. if (property_length_rest < len) {
  6489. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6490. call_protocol_error_handlers();
  6491. return;
  6492. }
  6493. process_nbytes(
  6494. force_move(self),
  6495. force_move(session_life_keeper),
  6496. force_move(buf),
  6497. len,
  6498. [
  6499. this,
  6500. props = force_move(props),
  6501. handler = force_move(handler),
  6502. rest = property_length_rest - len
  6503. ]
  6504. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6505. auto& body = variant_get<buffer>(var);
  6506. props.emplace_back(
  6507. v5::property::retain_available(body.begin(), body.end())
  6508. );
  6509. process_property_id(
  6510. force_move(self),
  6511. force_move(session_life_keeper),
  6512. force_move(buf),
  6513. rest,
  6514. force_move(props),
  6515. force_move(handler)
  6516. );
  6517. }
  6518. );
  6519. } break;
  6520. case v5::property::id::user_property: {
  6521. process_string(
  6522. force_move(self),
  6523. force_move(session_life_keeper),
  6524. force_move(buf),
  6525. [
  6526. this,
  6527. props = force_move(props),
  6528. handler = force_move(handler),
  6529. property_length_rest
  6530. ]
  6531. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6532. auto& key = variant_get<buffer>(var);
  6533. auto rest = property_length_rest - length_bytes - key.size();
  6534. process_string(
  6535. force_move(self),
  6536. force_move(session_life_keeper),
  6537. force_move(buf),
  6538. [
  6539. this,
  6540. props = force_move(props),
  6541. handler = force_move(handler),
  6542. key = force_move(key),
  6543. property_length_rest = rest
  6544. ]
  6545. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6546. auto& val = variant_get<buffer>(var);
  6547. auto rest = property_length_rest - length_bytes - val.size();
  6548. props.emplace_back(
  6549. v5::property::user_property(
  6550. force_move(key),
  6551. force_move(val),
  6552. true,
  6553. true
  6554. )
  6555. );
  6556. process_property_id(
  6557. force_move(self),
  6558. force_move(session_life_keeper),
  6559. force_move(buf),
  6560. rest,
  6561. force_move(props),
  6562. force_move(handler)
  6563. );
  6564. }
  6565. );
  6566. }
  6567. );
  6568. } break;
  6569. case v5::property::id::maximum_packet_size: {
  6570. static constexpr std::size_t len = 4;
  6571. if (property_length_rest < len) {
  6572. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6573. call_protocol_error_handlers();
  6574. return;
  6575. }
  6576. process_nbytes(
  6577. force_move(self),
  6578. force_move(session_life_keeper),
  6579. force_move(buf),
  6580. len,
  6581. [
  6582. this,
  6583. props = force_move(props),
  6584. handler = force_move(handler),
  6585. rest = property_length_rest - len
  6586. ]
  6587. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6588. auto& body = variant_get<buffer>(var);
  6589. props.emplace_back(
  6590. v5::property::maximum_packet_size(body.begin(), body.end())
  6591. );
  6592. process_property_id(
  6593. force_move(self),
  6594. force_move(session_life_keeper),
  6595. force_move(buf),
  6596. rest,
  6597. force_move(props),
  6598. force_move(handler)
  6599. );
  6600. }
  6601. );
  6602. } break;
  6603. case v5::property::id::wildcard_subscription_available: {
  6604. static constexpr std::size_t len = 1;
  6605. if (property_length_rest < len) {
  6606. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6607. call_protocol_error_handlers();
  6608. return;
  6609. }
  6610. process_nbytes(
  6611. force_move(self),
  6612. force_move(session_life_keeper),
  6613. force_move(buf),
  6614. len,
  6615. [
  6616. this,
  6617. props = force_move(props),
  6618. handler = force_move(handler),
  6619. rest = property_length_rest - len
  6620. ]
  6621. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6622. auto& body = variant_get<buffer>(var);
  6623. props.emplace_back(
  6624. v5::property::wildcard_subscription_available(body.begin(), body.end())
  6625. );
  6626. process_property_id(
  6627. force_move(self),
  6628. force_move(session_life_keeper),
  6629. force_move(buf),
  6630. rest,
  6631. force_move(props),
  6632. force_move(handler)
  6633. );
  6634. }
  6635. );
  6636. } break;
  6637. case v5::property::id::subscription_identifier_available: {
  6638. static constexpr std::size_t len = 1;
  6639. if (property_length_rest < len) {
  6640. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6641. call_protocol_error_handlers();
  6642. return;
  6643. }
  6644. process_nbytes(
  6645. force_move(self),
  6646. force_move(session_life_keeper),
  6647. force_move(buf),
  6648. len,
  6649. [
  6650. this,
  6651. props = force_move(props),
  6652. handler = force_move(handler),
  6653. rest = property_length_rest - len
  6654. ]
  6655. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6656. auto& body = variant_get<buffer>(var);
  6657. props.emplace_back(
  6658. v5::property::subscription_identifier_available(body.begin(), body.end())
  6659. );
  6660. process_property_id(
  6661. force_move(self),
  6662. force_move(session_life_keeper),
  6663. force_move(buf),
  6664. rest,
  6665. force_move(props),
  6666. force_move(handler)
  6667. );
  6668. }
  6669. );
  6670. } break;
  6671. case v5::property::id::shared_subscription_available: {
  6672. static constexpr std::size_t len = 1;
  6673. if (property_length_rest < len) {
  6674. send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  6675. call_protocol_error_handlers();
  6676. return;
  6677. }
  6678. process_nbytes(
  6679. force_move(self),
  6680. force_move(session_life_keeper),
  6681. force_move(buf),
  6682. len,
  6683. [
  6684. this,
  6685. props = force_move(props),
  6686. handler = force_move(handler),
  6687. rest = property_length_rest - len
  6688. ]
  6689. (this_type_sp&& self, any&& session_life_keeper, parse_handler_variant var, buffer buf) mutable {
  6690. auto& body = variant_get<buffer>(var);
  6691. props.emplace_back(
  6692. v5::property::shared_subscription_available(body.begin(), body.end())
  6693. );
  6694. process_property_id(
  6695. force_move(self),
  6696. force_move(session_life_keeper),
  6697. force_move(buf),
  6698. rest,
  6699. force_move(props),
  6700. force_move(handler)
  6701. );
  6702. }
  6703. );
  6704. } break;
  6705. }
  6706. }
  6707. // process common
  6708. void process_header(
  6709. this_type_sp&& self,
  6710. any&& session_life_keeper,
  6711. bool all_read,
  6712. std::size_t header_len,
  6713. parse_handler&& handler
  6714. ) {
  6715. if (all_read) {
  6716. auto spa = make_shared_ptr_array(remaining_length_);
  6717. auto ptr = spa.get();
  6718. socket_->async_read(
  6719. as::buffer(ptr, remaining_length_),
  6720. [
  6721. this,
  6722. self = force_move(self),
  6723. session_life_keeper = force_move(session_life_keeper),
  6724. buf = buffer(string_view(ptr, remaining_length_), force_move(spa)),
  6725. handler = force_move(handler)
  6726. ]
  6727. (error_code ec, std::size_t bytes_transferred) mutable {
  6728. this->total_bytes_received_ += bytes_transferred;
  6729. if (!check_error_and_transferred_length(ec, bytes_transferred, remaining_length_)) return;
  6730. handler(
  6731. force_move(self),
  6732. force_move(session_life_keeper),
  6733. force_move(buf),
  6734. buffer()
  6735. );
  6736. }
  6737. );
  6738. return;
  6739. }
  6740. if (header_len == 0) {
  6741. force_move(handler)(
  6742. force_move(self),
  6743. force_move(session_life_keeper),
  6744. buffer(),
  6745. buffer()
  6746. );
  6747. return;
  6748. }
  6749. socket_->async_read(
  6750. as::buffer(buf_.data(), header_len),
  6751. [
  6752. this,
  6753. self = force_move(self),
  6754. session_life_keeper = force_move(session_life_keeper),
  6755. header_len,
  6756. handler = force_move(handler)
  6757. ]
  6758. (error_code ec,
  6759. std::size_t bytes_transferred) mutable {
  6760. this->total_bytes_received_ += bytes_transferred;
  6761. if (!check_error_and_transferred_length(ec, bytes_transferred, header_len)) return;
  6762. handler(
  6763. force_move(self),
  6764. force_move(session_life_keeper),
  6765. buffer(string_view(buf_.data(), header_len)),
  6766. buffer()
  6767. );
  6768. }
  6769. );
  6770. }
  6771. // process connect
  6772. struct process_connect : as::coroutine, std::enable_shared_from_this<process_connect> {
  6773. using ep_t = this_type;
  6774. using ep_t_sp = this_type_sp;
  6775. using process_type = process_connect;
  6776. using process_type_sp = std::shared_ptr<process_type>;
  6777. process_connect(
  6778. ep_t& ep,
  6779. bool all_read
  6780. ):ep_{ep},
  6781. all_read_{all_read} {
  6782. }
  6783. void operator()(
  6784. ep_t_sp spep,
  6785. any&& session_life_keeper,
  6786. parse_handler_variant var = std::size_t(0),
  6787. buffer remain_buf = buffer()
  6788. ) {
  6789. reenter(this) {
  6790. if (ep_.remaining_length_ < header_len_) {
  6791. ep_.call_protocol_error_handlers();
  6792. return;
  6793. }
  6794. // header
  6795. yield ep_.process_header(
  6796. force_move(spep),
  6797. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  6798. all_read_,
  6799. header_len_,
  6800. [this]
  6801. (auto&&... args ) {
  6802. (*this)(std::forward<decltype(args)>(args)...);
  6803. }
  6804. );
  6805. yield {
  6806. auto& buf = variant_get<buffer>(var);
  6807. static constexpr char protocol_name[] = { 0x00, 0x04, 'M', 'Q', 'T', 'T' };
  6808. if (std::memcmp(buf.data(), protocol_name, sizeof(protocol_name)) != 0) {
  6809. ep_.call_protocol_error_handlers();
  6810. return;
  6811. }
  6812. std::size_t i = sizeof(protocol_name);
  6813. auto version = static_cast<protocol_version>(buf[i++]);
  6814. if (version != protocol_version::v3_1_1 && version != protocol_version::v5) {
  6815. ep_.call_protocol_error_handlers();
  6816. return;
  6817. }
  6818. if (ep_.version_ == protocol_version::undetermined) {
  6819. ep_.version_ = version;
  6820. }
  6821. else if (ep_.version_ != version) {
  6822. ep_.call_protocol_error_handlers();
  6823. return;
  6824. }
  6825. connect_flag_ = buf[i++];
  6826. keep_alive_ = make_uint16_t(buf[i], buf[i + 1]);
  6827. ep_.clean_start_ = connect_flags::has_clean_start(connect_flag_);
  6828. buf.remove_prefix(header_len_); // consume buffer
  6829. if (ep_.version_ == protocol_version::v5) {
  6830. // properties
  6831. ep_.process_properties(
  6832. force_move(spep),
  6833. force_move(session_life_keeper),
  6834. force_move(buf),
  6835. [this]
  6836. (auto&&... args ) {
  6837. (*this)(std::forward<decltype(args)>(args)...);
  6838. }
  6839. );
  6840. }
  6841. else {
  6842. (*this)(force_move(spep), force_move(session_life_keeper), v5::properties(), force_move(buf));
  6843. }
  6844. }
  6845. props_ = force_move(variant_get<v5::properties>(var));
  6846. // client_id
  6847. yield ep_.process_string(
  6848. force_move(spep),
  6849. force_move(session_life_keeper),
  6850. force_move(remain_buf),
  6851. [this]
  6852. (auto&&... args ) {
  6853. (*this)(std::forward<decltype(args)>(args)...);
  6854. }
  6855. );
  6856. client_id_ = force_move(variant_get<buffer>(var));
  6857. ep_.set_client_id(std::string(client_id_));
  6858. if (connect_flags::has_will_flag(connect_flag_)) {
  6859. if (ep_.version_ == protocol_version::v5) {
  6860. // will properties
  6861. yield ep_.process_properties(
  6862. force_move(spep),
  6863. force_move(session_life_keeper),
  6864. force_move(remain_buf),
  6865. [this]
  6866. (auto&&... args ) {
  6867. (*this)(std::forward<decltype(args)>(args)...);
  6868. }
  6869. );
  6870. will_props_ = force_move(variant_get<v5::properties>(var));
  6871. }
  6872. // will topic
  6873. yield ep_.process_string(
  6874. force_move(spep),
  6875. force_move(session_life_keeper),
  6876. force_move(remain_buf),
  6877. [this]
  6878. (auto&&... args ) {
  6879. (*this)(std::forward<decltype(args)>(args)...);
  6880. }
  6881. );
  6882. will_topic_ = force_move(variant_get<buffer>(var));
  6883. // will payload
  6884. yield ep_.process_binary(
  6885. force_move(spep),
  6886. force_move(session_life_keeper),
  6887. force_move(remain_buf),
  6888. [this]
  6889. (auto&&... args ) {
  6890. (*this)(std::forward<decltype(args)>(args)...);
  6891. }
  6892. );
  6893. will_payload_ = force_move(variant_get<buffer>(var));
  6894. }
  6895. if (connect_flags::has_user_name_flag(connect_flag_)) {
  6896. yield ep_.process_string(
  6897. force_move(spep),
  6898. force_move(session_life_keeper),
  6899. force_move(remain_buf),
  6900. [this]
  6901. (auto&&... args ) {
  6902. (*this)(std::forward<decltype(args)>(args)...);
  6903. }
  6904. );
  6905. user_name_ = force_move(variant_get<buffer>(var));
  6906. }
  6907. if (connect_flags::has_password_flag(connect_flag_)) {
  6908. yield ep_.process_binary(
  6909. force_move(spep),
  6910. force_move(session_life_keeper),
  6911. force_move(remain_buf),
  6912. [this]
  6913. (auto&&... args ) {
  6914. (*this)(std::forward<decltype(args)>(args)...);
  6915. }
  6916. );
  6917. password_ = force_move(variant_get<buffer>(var));
  6918. }
  6919. ep_.mqtt_connected_ = true;
  6920. {
  6921. ep_.publish_send_count_ = 0;
  6922. {
  6923. LockGuard<Mutex> lck (ep_.resend_pubrel_mtx_);
  6924. ep_.resend_pubrel_.clear();
  6925. }
  6926. {
  6927. LockGuard<Mutex> lck (ep_.publish_received_mtx_);
  6928. ep_.publish_received_.clear();
  6929. }
  6930. {
  6931. LockGuard<Mutex> lck (ep_.publish_send_queue_mtx_);
  6932. ep_.publish_send_queue_.clear();
  6933. }
  6934. }
  6935. if (!ep_.set_values_from_props_on_connection(connection_type::server, props_)) return;
  6936. switch (ep_.version_) {
  6937. case protocol_version::v3_1_1:
  6938. if (ep_.on_connect(
  6939. force_move(client_id_),
  6940. force_move(user_name_),
  6941. force_move(password_),
  6942. connect_flags::has_will_flag(connect_flag_)
  6943. ? optional<will>(in_place_init,
  6944. force_move(will_topic_),
  6945. force_move(will_payload_),
  6946. connect_flags::has_will_retain(connect_flag_) | connect_flags::will_qos(connect_flag_))
  6947. : optional<will>(nullopt),
  6948. ep_.clean_session(),
  6949. keep_alive_
  6950. )
  6951. ) {
  6952. ep_.on_mqtt_message_processed(
  6953. force_move(
  6954. std::get<0>(
  6955. any_cast<
  6956. std::tuple<any, process_type_sp>
  6957. >(session_life_keeper)
  6958. )
  6959. )
  6960. );
  6961. }
  6962. break;
  6963. case protocol_version::v5:
  6964. if (ep_.on_v5_connect(
  6965. force_move(client_id_),
  6966. force_move(user_name_),
  6967. force_move(password_),
  6968. connect_flags::has_will_flag(connect_flag_)
  6969. ? optional<will>(in_place_init,
  6970. force_move(will_topic_),
  6971. force_move(will_payload_),
  6972. connect_flags::has_will_retain(connect_flag_) | connect_flags::will_qos(connect_flag_),
  6973. force_move(will_props_))
  6974. : optional<will>(nullopt),
  6975. ep_.clean_start(),
  6976. keep_alive_,
  6977. force_move(props_)
  6978. )
  6979. ) {
  6980. ep_.on_mqtt_message_processed(
  6981. force_move(
  6982. std::get<0>(
  6983. any_cast<
  6984. std::tuple<any, process_type_sp>
  6985. >(session_life_keeper)
  6986. )
  6987. )
  6988. );
  6989. }
  6990. break;
  6991. default:
  6992. BOOST_ASSERT(false);
  6993. }
  6994. }
  6995. }
  6996. private:
  6997. static constexpr std::size_t header_len_ =
  6998. 2 + // string length
  6999. 4 + // "MQTT" string
  7000. 1 + // ProtocolVersion
  7001. 1 + // ConnectFlag
  7002. 2; // KeepAlive
  7003. ep_t& ep_;
  7004. bool all_read_;
  7005. char connect_flag_;
  7006. std::uint16_t keep_alive_;
  7007. v5::properties props_;
  7008. buffer client_id_;
  7009. v5::properties will_props_;
  7010. buffer will_topic_;
  7011. buffer will_payload_;
  7012. optional<buffer> user_name_;
  7013. optional<buffer> password_;
  7014. };
  7015. friend struct process_connect;
  7016. // process connack
  7017. struct process_connack : as::coroutine, std::enable_shared_from_this<process_connack> {
  7018. using ep_t = this_type;
  7019. using ep_t_sp = this_type_sp;
  7020. using process_type = process_connack;
  7021. using process_type_sp = std::shared_ptr<process_type>;
  7022. process_connack(
  7023. ep_t& ep,
  7024. bool all_read
  7025. ):ep_{ep},
  7026. all_read_{all_read} {
  7027. }
  7028. void operator()(
  7029. ep_t_sp spep,
  7030. any&& session_life_keeper,
  7031. parse_handler_variant var = std::size_t(0),
  7032. buffer /*remain_buf*/ = buffer()
  7033. ) {
  7034. reenter(this) {
  7035. if (ep_.remaining_length_ < header_len_) {
  7036. ep_.call_protocol_error_handlers();
  7037. return;
  7038. }
  7039. // header
  7040. yield ep_.process_header(
  7041. force_move(spep),
  7042. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  7043. all_read_,
  7044. header_len_,
  7045. [this]
  7046. (auto&&... args ) {
  7047. (*this)(std::forward<decltype(args)>(args)...);
  7048. }
  7049. );
  7050. yield {
  7051. auto& buf = variant_get<buffer>(var);
  7052. session_present_ = is_session_present(buf[0]);
  7053. switch (ep_.version_) {
  7054. case protocol_version::v3_1_1:
  7055. reason_code_ = static_cast<connect_return_code>(buf[1]);
  7056. break;
  7057. case protocol_version::v5:
  7058. reason_code_ = static_cast<v5::connect_reason_code>(buf[1]);
  7059. break;
  7060. default:
  7061. BOOST_ASSERT(false);
  7062. }
  7063. buf.remove_prefix(header_len_); // consume buffer
  7064. if (ep_.version_ == protocol_version::v5) {
  7065. // properties
  7066. ep_.process_properties(
  7067. force_move(spep),
  7068. force_move(session_life_keeper),
  7069. force_move(buf),
  7070. [this]
  7071. (auto&&... args ) {
  7072. (*this)(std::forward<decltype(args)>(args)...);
  7073. }
  7074. );
  7075. }
  7076. else {
  7077. (*this)(force_move(spep), force_move(session_life_keeper), v5::properties(), force_move(buf));
  7078. }
  7079. }
  7080. props_ = force_move(variant_get<v5::properties>(var));
  7081. ep_.mqtt_connected_ = true;
  7082. {
  7083. ep_.publish_send_count_ = 0;
  7084. {
  7085. LockGuard<Mutex> lck (ep_.resend_pubrel_mtx_);
  7086. ep_.resend_pubrel_.clear();
  7087. }
  7088. {
  7089. LockGuard<Mutex> lck (ep_.publish_received_mtx_);
  7090. ep_.publish_received_.clear();
  7091. }
  7092. {
  7093. LockGuard<Mutex> lck (ep_.publish_send_queue_mtx_);
  7094. ep_.publish_send_queue_.clear();
  7095. }
  7096. }
  7097. if (!ep_.set_values_from_props_on_connection(connection_type::client, props_)) return;
  7098. {
  7099. auto connack_proc =
  7100. [this]
  7101. (any&& session_life_keeper) mutable {
  7102. switch (ep_.version_) {
  7103. case protocol_version::v3_1_1:
  7104. if (ep_.on_connack(
  7105. session_present_,
  7106. variant_get<connect_return_code>(reason_code_)
  7107. )
  7108. ) {
  7109. ep_.on_mqtt_message_processed(
  7110. force_move(
  7111. std::get<0>(
  7112. any_cast<
  7113. std::tuple<any, process_type_sp>
  7114. >(session_life_keeper)
  7115. )
  7116. )
  7117. );
  7118. }
  7119. break;
  7120. case protocol_version::v5:
  7121. if (ep_.on_v5_connack(
  7122. session_present_,
  7123. variant_get<v5::connect_reason_code>(reason_code_),
  7124. force_move(props_)
  7125. )
  7126. ) {
  7127. ep_.on_mqtt_message_processed(
  7128. force_move(
  7129. std::get<0>(
  7130. any_cast<
  7131. std::tuple<any, process_type_sp>
  7132. >(session_life_keeper)
  7133. )
  7134. )
  7135. );
  7136. }
  7137. break;
  7138. default:
  7139. BOOST_ASSERT(false);
  7140. }
  7141. };
  7142. // Note: boost:variant has no featue to query if the variant currently holds a specific type.
  7143. // MQTT_CPP could create a type traits function to match the provided type to the index in
  7144. // the boost::variant type list, but for now it does not appear to be needed.
  7145. if ( ( (0 == variant_idx(reason_code_))
  7146. && (connect_return_code::accepted == variant_get<connect_return_code>(reason_code_)))
  7147. || ( (1 == variant_idx(reason_code_))
  7148. && (v5::connect_reason_code::success == variant_get<v5::connect_reason_code>(reason_code_)))) {
  7149. // If session_present is false, then call clear_session_data().
  7150. // Here is the reason why it works well.
  7151. // ---
  7152. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901078
  7153. //
  7154. // If the Server accepts a connection with Clean Start set to 1, the Server
  7155. // MUST set Session Present to 0 in the CONNACK packet in addition to setting
  7156. // a 0x00 (Success) Reason Code in the CONNACK packet [MQTT-3.2.2-2].
  7157. //
  7158. //
  7159. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901048
  7160. //
  7161. // The Client can avoid implementing its own Session expiry and instead rely on
  7162. // the Session Present flag returned from the Server to determine if the Session
  7163. // had expired. If the Client does implement its own Session expiry, it needs to
  7164. // store the time at which the Session State will be deleted as part of its
  7165. // Session State.
  7166. // ---
  7167. //
  7168. // Also it can avoid the following client side and broker side session state
  7169. // mismatch autonatically.
  7170. //
  7171. // ---
  7172. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901078
  7173. //
  7174. // If the Client does not have Session State and receives Session Present
  7175. // set to 1 it MUST close the Network Connection [MQTT-3.2.2-4]. If it
  7176. // wishes to restart with a new Session the Client can reconnect using
  7177. // Clean Start set to 1.
  7178. // If the Client does have Session State and receives Session Present set
  7179. // to 0 it MUST discard its Session State if it continues with the Network
  7180. // Connection [MQTT-3.2.2-5].
  7181. // ---
  7182. if (session_present_) {
  7183. if (ep_.async_operation_) {
  7184. // Until all stored messages are written to internal send buffer,
  7185. // disable further async reading of incoming packets..
  7186. ep_.async_read_on_message_processed_ = false;
  7187. auto async_connack_proc =
  7188. [
  7189. this,
  7190. spep = force_move(spep),
  7191. session_life_keeper = force_move(session_life_keeper),
  7192. connack_proc = force_move(connack_proc)
  7193. ]
  7194. () mutable {
  7195. // All stored messages are sent, so re-enable reading of incoming packets.
  7196. // and notify the end user code that the connack packet was received.
  7197. ep_.async_read_on_message_processed_ = true;
  7198. connack_proc(force_move(session_life_keeper));
  7199. };
  7200. ep_.async_send_store(force_move(async_connack_proc));
  7201. return;
  7202. }
  7203. ep_.send_store();
  7204. }
  7205. else {
  7206. ep_.clear_session_data();
  7207. }
  7208. }
  7209. connack_proc(force_move(session_life_keeper));
  7210. }
  7211. }
  7212. }
  7213. private:
  7214. static constexpr std::size_t header_len_ =
  7215. 1 + // Connect Acknowledge Flags
  7216. 1; // Reason Code
  7217. ep_t& ep_;
  7218. bool all_read_;
  7219. bool session_present_;
  7220. variant<connect_return_code, v5::connect_reason_code> reason_code_;
  7221. v5::properties props_;
  7222. };
  7223. friend struct process_connack;
  7224. // process publish
  7225. struct process_publish : as::coroutine, std::enable_shared_from_this<process_publish> {
  7226. using ep_t = this_type;
  7227. using ep_t_sp = this_type_sp;
  7228. using process_type = process_publish;
  7229. using process_type_sp = std::shared_ptr<process_type>;
  7230. process_publish(
  7231. ep_t& ep,
  7232. bool all_read
  7233. ):ep_{ep},
  7234. all_read_{all_read} {
  7235. }
  7236. void operator()(
  7237. ep_t_sp spep,
  7238. any&& session_life_keeper,
  7239. parse_handler_variant var = std::size_t(0),
  7240. buffer remain_buf = buffer()
  7241. ) {
  7242. reenter(this) {
  7243. if (ep_.remaining_length_ < min_len_) {
  7244. ep_.call_protocol_error_handlers();
  7245. return;
  7246. }
  7247. // header
  7248. yield ep_.process_header(
  7249. force_move(spep),
  7250. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  7251. all_read_,
  7252. 0,
  7253. [this]
  7254. (auto&&... args ) {
  7255. (*this)(std::forward<decltype(args)>(args)...);
  7256. }
  7257. );
  7258. // topic_name
  7259. yield ep_.process_string(
  7260. force_move(spep),
  7261. force_move(session_life_keeper),
  7262. force_move(variant_get<buffer>(var)),
  7263. [this]
  7264. (auto&&... args ) {
  7265. (*this)(std::forward<decltype(args)>(args)...);
  7266. }
  7267. );
  7268. topic_name_ = force_move(variant_get<buffer>(var));
  7269. qos_value_ = publish::get_qos(ep_.fixed_header_);
  7270. if (qos_value_ != qos::at_most_once &&
  7271. qos_value_ != qos::at_least_once &&
  7272. qos_value_ != qos::exactly_once) {
  7273. ep_.call_bad_message_error_handlers();
  7274. return;
  7275. }
  7276. if (qos_value_ == qos::at_least_once ||
  7277. qos_value_ == qos::exactly_once) {
  7278. yield ep_.process_packet_id(
  7279. force_move(spep),
  7280. force_move(session_life_keeper),
  7281. force_move(remain_buf),
  7282. [this]
  7283. (auto&&... args ) {
  7284. (*this)(std::forward<decltype(args)>(args)...);
  7285. }
  7286. );
  7287. packet_id_ = force_move(variant_get<packet_id_t>(var));
  7288. }
  7289. if (ep_.version_ == protocol_version::v5) {
  7290. yield ep_.process_properties(
  7291. force_move(spep),
  7292. force_move(session_life_keeper),
  7293. force_move(remain_buf),
  7294. [this]
  7295. (auto&&... args ) {
  7296. (*this)(std::forward<decltype(args)>(args)...);
  7297. }
  7298. );
  7299. props_ = force_move(variant_get<v5::properties>(var));
  7300. }
  7301. yield ep_.process_nbytes(
  7302. force_move(spep),
  7303. force_move(session_life_keeper),
  7304. force_move(remain_buf),
  7305. ep_.remaining_length_,
  7306. [this]
  7307. (auto&&... args ) {
  7308. (*this)(std::forward<decltype(args)>(args)...);
  7309. }
  7310. );
  7311. {
  7312. auto handler_call =
  7313. [&] {
  7314. auto check_full =
  7315. [&] {
  7316. LockGuard<Mutex> lck (ep_.publish_received_mtx_);
  7317. if (ep_.publish_received_.size() == ep_.publish_recv_max_) {
  7318. return true;
  7319. }
  7320. ep_.publish_received_.insert(*packet_id_);
  7321. return false;
  7322. };
  7323. switch (ep_.version_) {
  7324. case protocol_version::v3_1_1:
  7325. return ep_.on_publish(
  7326. packet_id_,
  7327. publish_options(ep_.fixed_header_),
  7328. force_move(topic_name_),
  7329. force_move(variant_get<buffer>(var))
  7330. );
  7331. case protocol_version::v5:
  7332. switch (qos_value_) {
  7333. case qos::at_most_once:
  7334. break;
  7335. // automatically response error using puback / pubrec
  7336. // but the connection continues.
  7337. // publish handler is not called
  7338. case qos::at_least_once:
  7339. if (check_full()) {
  7340. if (ep_.async_operation_) {
  7341. ep_.async_send_puback(
  7342. *packet_id_,
  7343. v5::puback_reason_code::quota_exceeded,
  7344. v5::properties{},
  7345. [](auto){}
  7346. );
  7347. }
  7348. else {
  7349. ep_.send_puback(
  7350. *packet_id_,
  7351. v5::puback_reason_code::quota_exceeded,
  7352. v5::properties{}
  7353. );
  7354. }
  7355. ep_.on_mqtt_message_processed(
  7356. force_move(
  7357. std::get<0>(
  7358. any_cast<
  7359. std::tuple<any, process_type_sp>
  7360. >(session_life_keeper)
  7361. )
  7362. )
  7363. );
  7364. return false;
  7365. }
  7366. break;
  7367. case qos::exactly_once:
  7368. if (check_full()) {
  7369. if (ep_.async_operation_) {
  7370. ep_.async_send_pubrec(
  7371. *packet_id_,
  7372. v5::pubrec_reason_code::quota_exceeded,
  7373. v5::properties{},
  7374. [](auto){}
  7375. );
  7376. }
  7377. else {
  7378. ep_.send_pubrec(
  7379. *packet_id_,
  7380. v5::pubrec_reason_code::quota_exceeded,
  7381. v5::properties{}
  7382. );
  7383. }
  7384. ep_.on_mqtt_message_processed(
  7385. force_move(
  7386. std::get<0>(
  7387. any_cast<
  7388. std::tuple<any, process_type_sp>
  7389. >(session_life_keeper)
  7390. )
  7391. )
  7392. );
  7393. return false;
  7394. }
  7395. break;
  7396. }
  7397. if (topic_name_.empty()) {
  7398. if (auto topic_alias = get_topic_alias_from_props(props_)) {
  7399. if (topic_alias.value() == 0 ||
  7400. topic_alias.value() > ep_.topic_alias_recv_.value().max()) {
  7401. ep_.send_error_disconnect(v5::disconnect_reason_code::topic_alias_invalid);
  7402. ep_.call_protocol_error_handlers();
  7403. return false;
  7404. }
  7405. auto topic_name = [&] {
  7406. LockGuard<Mutex> lck (ep_.topic_alias_recv_mtx_);
  7407. if (ep_.topic_alias_recv_) {
  7408. return ep_.topic_alias_recv_.value().find(topic_alias.value());
  7409. }
  7410. return std::string();
  7411. }();
  7412. if (topic_name.empty()) {
  7413. MQTT_LOG("mqtt_cb", error)
  7414. << MQTT_ADD_VALUE(address, &ep_)
  7415. << "no matching topic alias: "
  7416. << topic_alias.value();
  7417. ep_.send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  7418. ep_.call_protocol_error_handlers();
  7419. return false;
  7420. }
  7421. else {
  7422. topic_name_ = allocate_buffer(topic_name);
  7423. }
  7424. }
  7425. }
  7426. else {
  7427. if (auto topic_alias = ep_.get_topic_alias_from_props(props_)) {
  7428. LockGuard<Mutex> lck (ep_.topic_alias_recv_mtx_);
  7429. if (ep_.topic_alias_recv_) {
  7430. ep_.topic_alias_recv_.value().insert_or_update(topic_name_, topic_alias.value());
  7431. }
  7432. }
  7433. }
  7434. {
  7435. auto ret = ep_.on_v5_publish(
  7436. packet_id_,
  7437. publish_options(ep_.fixed_header_),
  7438. force_move(topic_name_),
  7439. force_move(variant_get<buffer>(var)),
  7440. force_move(props_)
  7441. );
  7442. return ret;
  7443. }
  7444. default:
  7445. BOOST_ASSERT(false);
  7446. }
  7447. return false;
  7448. };
  7449. switch (qos_value_) {
  7450. case qos::at_most_once:
  7451. if (handler_call()) {
  7452. ep_.on_mqtt_message_processed(
  7453. force_move(
  7454. std::get<0>(
  7455. any_cast<
  7456. std::tuple<any, process_type_sp>
  7457. >(session_life_keeper)
  7458. )
  7459. )
  7460. );
  7461. }
  7462. break;
  7463. case qos::at_least_once:
  7464. if (handler_call()) {
  7465. ep_.on_mqtt_message_processed(
  7466. force_move(
  7467. std::get<0>(
  7468. any_cast<
  7469. std::tuple<any, process_type_sp>
  7470. >(session_life_keeper)
  7471. )
  7472. )
  7473. );
  7474. ep_.auto_pub_response(
  7475. [this] {
  7476. if (ep_.connected_) {
  7477. ep_.send_puback(
  7478. *packet_id_,
  7479. v5::puback_reason_code::success,
  7480. v5::properties{}
  7481. );
  7482. }
  7483. },
  7484. [this] {
  7485. if (ep_.connected_) {
  7486. ep_.async_send_puback(
  7487. *packet_id_,
  7488. v5::puback_reason_code::success,
  7489. v5::properties{},
  7490. [](auto){}
  7491. );
  7492. }
  7493. }
  7494. );
  7495. }
  7496. break;
  7497. case qos::exactly_once:
  7498. if (ep_.qos2_publish_handled_.find(*packet_id_) == ep_.qos2_publish_handled_.end()) {
  7499. if (handler_call()) {
  7500. ep_.on_mqtt_message_processed(
  7501. force_move(
  7502. std::get<0>(
  7503. any_cast<
  7504. std::tuple<any, process_type_sp>
  7505. >(session_life_keeper)
  7506. )
  7507. )
  7508. );
  7509. ep_.qos2_publish_handled_.emplace(*packet_id_);
  7510. ep_.auto_pub_response(
  7511. [this] {
  7512. if (ep_.connected_) {
  7513. ep_.send_pubrec(
  7514. *packet_id_,
  7515. v5::pubrec_reason_code::success,
  7516. v5::properties{}
  7517. );
  7518. }
  7519. },
  7520. [this] {
  7521. if (ep_.connected_) {
  7522. ep_.async_send_pubrec(
  7523. *packet_id_,
  7524. v5::pubrec_reason_code::success,
  7525. v5::properties{},
  7526. [](auto){}
  7527. );
  7528. }
  7529. }
  7530. );
  7531. }
  7532. }
  7533. else {
  7534. // publish has already been handled
  7535. ep_.on_mqtt_message_processed(
  7536. force_move(
  7537. std::get<0>(
  7538. any_cast<
  7539. std::tuple<any, process_type_sp>
  7540. >(session_life_keeper)
  7541. )
  7542. )
  7543. );
  7544. if (ep_.async_operation_) {
  7545. ep_.async_send_pubrec(
  7546. *packet_id_,
  7547. v5::pubrec_reason_code::success,
  7548. v5::properties{},
  7549. [](auto){}
  7550. );
  7551. }
  7552. else {
  7553. ep_.send_pubrec(
  7554. *packet_id_,
  7555. v5::pubrec_reason_code::success,
  7556. v5::properties{}
  7557. );
  7558. }
  7559. }
  7560. break;
  7561. }
  7562. }
  7563. }
  7564. }
  7565. private:
  7566. static constexpr std::size_t min_len_ = 2; // topic name length
  7567. ep_t& ep_;
  7568. bool all_read_;
  7569. buffer topic_name_;
  7570. qos qos_value_;
  7571. optional<packet_id_t> packet_id_;
  7572. v5::properties props_;
  7573. buffer payload_;
  7574. };
  7575. friend struct process_publish;
  7576. // process puback
  7577. struct process_puback : as::coroutine, std::enable_shared_from_this<process_puback> {
  7578. using ep_t = this_type;
  7579. using ep_t_sp = this_type_sp;
  7580. using process_type = process_puback;
  7581. using process_type_sp = std::shared_ptr<process_type>;
  7582. process_puback(
  7583. ep_t& ep,
  7584. bool all_read
  7585. ):ep_{ep},
  7586. all_read_{all_read} {
  7587. }
  7588. void operator()(
  7589. ep_t_sp spep,
  7590. any&& session_life_keeper,
  7591. parse_handler_variant var = std::size_t(0),
  7592. buffer remain_buf = buffer()
  7593. ) {
  7594. reenter(this) {
  7595. if (ep_.remaining_length_ < header_len_) {
  7596. ep_.call_protocol_error_handlers();
  7597. return;
  7598. }
  7599. // header
  7600. yield ep_.process_header(
  7601. force_move(spep),
  7602. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  7603. all_read_,
  7604. header_len_,
  7605. [this]
  7606. (auto&&... args ) {
  7607. (*this)(std::forward<decltype(args)>(args)...);
  7608. }
  7609. );
  7610. // packet_id
  7611. yield ep_.process_packet_id(
  7612. force_move(spep),
  7613. force_move(session_life_keeper),
  7614. force_move(variant_get<buffer>(var)),
  7615. [this]
  7616. (auto&&... args ) {
  7617. (*this)(std::forward<decltype(args)>(args)...);
  7618. }
  7619. );
  7620. packet_id_ = force_move(variant_get<packet_id_t>(var));
  7621. if (ep_.remaining_length_ == 0) {
  7622. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901126
  7623. // If the Remaining Length is 0, there is no reason code & property length
  7624. // the value of success is used for reason code, the value of 0 is used for property length
  7625. reason_code_ = v5::puback_reason_code::success;
  7626. }
  7627. else {
  7628. // reason_code
  7629. yield ep_.process_nbytes(
  7630. force_move(spep),
  7631. force_move(session_life_keeper),
  7632. force_move(remain_buf),
  7633. 1,
  7634. [this]
  7635. (auto&&... args ) {
  7636. (*this)(std::forward<decltype(args)>(args)...);
  7637. }
  7638. );
  7639. reason_code_ = static_cast<v5::puback_reason_code>(variant_get<buffer>(var)[0]);
  7640. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901126
  7641. // If the Remaining Length is 0, there is no property length and the value of 0 is used
  7642. if (ep_.remaining_length_ > 0) {
  7643. // properties
  7644. yield ep_.process_properties(
  7645. force_move(spep),
  7646. force_move(session_life_keeper),
  7647. force_move(remain_buf),
  7648. [this]
  7649. (auto&&... args ) {
  7650. (*this)(std::forward<decltype(args)>(args)...);
  7651. }
  7652. );
  7653. props_ = force_move(variant_get<v5::properties>(var));
  7654. }
  7655. }
  7656. auto erased =
  7657. [&] {
  7658. LockGuard<Mutex> lck (ep_.store_mtx_);
  7659. if (!ep_.store_.erase(packet_id_, control_packet_type::puback)) {
  7660. // puback packet_id is not matched to publish
  7661. return false;
  7662. }
  7663. ep_.pid_man_.release_id(packet_id_);
  7664. return true;
  7665. } ();
  7666. if (erased) ep_.on_serialize_remove(packet_id_);
  7667. switch (ep_.version_) {
  7668. case protocol_version::v3_1_1:
  7669. if (ep_.on_puback(packet_id_)) {
  7670. ep_.on_mqtt_message_processed(
  7671. force_move(
  7672. std::get<0>(
  7673. any_cast<
  7674. std::tuple<any, process_type_sp>
  7675. >(session_life_keeper)
  7676. )
  7677. )
  7678. );
  7679. }
  7680. break;
  7681. case protocol_version::v5:
  7682. if (erased) ep_.send_publish_queue_one();
  7683. if (ep_.on_v5_puback(packet_id_, reason_code_, force_move(props_))) {
  7684. ep_.on_mqtt_message_processed(
  7685. force_move(
  7686. std::get<0>(
  7687. any_cast<
  7688. std::tuple<any, process_type_sp>
  7689. >(session_life_keeper)
  7690. )
  7691. )
  7692. );
  7693. }
  7694. break;
  7695. default:
  7696. BOOST_ASSERT(false);
  7697. }
  7698. }
  7699. }
  7700. private:
  7701. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  7702. ep_t& ep_;
  7703. bool all_read_;
  7704. packet_id_t packet_id_;
  7705. v5::puback_reason_code reason_code_;
  7706. v5::properties props_;
  7707. };
  7708. friend struct process_puback;
  7709. // process pubrec
  7710. struct process_pubrec : as::coroutine, std::enable_shared_from_this<process_pubrec> {
  7711. using ep_t = this_type;
  7712. using ep_t_sp = this_type_sp;
  7713. using process_type = process_pubrec;
  7714. using process_type_sp = std::shared_ptr<process_type>;
  7715. process_pubrec(
  7716. ep_t& ep,
  7717. bool all_read
  7718. ):ep_{ep},
  7719. all_read_{all_read} {
  7720. }
  7721. void operator()(
  7722. ep_t_sp spep,
  7723. any&& session_life_keeper,
  7724. parse_handler_variant var = std::size_t(0),
  7725. buffer remain_buf = buffer()
  7726. ) {
  7727. reenter(this) {
  7728. if (ep_.remaining_length_ < header_len_) {
  7729. ep_.call_protocol_error_handlers();
  7730. return;
  7731. }
  7732. // header
  7733. yield ep_.process_header(
  7734. force_move(spep),
  7735. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  7736. all_read_,
  7737. header_len_,
  7738. [this]
  7739. (auto&&... args ) {
  7740. (*this)(std::forward<decltype(args)>(args)...);
  7741. }
  7742. );
  7743. // packet_id
  7744. yield ep_.process_packet_id(
  7745. force_move(spep),
  7746. force_move(session_life_keeper),
  7747. force_move(variant_get<buffer>(var)),
  7748. [this]
  7749. (auto&&... args ) {
  7750. (*this)(std::forward<decltype(args)>(args)...);
  7751. }
  7752. );
  7753. packet_id_ = force_move(variant_get<packet_id_t>(var));
  7754. if (ep_.remaining_length_ == 0) {
  7755. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901136
  7756. // If the Remaining Length is 0, there is no reason code & property length
  7757. // the value of success is used for reason code, the value of 0 is used for property length
  7758. reason_code_ = v5::pubrec_reason_code::success;
  7759. }
  7760. else {
  7761. // reason_code
  7762. yield ep_.process_nbytes(
  7763. force_move(spep),
  7764. force_move(session_life_keeper),
  7765. force_move(remain_buf),
  7766. 1,
  7767. [this]
  7768. (auto&&... args ) {
  7769. (*this)(std::forward<decltype(args)>(args)...);
  7770. }
  7771. );
  7772. reason_code_ = static_cast<v5::pubrec_reason_code>(variant_get<buffer>(var)[0]);
  7773. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901136
  7774. // If the Remaining Length is 0, there is no property length and the value of 0 is used
  7775. if (ep_.remaining_length_ > 0) {
  7776. // properties
  7777. yield ep_.process_properties(
  7778. force_move(spep),
  7779. force_move(session_life_keeper),
  7780. force_move(remain_buf),
  7781. [this]
  7782. (auto&&... args ) {
  7783. (*this)(std::forward<decltype(args)>(args)...);
  7784. }
  7785. );
  7786. props_ = force_move(variant_get<v5::properties>(var));
  7787. }
  7788. }
  7789. auto erased =
  7790. [&] {
  7791. LockGuard<Mutex> lck (ep_.store_mtx_);
  7792. if (!ep_.store_.erase(packet_id_, control_packet_type::pubrec)) {
  7793. // pubrec packet_id is not matched to publish
  7794. return false;
  7795. }
  7796. // packet_id should be erased here only if reason_code is error.
  7797. // Otherwise the packet_id is continue to be used for pubrel/pubcomp.
  7798. if (is_error(reason_code_)) ep_.pid_man_.release_id(packet_id_);
  7799. return true;
  7800. } ();
  7801. {
  7802. auto res =
  7803. [&] {
  7804. auto rc =
  7805. [&] {
  7806. if (erased) return v5::pubrel_reason_code::success;
  7807. return v5::pubrel_reason_code::packet_identifier_not_found;
  7808. } ();
  7809. ep_.auto_pub_response(
  7810. [&] {
  7811. if (ep_.connected_) {
  7812. ep_.send_pubrel(
  7813. packet_id_,
  7814. rc,
  7815. v5::properties{},
  7816. any{}
  7817. );
  7818. }
  7819. else {
  7820. ep_.store_pubrel(
  7821. packet_id_,
  7822. rc,
  7823. v5::properties{},
  7824. any{}
  7825. );
  7826. }
  7827. },
  7828. [&] {
  7829. if (ep_.connected_) {
  7830. ep_.async_send_pubrel(
  7831. packet_id_,
  7832. rc,
  7833. v5::properties{},
  7834. any{},
  7835. [](auto){}
  7836. );
  7837. }
  7838. else {
  7839. ep_.store_pubrel(
  7840. packet_id_,
  7841. rc,
  7842. v5::properties{},
  7843. any{}
  7844. );
  7845. }
  7846. }
  7847. );
  7848. };
  7849. switch (ep_.version_) {
  7850. case protocol_version::v3_1_1:
  7851. if (ep_.on_pubrec(packet_id_)) {
  7852. res();
  7853. ep_.on_mqtt_message_processed(
  7854. force_move(
  7855. std::get<0>(
  7856. any_cast<
  7857. std::tuple<any, process_type_sp>
  7858. >(session_life_keeper)
  7859. )
  7860. )
  7861. );
  7862. }
  7863. break;
  7864. case protocol_version::v5:
  7865. if (erased && is_error(reason_code_)) {
  7866. ep_.on_serialize_remove(packet_id_);
  7867. ep_.send_publish_queue_one();
  7868. }
  7869. if (ep_.on_v5_pubrec(packet_id_, reason_code_, force_move(props_))) {
  7870. if (!is_error(reason_code_)) res();
  7871. ep_.on_mqtt_message_processed(
  7872. force_move(
  7873. std::get<0>(
  7874. any_cast<
  7875. std::tuple<any, process_type_sp>
  7876. >(session_life_keeper)
  7877. )
  7878. )
  7879. );
  7880. }
  7881. break;
  7882. default:
  7883. BOOST_ASSERT(false);
  7884. }
  7885. }
  7886. }
  7887. }
  7888. private:
  7889. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  7890. ep_t& ep_;
  7891. bool all_read_;
  7892. packet_id_t packet_id_;
  7893. v5::pubrec_reason_code reason_code_;
  7894. v5::properties props_;
  7895. };
  7896. friend struct process_pubrec;
  7897. struct process_pubrel : as::coroutine, std::enable_shared_from_this<process_pubrel> {
  7898. using ep_t = this_type;
  7899. using ep_t_sp = this_type_sp;
  7900. using process_type = process_pubrel;
  7901. using process_type_sp = std::shared_ptr<process_type>;
  7902. process_pubrel(
  7903. ep_t& ep,
  7904. bool all_read
  7905. ):ep_{ep},
  7906. all_read_{all_read} {
  7907. }
  7908. void operator()(
  7909. ep_t_sp spep,
  7910. any&& session_life_keeper,
  7911. parse_handler_variant var = std::size_t(0),
  7912. buffer remain_buf = buffer()
  7913. ) {
  7914. reenter(this) {
  7915. if (ep_.remaining_length_ < header_len_) {
  7916. ep_.call_protocol_error_handlers();
  7917. return;
  7918. }
  7919. // header
  7920. yield ep_.process_header(
  7921. force_move(spep),
  7922. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  7923. all_read_,
  7924. header_len_,
  7925. [this]
  7926. (auto&&... args ) {
  7927. (*this)(std::forward<decltype(args)>(args)...);
  7928. }
  7929. );
  7930. // packet_id
  7931. yield ep_.process_packet_id(
  7932. force_move(spep),
  7933. force_move(session_life_keeper),
  7934. force_move(variant_get<buffer>(var)),
  7935. [this]
  7936. (auto&&... args ) {
  7937. (*this)(std::forward<decltype(args)>(args)...);
  7938. }
  7939. );
  7940. packet_id_ = force_move(variant_get<packet_id_t>(var));
  7941. if (ep_.remaining_length_ == 0) {
  7942. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901146
  7943. // If the Remaining Length is 0, there is no reason code & property length
  7944. // the value of success is used for reason code, the value of 0 is used for property length
  7945. reason_code_ = v5::pubrel_reason_code::success;
  7946. }
  7947. else {
  7948. // reason_code
  7949. yield ep_.process_nbytes(
  7950. force_move(spep),
  7951. force_move(session_life_keeper),
  7952. force_move(remain_buf),
  7953. 1,
  7954. [this]
  7955. (auto&&... args ) {
  7956. (*this)(std::forward<decltype(args)>(args)...);
  7957. }
  7958. );
  7959. reason_code_ = static_cast<v5::pubrel_reason_code>(variant_get<buffer>(var)[0]);
  7960. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901146
  7961. // If the Remaining Length is 0, there is no property length and the value of 0 is used
  7962. if (ep_.remaining_length_ > 0) {
  7963. // properties
  7964. yield ep_.process_properties(
  7965. force_move(spep),
  7966. force_move(session_life_keeper),
  7967. force_move(remain_buf),
  7968. [this]
  7969. (auto&&... args ) {
  7970. (*this)(std::forward<decltype(args)>(args)...);
  7971. }
  7972. );
  7973. props_ = force_move(variant_get<v5::properties>(var));
  7974. }
  7975. }
  7976. {
  7977. auto res =
  7978. [&] {
  7979. ep_.auto_pub_response(
  7980. [&] {
  7981. if (ep_.connected_) {
  7982. ep_.send_pubcomp(
  7983. packet_id_,
  7984. static_cast<v5::pubcomp_reason_code>(reason_code_),
  7985. v5::properties{}
  7986. );
  7987. }
  7988. },
  7989. [&] {
  7990. if (ep_.connected_) {
  7991. ep_.async_send_pubcomp(
  7992. packet_id_,
  7993. static_cast<v5::pubcomp_reason_code>(reason_code_),
  7994. v5::properties{},
  7995. [](auto){}
  7996. );
  7997. }
  7998. }
  7999. );
  8000. };
  8001. ep_.qos2_publish_handled_.erase(packet_id_);
  8002. switch (ep_.version_) {
  8003. case protocol_version::v3_1_1:
  8004. if (ep_.on_pubrel(packet_id_)) {
  8005. res();
  8006. ep_.on_mqtt_message_processed(
  8007. force_move(
  8008. std::get<0>(
  8009. any_cast<
  8010. std::tuple<any, process_type_sp>
  8011. >(session_life_keeper)
  8012. )
  8013. )
  8014. );
  8015. }
  8016. break;
  8017. case protocol_version::v5:
  8018. if (ep_.on_v5_pubrel(packet_id_, reason_code_, force_move(props_))) {
  8019. res();
  8020. ep_.on_mqtt_message_processed(
  8021. force_move(
  8022. std::get<0>(
  8023. any_cast<
  8024. std::tuple<any, process_type_sp>
  8025. >(session_life_keeper)
  8026. )
  8027. )
  8028. );
  8029. }
  8030. break;
  8031. default:
  8032. BOOST_ASSERT(false);
  8033. }
  8034. }
  8035. }
  8036. }
  8037. private:
  8038. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8039. ep_t& ep_;
  8040. bool all_read_;
  8041. packet_id_t packet_id_;
  8042. v5::pubrel_reason_code reason_code_;
  8043. v5::properties props_;
  8044. };
  8045. friend struct process_pubrel;
  8046. // process pubcomp
  8047. struct process_pubcomp : as::coroutine, std::enable_shared_from_this<process_pubcomp> {
  8048. using ep_t = this_type;
  8049. using ep_t_sp = this_type_sp;
  8050. using process_type = process_pubcomp;
  8051. using process_type_sp = std::shared_ptr<process_type>;
  8052. process_pubcomp(
  8053. ep_t& ep,
  8054. bool all_read
  8055. ):ep_{ep},
  8056. all_read_{all_read} {
  8057. }
  8058. void operator()(
  8059. ep_t_sp spep,
  8060. any&& session_life_keeper,
  8061. parse_handler_variant var = std::size_t(0),
  8062. buffer remain_buf = buffer()
  8063. ) {
  8064. reenter(this) {
  8065. if (ep_.remaining_length_ < header_len_) {
  8066. ep_.call_protocol_error_handlers();
  8067. return;
  8068. }
  8069. // header
  8070. yield ep_.process_header(
  8071. force_move(spep),
  8072. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  8073. all_read_,
  8074. header_len_,
  8075. [this]
  8076. (auto&&... args ) {
  8077. (*this)(std::forward<decltype(args)>(args)...);
  8078. }
  8079. );
  8080. // packet_id
  8081. yield ep_.process_packet_id(
  8082. force_move(spep),
  8083. force_move(session_life_keeper),
  8084. force_move(variant_get<buffer>(var)),
  8085. [this]
  8086. (auto&&... args ) {
  8087. (*this)(std::forward<decltype(args)>(args)...);
  8088. }
  8089. );
  8090. packet_id_ = force_move(variant_get<packet_id_t>(var));
  8091. if (ep_.remaining_length_ == 0) {
  8092. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901156
  8093. // If the Remaining Length is 0, there is no reason code & property length
  8094. // the value of success is used for reason code, the value of 0 is used for property length
  8095. reason_code_ = v5::pubcomp_reason_code::success;
  8096. }
  8097. else {
  8098. // reason_code
  8099. yield ep_.process_nbytes(
  8100. force_move(spep),
  8101. force_move(session_life_keeper),
  8102. force_move(remain_buf),
  8103. 1,
  8104. [this]
  8105. (auto&&... args ) {
  8106. (*this)(std::forward<decltype(args)>(args)...);
  8107. }
  8108. );
  8109. reason_code_ = static_cast<v5::pubcomp_reason_code>(variant_get<buffer>(var)[0]);
  8110. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901156
  8111. // If the Remaining Length is 0, there is no property length and the value of 0 is used
  8112. if (ep_.remaining_length_ > 0) {
  8113. // properties
  8114. yield ep_.process_properties(
  8115. force_move(spep),
  8116. force_move(session_life_keeper),
  8117. force_move(remain_buf),
  8118. [this]
  8119. (auto&&... args ) {
  8120. (*this)(std::forward<decltype(args)>(args)...);
  8121. }
  8122. );
  8123. props_ = force_move(variant_get<v5::properties>(var));
  8124. }
  8125. }
  8126. auto erased =
  8127. [&] {
  8128. LockGuard<Mutex> lck (ep_.store_mtx_);
  8129. if (!ep_.store_.erase(packet_id_, control_packet_type::pubcomp)) {
  8130. // pubcomp packet_id is not matched to pubrel
  8131. return false;
  8132. }
  8133. ep_.pid_man_.release_id(packet_id_);
  8134. return true;
  8135. } ();
  8136. if (erased) ep_.on_serialize_remove(packet_id_);
  8137. switch (ep_.version_) {
  8138. case protocol_version::v3_1_1:
  8139. if (ep_.on_pubcomp(packet_id_)) {
  8140. ep_.on_mqtt_message_processed(
  8141. force_move(
  8142. std::get<0>(
  8143. any_cast<
  8144. std::tuple<any, process_type_sp>
  8145. >(session_life_keeper)
  8146. )
  8147. )
  8148. );
  8149. }
  8150. break;
  8151. case protocol_version::v5:
  8152. if (
  8153. erased &&
  8154. [&] {
  8155. LockGuard<Mutex> lck (ep_.resend_pubrel_mtx_);
  8156. return ep_.resend_pubrel_.find(packet_id_) == ep_.resend_pubrel_.end();
  8157. } ()
  8158. ) {
  8159. ep_.send_publish_queue_one();
  8160. }
  8161. if (ep_.on_v5_pubcomp(packet_id_, reason_code_, force_move(props_))) {
  8162. ep_.on_mqtt_message_processed(
  8163. force_move(
  8164. std::get<0>(
  8165. any_cast<
  8166. std::tuple<any, process_type_sp>
  8167. >(session_life_keeper)
  8168. )
  8169. )
  8170. );
  8171. }
  8172. break;
  8173. default:
  8174. BOOST_ASSERT(false);
  8175. }
  8176. }
  8177. }
  8178. private:
  8179. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8180. ep_t& ep_;
  8181. bool all_read_;
  8182. packet_id_t packet_id_;
  8183. v5::pubcomp_reason_code reason_code_;
  8184. v5::properties props_;
  8185. };
  8186. friend struct process_pubcomp;
  8187. // process subscribe
  8188. struct process_subscribe : as::coroutine, std::enable_shared_from_this<process_subscribe> {
  8189. using ep_t = this_type;
  8190. using ep_t_sp = this_type_sp;
  8191. using process_type = process_subscribe;
  8192. using process_type_sp = std::shared_ptr<process_type>;
  8193. process_subscribe(
  8194. ep_t& ep,
  8195. bool all_read
  8196. ):ep_{ep},
  8197. all_read_{all_read} {
  8198. }
  8199. void operator()(
  8200. ep_t_sp spep,
  8201. any&& session_life_keeper,
  8202. parse_handler_variant var = std::size_t(0),
  8203. buffer remain_buf = buffer()
  8204. ) {
  8205. reenter(this) {
  8206. if (ep_.remaining_length_ < header_len_) {
  8207. ep_.call_protocol_error_handlers();
  8208. return;
  8209. }
  8210. // header
  8211. yield ep_.process_header(
  8212. force_move(spep),
  8213. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  8214. all_read_,
  8215. header_len_,
  8216. [this]
  8217. (auto&&... args ) {
  8218. (*this)(std::forward<decltype(args)>(args)...);
  8219. }
  8220. );
  8221. // packet_id
  8222. yield ep_.process_packet_id(
  8223. force_move(spep),
  8224. force_move(session_life_keeper),
  8225. force_move(variant_get<buffer>(var)),
  8226. [this]
  8227. (auto&&... args ) {
  8228. (*this)(std::forward<decltype(args)>(args)...);
  8229. }
  8230. );
  8231. packet_id_ = force_move(variant_get<packet_id_t>(var));
  8232. if (ep_.version_ == protocol_version::v5) {
  8233. // properties
  8234. yield ep_.process_properties(
  8235. force_move(spep),
  8236. force_move(session_life_keeper),
  8237. force_move(remain_buf),
  8238. [this]
  8239. (auto&&... args ) {
  8240. (*this)(std::forward<decltype(args)>(args)...);
  8241. }
  8242. );
  8243. props_ = force_move(variant_get<v5::properties>(var));
  8244. }
  8245. while (true) {
  8246. // topic_filter including share_name
  8247. yield ep_.process_string(
  8248. force_move(spep),
  8249. force_move(session_life_keeper),
  8250. force_move(remain_buf),
  8251. [this]
  8252. (auto&&... args ) {
  8253. (*this)(std::forward<decltype(args)>(args)...);
  8254. }
  8255. );
  8256. sn_tf_opt_ = parse_shared_subscription(variant_get<buffer>(var));
  8257. if (!sn_tf_opt_) {
  8258. MQTT_LOG("mqtt_impl", error)
  8259. << MQTT_ADD_VALUE(address, &ep_)
  8260. << "topic_filter parse error"
  8261. << " whole_topic_filter: "
  8262. << variant_get<buffer>(var);
  8263. ep_.send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  8264. ep_.call_protocol_error_handlers();
  8265. return;
  8266. }
  8267. // subscribe options
  8268. yield ep_.process_nbytes(
  8269. force_move(spep),
  8270. force_move(session_life_keeper),
  8271. force_move(remain_buf),
  8272. 1,
  8273. [this]
  8274. (auto&&... args ) {
  8275. (*this)(std::forward<decltype(args)>(args)...);
  8276. }
  8277. );
  8278. sub_opts_opt_.emplace(static_cast<std::uint8_t>(variant_get<buffer>(var)[0]));
  8279. if (sub_opts_opt_.value().get_qos() != qos::at_most_once &&
  8280. sub_opts_opt_.value().get_qos() != qos::at_least_once &&
  8281. sub_opts_opt_.value().get_qos() != qos::exactly_once) {
  8282. ep_.call_bad_message_error_handlers();
  8283. return;
  8284. }
  8285. entries_.emplace_back(
  8286. force_move(sn_tf_opt_.value().share_name),
  8287. force_move(sn_tf_opt_.value().topic_filter),
  8288. sub_opts_opt_.value()
  8289. );
  8290. if (ep_.remaining_length_ == 0) {
  8291. switch (ep_.version_) {
  8292. case protocol_version::v3_1_1:
  8293. if (ep_.on_subscribe(packet_id_, force_move(entries_))) {
  8294. ep_.on_mqtt_message_processed(
  8295. force_move(
  8296. std::get<0>(
  8297. any_cast<
  8298. std::tuple<any, process_type_sp>
  8299. >(session_life_keeper)
  8300. )
  8301. )
  8302. );
  8303. }
  8304. break;
  8305. case protocol_version::v5:
  8306. if (ep_.on_v5_subscribe(packet_id_, force_move(entries_), force_move(props_))) {
  8307. ep_.on_mqtt_message_processed(
  8308. force_move(
  8309. std::get<0>(
  8310. any_cast<
  8311. std::tuple<any, process_type_sp>
  8312. >(session_life_keeper)
  8313. )
  8314. )
  8315. );
  8316. }
  8317. break;
  8318. default:
  8319. BOOST_ASSERT(false);
  8320. }
  8321. return;
  8322. }
  8323. }
  8324. }
  8325. }
  8326. private:
  8327. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8328. ep_t& ep_;
  8329. bool all_read_;
  8330. packet_id_t packet_id_;
  8331. v5::properties props_;
  8332. optional<share_name_topic_filter> sn_tf_opt_;
  8333. optional<subscribe_options> sub_opts_opt_;
  8334. std::vector<subscribe_entry> entries_;
  8335. };
  8336. friend struct process_subscribe;
  8337. // process suback
  8338. struct process_suback : as::coroutine, std::enable_shared_from_this<process_suback> {
  8339. using ep_t = this_type;
  8340. using ep_t_sp = this_type_sp;
  8341. using process_type = process_suback;
  8342. using process_type_sp = std::shared_ptr<process_type>;
  8343. process_suback(
  8344. ep_t& ep,
  8345. bool all_read
  8346. ):ep_{ep},
  8347. all_read_{all_read} {
  8348. }
  8349. void operator()(
  8350. ep_t_sp spep,
  8351. any&& session_life_keeper,
  8352. parse_handler_variant var = std::size_t(0),
  8353. buffer remain_buf = buffer()
  8354. ) {
  8355. reenter(this) {
  8356. if (ep_.remaining_length_ < header_len_) {
  8357. ep_.call_protocol_error_handlers();
  8358. return;
  8359. }
  8360. // header
  8361. yield ep_.process_header(
  8362. force_move(spep),
  8363. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  8364. all_read_,
  8365. header_len_,
  8366. [this]
  8367. (auto&&... args ) {
  8368. (*this)(std::forward<decltype(args)>(args)...);
  8369. }
  8370. );
  8371. // packet_id
  8372. yield ep_.process_packet_id(
  8373. force_move(spep),
  8374. force_move(session_life_keeper),
  8375. force_move(variant_get<buffer>(var)),
  8376. [this]
  8377. (auto&&... args ) {
  8378. (*this)(std::forward<decltype(args)>(args)...);
  8379. }
  8380. );
  8381. packet_id_ = force_move(variant_get<packet_id_t>(var));
  8382. if (ep_.version_ == protocol_version::v5) {
  8383. // properties
  8384. yield ep_.process_properties(
  8385. force_move(spep),
  8386. force_move(session_life_keeper),
  8387. force_move(remain_buf),
  8388. [this]
  8389. (auto&&... args ) {
  8390. (*this)(std::forward<decltype(args)>(args)...);
  8391. }
  8392. );
  8393. props_ = force_move(variant_get<v5::properties>(var));
  8394. }
  8395. // suback reason codes
  8396. yield ep_.process_nbytes(
  8397. force_move(spep),
  8398. force_move(session_life_keeper),
  8399. force_move(remain_buf),
  8400. ep_.remaining_length_,
  8401. [this]
  8402. (auto&&... args ) {
  8403. (*this)(std::forward<decltype(args)>(args)...);
  8404. }
  8405. );
  8406. {
  8407. LockGuard<Mutex> lck_store (ep_.store_mtx_);
  8408. LockGuard<Mutex> lck_sub_unsub (ep_.sub_unsub_inflight_mtx_);
  8409. ep_.pid_man_.release_id(packet_id_);
  8410. ep_.sub_unsub_inflight_.erase(packet_id_);
  8411. }
  8412. switch (ep_.version_) {
  8413. case protocol_version::v3_1_1:
  8414. {
  8415. // TODO: We can avoid an allocation by casting the raw bytes of the
  8416. // MQTT_NS::buffer that is being parsed, and instead call the suback
  8417. // handler with an std::span and the MQTT_NS::buffer (as lifekeeper)
  8418. std::vector<suback_return_code> results;
  8419. auto& body = variant_get<buffer>(var);
  8420. results.resize(body.size());
  8421. std::transform(
  8422. body.begin(),
  8423. body.end(),
  8424. results.begin(),
  8425. // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180880
  8426. // The SUBACK Packet sent by the Server to the Client MUST
  8427. // contain a return code for each Topic Filter/QoS pair.
  8428. // This return code MUST either show the maximum QoS that
  8429. // was granted for that Subscription or indicate that the
  8430. // subscription failed [MQTT-3.8.4-5].
  8431. [&](auto const& e) -> suback_return_code {
  8432. return static_cast<suback_return_code>(e);
  8433. }
  8434. );
  8435. if (ep_.on_suback(packet_id_, force_move(results))) {
  8436. ep_.on_mqtt_message_processed(
  8437. force_move(
  8438. std::get<0>(
  8439. any_cast<
  8440. std::tuple<any, process_type_sp>
  8441. >(session_life_keeper)
  8442. )
  8443. )
  8444. );
  8445. }
  8446. break;
  8447. }
  8448. case protocol_version::v5:
  8449. {
  8450. // TODO: We can avoid an allocation by casting the raw bytes of the
  8451. // MQTT_NS::buffer that is being parsed, and instead call the suback
  8452. // handler with an std::span and the MQTT_NS::buffer (as lifekeeper)
  8453. std::vector<v5::suback_reason_code> reasons;
  8454. auto& body = variant_get<buffer>(var);
  8455. reasons.resize(body.size());
  8456. std::transform(
  8457. body.begin(),
  8458. body.end(),
  8459. reasons.begin(),
  8460. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901170
  8461. // The SUBACK packet sent by the Server to the Client MUST
  8462. // contain a Reason Code for each Topic Filter/Subscription
  8463. // Option pair [MQTT-3.8.4-6].
  8464. // This Reason Code MUST either show the maximum QoS that
  8465. // was granted for that Subscription or indicate that the
  8466. // subscription failed [MQTT-3.8.4-7].
  8467. [&](auto const& e) {
  8468. return static_cast<v5::suback_reason_code>(e);
  8469. }
  8470. );
  8471. if (ep_.on_v5_suback(packet_id_, force_move(reasons), force_move(props_))) {
  8472. ep_.on_mqtt_message_processed(
  8473. force_move(
  8474. std::get<0>(
  8475. any_cast<
  8476. std::tuple<any, process_type_sp>
  8477. >(session_life_keeper)
  8478. )
  8479. )
  8480. );
  8481. }
  8482. break;
  8483. }
  8484. default:
  8485. BOOST_ASSERT(false);
  8486. }
  8487. }
  8488. }
  8489. private:
  8490. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8491. ep_t& ep_;
  8492. bool all_read_;
  8493. packet_id_t packet_id_;
  8494. v5::properties props_;
  8495. };
  8496. friend struct process_suback;
  8497. // process unsubscribe
  8498. struct process_unsubscribe : as::coroutine, std::enable_shared_from_this<process_unsubscribe> {
  8499. using ep_t = this_type;
  8500. using ep_t_sp = this_type_sp;
  8501. using process_type = process_unsubscribe;
  8502. using process_type_sp = std::shared_ptr<process_type>;
  8503. process_unsubscribe(
  8504. ep_t& ep,
  8505. bool all_read
  8506. ):ep_{ep},
  8507. all_read_{all_read} {
  8508. }
  8509. void operator()(
  8510. ep_t_sp spep,
  8511. any&& session_life_keeper,
  8512. parse_handler_variant var = std::size_t(0),
  8513. buffer remain_buf = buffer()
  8514. ) {
  8515. reenter(this) {
  8516. if (ep_.remaining_length_ < header_len_) {
  8517. ep_.call_protocol_error_handlers();
  8518. return;
  8519. }
  8520. // header
  8521. yield ep_.process_header(
  8522. force_move(spep),
  8523. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  8524. all_read_,
  8525. header_len_,
  8526. [this]
  8527. (auto&&... args ) {
  8528. (*this)(std::forward<decltype(args)>(args)...);
  8529. }
  8530. );
  8531. // packet_id
  8532. yield ep_.process_packet_id(
  8533. force_move(spep),
  8534. force_move(session_life_keeper),
  8535. force_move(variant_get<buffer>(var)),
  8536. [this]
  8537. (auto&&... args ) {
  8538. (*this)(std::forward<decltype(args)>(args)...);
  8539. }
  8540. );
  8541. packet_id_ = force_move(variant_get<packet_id_t>(var));
  8542. if (ep_.version_ == protocol_version::v5) {
  8543. // properties
  8544. yield ep_.process_properties(
  8545. force_move(spep),
  8546. force_move(session_life_keeper),
  8547. force_move(remain_buf),
  8548. [this]
  8549. (auto&&... args ) {
  8550. (*this)(std::forward<decltype(args)>(args)...);
  8551. }
  8552. );
  8553. props_ = force_move(variant_get<v5::properties>(var));
  8554. }
  8555. while (true) {
  8556. // topic_filter including share_name
  8557. yield ep_.process_string(
  8558. force_move(spep),
  8559. force_move(session_life_keeper),
  8560. force_move(remain_buf),
  8561. [this]
  8562. (auto&&... args ) {
  8563. (*this)(std::forward<decltype(args)>(args)...);
  8564. }
  8565. );
  8566. sn_tf_opt_ = parse_shared_subscription(variant_get<buffer>(var));
  8567. if (!sn_tf_opt_) {
  8568. MQTT_LOG("mqtt_impl", error)
  8569. << MQTT_ADD_VALUE(address, &ep_)
  8570. << "topic_filter parse error"
  8571. << " whole_topic_filter: "
  8572. << variant_get<buffer>(var);
  8573. ep_.send_error_disconnect(v5::disconnect_reason_code::protocol_error);
  8574. ep_.call_protocol_error_handlers();
  8575. return;
  8576. }
  8577. entries_.emplace_back(
  8578. force_move(sn_tf_opt_.value().share_name),
  8579. force_move(sn_tf_opt_.value().topic_filter)
  8580. );
  8581. if (ep_.remaining_length_ == 0) {
  8582. switch (ep_.version_) {
  8583. case protocol_version::v3_1_1:
  8584. if (ep_.on_unsubscribe(packet_id_, force_move(entries_))) {
  8585. ep_.on_mqtt_message_processed(
  8586. force_move(
  8587. std::get<0>(
  8588. any_cast<
  8589. std::tuple<any, process_type_sp>
  8590. >(session_life_keeper)
  8591. )
  8592. )
  8593. );
  8594. }
  8595. break;
  8596. case protocol_version::v5:
  8597. if (ep_.on_v5_unsubscribe(packet_id_, force_move(entries_), force_move(props_))) {
  8598. ep_.on_mqtt_message_processed(
  8599. force_move(
  8600. std::get<0>(
  8601. any_cast<
  8602. std::tuple<any, process_type_sp>
  8603. >(session_life_keeper)
  8604. )
  8605. )
  8606. );
  8607. }
  8608. break;
  8609. default:
  8610. BOOST_ASSERT(false);
  8611. }
  8612. return;
  8613. }
  8614. }
  8615. }
  8616. }
  8617. private:
  8618. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8619. ep_t& ep_;
  8620. bool all_read_;
  8621. packet_id_t packet_id_;
  8622. v5::properties props_;
  8623. optional<share_name_topic_filter> sn_tf_opt_;
  8624. std::vector<unsubscribe_entry> entries_;
  8625. };
  8626. friend struct process_unsubscribe;
  8627. // process unsuback
  8628. struct process_unsuback : as::coroutine, std::enable_shared_from_this<process_unsuback> {
  8629. using ep_t = this_type;
  8630. using ep_t_sp = this_type_sp;
  8631. using process_type = process_unsuback;
  8632. using process_type_sp = std::shared_ptr<process_type>;
  8633. process_unsuback(
  8634. ep_t& ep,
  8635. bool all_read
  8636. ):ep_{ep},
  8637. all_read_{all_read} {
  8638. }
  8639. void operator()(
  8640. ep_t_sp spep,
  8641. any&& session_life_keeper,
  8642. parse_handler_variant var = std::size_t(0),
  8643. buffer remain_buf = buffer()
  8644. ) {
  8645. reenter(this) {
  8646. if (ep_.remaining_length_ < header_len_) {
  8647. ep_.call_protocol_error_handlers();
  8648. return;
  8649. }
  8650. // header
  8651. yield ep_.process_header(
  8652. force_move(spep),
  8653. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  8654. all_read_,
  8655. header_len_,
  8656. [this]
  8657. (auto&&... args ) {
  8658. (*this)(std::forward<decltype(args)>(args)...);
  8659. }
  8660. );
  8661. // packet_id
  8662. yield ep_.process_packet_id(
  8663. force_move(spep),
  8664. force_move(session_life_keeper),
  8665. force_move(variant_get<buffer>(var)),
  8666. [this]
  8667. (auto&&... args ) {
  8668. (*this)(std::forward<decltype(args)>(args)...);
  8669. }
  8670. );
  8671. packet_id_ = force_move(variant_get<packet_id_t>(var));
  8672. if (ep_.version_ == protocol_version::v5) {
  8673. // properties
  8674. yield ep_.process_properties(
  8675. force_move(spep),
  8676. force_move(session_life_keeper),
  8677. force_move(remain_buf),
  8678. [this]
  8679. (auto&&... args ) {
  8680. (*this)(std::forward<decltype(args)>(args)...);
  8681. }
  8682. );
  8683. props_ = force_move(variant_get<v5::properties>(var));
  8684. // unsuback reason codes
  8685. yield ep_.process_nbytes(
  8686. force_move(spep),
  8687. force_move(session_life_keeper),
  8688. force_move(remain_buf),
  8689. ep_.remaining_length_,
  8690. [this]
  8691. (auto&&... args ) {
  8692. (*this)(std::forward<decltype(args)>(args)...);
  8693. }
  8694. );
  8695. auto body = variant_get<buffer>(var);
  8696. reasons_.resize(body.size());
  8697. std::transform(
  8698. body.begin(),
  8699. body.end(),
  8700. reasons_.begin(),
  8701. [&](auto const& e) {
  8702. return static_cast<v5::unsuback_reason_code>(e);
  8703. }
  8704. );
  8705. }
  8706. {
  8707. LockGuard<Mutex> lck_store (ep_.store_mtx_);
  8708. LockGuard<Mutex> lck_sub_unsub (ep_.sub_unsub_inflight_mtx_);
  8709. ep_.pid_man_.release_id(packet_id_);
  8710. ep_.sub_unsub_inflight_.erase(packet_id_);
  8711. }
  8712. switch (ep_.version_) {
  8713. case protocol_version::v3_1_1:
  8714. if (ep_.on_unsuback(packet_id_)) {
  8715. ep_.on_mqtt_message_processed(
  8716. force_move(
  8717. std::get<0>(
  8718. any_cast<
  8719. std::tuple<any, process_type_sp>
  8720. >(session_life_keeper)
  8721. )
  8722. )
  8723. );
  8724. }
  8725. break;
  8726. case protocol_version::v5:
  8727. if (ep_.on_v5_unsuback(packet_id_, force_move(reasons_), force_move(props_))) {
  8728. ep_.on_mqtt_message_processed(
  8729. force_move(
  8730. std::get<0>(
  8731. any_cast<
  8732. std::tuple<any, process_type_sp>
  8733. >(session_life_keeper)
  8734. )
  8735. )
  8736. );
  8737. }
  8738. break;
  8739. default:
  8740. BOOST_ASSERT(false);
  8741. }
  8742. }
  8743. }
  8744. private:
  8745. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8746. ep_t& ep_;
  8747. bool all_read_;
  8748. packet_id_t packet_id_;
  8749. v5::properties props_;
  8750. std::vector<v5::unsuback_reason_code> reasons_;
  8751. };
  8752. friend struct process_unsuback;
  8753. // process pingreq
  8754. void process_pingreq(
  8755. any session_life_keeper
  8756. ) {
  8757. static constexpr std::size_t header_len = 0;
  8758. if (remaining_length_ != header_len) {
  8759. call_protocol_error_handlers();
  8760. return;
  8761. }
  8762. if (on_pingreq()) {
  8763. on_mqtt_message_processed(force_move(session_life_keeper));
  8764. }
  8765. }
  8766. // process pingresp
  8767. void process_pingresp(
  8768. any session_life_keeper
  8769. ) {
  8770. static constexpr std::size_t header_len = 0;
  8771. if (remaining_length_ != header_len) {
  8772. call_protocol_error_handlers();
  8773. return;
  8774. }
  8775. if (on_pingresp()) {
  8776. on_mqtt_message_processed(force_move(session_life_keeper));
  8777. }
  8778. if (pingresp_timeout_ != std::chrono::steady_clock::duration::zero()) {
  8779. LockGuard<Mutex> lck (mtx_tim_pingresp_);
  8780. tim_pingresp_.cancel();
  8781. }
  8782. }
  8783. // process disconnect
  8784. struct process_disconnect : as::coroutine, std::enable_shared_from_this<process_disconnect> {
  8785. using ep_t = this_type;
  8786. using ep_t_sp = this_type_sp;
  8787. using process_type = process_disconnect;
  8788. using process_type_sp = std::shared_ptr<process_type>;
  8789. process_disconnect(
  8790. ep_t& ep,
  8791. bool all_read
  8792. ):ep_{ep},
  8793. all_read_{all_read} {
  8794. }
  8795. void operator()(
  8796. ep_t_sp spep,
  8797. any&& session_life_keeper,
  8798. parse_handler_variant var = std::size_t(0),
  8799. buffer remain_buf = buffer()
  8800. ) {
  8801. reenter(this) {
  8802. if (ep_.remaining_length_ > 0) {
  8803. if (ep_.version_ != protocol_version::v5) {
  8804. ep_.call_protocol_error_handlers();
  8805. return;
  8806. }
  8807. // header
  8808. yield ep_.process_header(
  8809. force_move(spep),
  8810. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  8811. all_read_,
  8812. header_len_,
  8813. [this]
  8814. (auto&&... args ) {
  8815. (*this)(std::forward<decltype(args)>(args)...);
  8816. }
  8817. );
  8818. // reason_code
  8819. yield ep_.process_nbytes(
  8820. force_move(spep),
  8821. force_move(session_life_keeper),
  8822. force_move(variant_get<buffer>(var)),
  8823. 1,
  8824. [this]
  8825. (auto&&... args ) {
  8826. (*this)(std::forward<decltype(args)>(args)...);
  8827. }
  8828. );
  8829. reason_code_ = static_cast<v5::disconnect_reason_code>(variant_get<buffer>(var)[0]);
  8830. // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901210
  8831. // If the Remaining Length is 0, there is no property length and the value of 0 is used
  8832. if (ep_.remaining_length_ > 0) {
  8833. yield ep_.process_properties(
  8834. force_move(spep),
  8835. force_move(session_life_keeper),
  8836. force_move(remain_buf),
  8837. [this]
  8838. (auto&&... args ) {
  8839. (*this)(std::forward<decltype(args)>(args)...);
  8840. }
  8841. );
  8842. props_ = force_move(variant_get<v5::properties>(var));
  8843. }
  8844. switch (ep_.version_) {
  8845. case protocol_version::v3_1_1:
  8846. ep_.on_disconnect();
  8847. break;
  8848. case protocol_version::v5:
  8849. ep_.on_v5_disconnect(reason_code_, force_move(props_));
  8850. break;
  8851. default:
  8852. BOOST_ASSERT(false);
  8853. }
  8854. MQTT_LOG("mqtt_impl", trace)
  8855. << MQTT_ADD_VALUE(address, this)
  8856. << "receive DISCONNECT call shutdown";
  8857. ep_.shutdown(*ep_.socket_);
  8858. ep_.on_mqtt_message_processed(
  8859. force_move(
  8860. std::get<0>(
  8861. any_cast<
  8862. std::tuple<any, process_type_sp>
  8863. >(session_life_keeper)
  8864. )
  8865. )
  8866. );
  8867. return;
  8868. }
  8869. switch (ep_.version_) {
  8870. case protocol_version::v3_1_1:
  8871. ep_.on_disconnect();
  8872. break;
  8873. case protocol_version::v5:
  8874. ep_.on_v5_disconnect(reason_code_, force_move(props_));
  8875. break;
  8876. default:
  8877. BOOST_ASSERT(false);
  8878. }
  8879. MQTT_LOG("mqtt_impl", trace)
  8880. << MQTT_ADD_VALUE(address, this)
  8881. << "receive DISCONNECT call shutdown";
  8882. ep_.shutdown(*ep_.socket_);
  8883. ep_.on_mqtt_message_processed(
  8884. force_move(
  8885. session_life_keeper
  8886. )
  8887. );
  8888. }
  8889. }
  8890. private:
  8891. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8892. ep_t& ep_;
  8893. bool all_read_;
  8894. v5::disconnect_reason_code reason_code_;
  8895. v5::properties props_;
  8896. };
  8897. friend struct process_disconnect;
  8898. // process auth
  8899. struct process_auth : as::coroutine, std::enable_shared_from_this<process_auth> {
  8900. using ep_t = this_type;
  8901. using ep_t_sp = this_type_sp;
  8902. using process_type = process_auth;
  8903. using process_type_sp = std::shared_ptr<process_type>;
  8904. process_auth(
  8905. ep_t& ep,
  8906. bool all_read
  8907. ):ep_{ep},
  8908. all_read_{all_read} {
  8909. }
  8910. void operator()(
  8911. ep_t_sp spep,
  8912. any&& session_life_keeper,
  8913. parse_handler_variant var = std::size_t(0),
  8914. buffer remain_buf = buffer()
  8915. ) {
  8916. reenter(this) {
  8917. if (ep_.version_ != protocol_version::v5) {
  8918. ep_.call_protocol_error_handlers();
  8919. return;
  8920. }
  8921. if (ep_.remaining_length_ > 0) {
  8922. // header
  8923. yield ep_.process_header(
  8924. force_move(spep),
  8925. std::make_tuple(force_move(session_life_keeper), this->shared_from_this()),
  8926. all_read_,
  8927. header_len_,
  8928. [this]
  8929. (auto&&... args ) {
  8930. (*this)(std::forward<decltype(args)>(args)...);
  8931. }
  8932. );
  8933. // reason_code
  8934. yield ep_.process_nbytes(
  8935. force_move(spep),
  8936. force_move(session_life_keeper),
  8937. force_move(variant_get<buffer>(var)),
  8938. 1,
  8939. [this]
  8940. (auto&&... args ) {
  8941. (*this)(std::forward<decltype(args)>(args)...);
  8942. }
  8943. );
  8944. reason_code_ = static_cast<v5::auth_reason_code>(variant_get<buffer>(var)[0]);
  8945. yield ep_.process_properties(
  8946. force_move(spep),
  8947. force_move(session_life_keeper),
  8948. force_move(remain_buf),
  8949. [this]
  8950. (auto&&... args ) {
  8951. (*this)(std::forward<decltype(args)>(args)...);
  8952. }
  8953. );
  8954. props_ = force_move(variant_get<v5::properties>(var));
  8955. BOOST_ASSERT(ep_.version_ == protocol_version::v5);
  8956. if (ep_.on_v5_auth(reason_code_, force_move(props_))) {
  8957. ep_.on_mqtt_message_processed(
  8958. force_move(
  8959. std::get<0>(
  8960. any_cast<
  8961. std::tuple<any, process_type_sp>
  8962. >(session_life_keeper)
  8963. )
  8964. )
  8965. );
  8966. }
  8967. return;
  8968. }
  8969. BOOST_ASSERT(ep_.version_ == protocol_version::v5);
  8970. if (ep_.on_v5_auth(reason_code_, force_move(props_))) {
  8971. ep_.on_mqtt_message_processed(
  8972. force_move(
  8973. session_life_keeper
  8974. )
  8975. );
  8976. }
  8977. }
  8978. }
  8979. private:
  8980. static constexpr std::size_t header_len_ = sizeof(packet_id_t); // Packet Id
  8981. this_type& ep_;
  8982. bool all_read_;
  8983. v5::auth_reason_code reason_code_;
  8984. v5::properties props_;
  8985. };
  8986. friend struct process_auth;
  8987. template <typename F, typename AF>
  8988. void auto_pub_response(F const& f, AF const& af) {
  8989. if (auto_pub_response_) {
  8990. if (async_operation_) af();
  8991. else f();
  8992. }
  8993. }
  8994. // Blocking senders.
  8995. void send_connect(
  8996. buffer client_id,
  8997. optional<buffer> user_name,
  8998. optional<buffer> password,
  8999. optional<will> w,
  9000. std::uint16_t keep_alive_sec,
  9001. v5::properties props
  9002. ) {
  9003. shutdown_requested_ = false;
  9004. switch (version_) {
  9005. case protocol_version::v3_1_1:
  9006. do_sync_write(
  9007. v3_1_1::connect_message(
  9008. keep_alive_sec,
  9009. force_move(client_id),
  9010. clean_session(),
  9011. force_move(w),
  9012. force_move(user_name),
  9013. force_move(password)
  9014. )
  9015. );
  9016. break;
  9017. case protocol_version::v5:
  9018. update_values_and_props_on_start_connection(props);
  9019. do_sync_write(
  9020. v5::connect_message(
  9021. keep_alive_sec,
  9022. force_move(client_id),
  9023. clean_start(),
  9024. force_move(w),
  9025. force_move(user_name),
  9026. force_move(password),
  9027. force_move(props)
  9028. )
  9029. );
  9030. break;
  9031. default:
  9032. BOOST_ASSERT(false);
  9033. break;
  9034. }
  9035. }
  9036. void send_connack(
  9037. bool session_present,
  9038. variant<connect_return_code, v5::connect_reason_code> reason_code,
  9039. v5::properties props
  9040. ) {
  9041. switch (version_) {
  9042. case protocol_version::v3_1_1: {
  9043. auto msg = v3_1_1::connack_message(
  9044. session_present,
  9045. variant_get<connect_return_code>(reason_code)
  9046. );
  9047. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9048. throw packet_size_error();
  9049. }
  9050. do_sync_write(force_move(msg));
  9051. } break;
  9052. case protocol_version::v5: {
  9053. update_values_and_props_on_start_connection(props);
  9054. auto msg = v5::connack_message(
  9055. session_present,
  9056. variant_get<v5::connect_reason_code>(reason_code),
  9057. force_move(props)
  9058. );
  9059. do_sync_write(force_move(msg));
  9060. } break;
  9061. default:
  9062. BOOST_ASSERT(false);
  9063. break;
  9064. }
  9065. }
  9066. template <typename PublishMessage>
  9067. std::enable_if_t<
  9068. std::is_same<
  9069. PublishMessage,
  9070. v5::basic_publish_message<PacketIdBytes>
  9071. >::value
  9072. >
  9073. remove_topic_alias(
  9074. PublishMessage& msg,
  9075. any& life_keeper
  9076. ) {
  9077. if (msg.topic().empty()) {
  9078. // Recover topic alias for store
  9079. if (auto ta_opt = get_topic_alias_from_props(msg.props())) {
  9080. LockGuard<Mutex> lck (topic_alias_send_mtx_);
  9081. std::string t;
  9082. if (topic_alias_send_) t = topic_alias_send_.value().find(ta_opt.value());
  9083. if (t.empty()) {
  9084. MQTT_LOG("mqtt_impl", error)
  9085. << MQTT_ADD_VALUE(address, this)
  9086. << "publish topic_name is empty, topic alias " << ta_opt.value()
  9087. << " is not registered." ;
  9088. throw protocol_error();
  9089. }
  9090. else {
  9091. MQTT_LOG("mqtt_impl", trace)
  9092. << MQTT_ADD_VALUE(address, this)
  9093. << "topia alias : " << t << " - " << ta_opt.value() << " is recovered for store." ;
  9094. auto topic_name_buf = allocate_buffer(t);
  9095. msg.set_topic_name(as::buffer(topic_name_buf));
  9096. life_keeper = std::make_tuple(force_move(life_keeper), force_move(topic_name_buf));
  9097. }
  9098. }
  9099. else {
  9100. MQTT_LOG("mqtt_impl", error)
  9101. << MQTT_ADD_VALUE(address, this)
  9102. << "publish topic_name is empty, no topic alias set.";
  9103. throw protocol_error();
  9104. }
  9105. }
  9106. msg.remove_prop(v5::property::id::topic_alias);
  9107. }
  9108. template <typename PublishMessage>
  9109. std::enable_if_t<
  9110. !std::is_same<
  9111. PublishMessage,
  9112. v5::basic_publish_message<PacketIdBytes>
  9113. >::value
  9114. >
  9115. remove_topic_alias(PublishMessage&, any&) {}
  9116. template <typename PublishMessage>
  9117. std::enable_if_t<
  9118. std::is_same<
  9119. PublishMessage,
  9120. v5::basic_publish_message<PacketIdBytes>
  9121. >::value,
  9122. std::tuple<PublishMessage, any>
  9123. >
  9124. apply_topic_alias(PublishMessage msg, any life_keeper) {
  9125. auto clear_topic_name_and_add_topic_alias =
  9126. [&](topic_alias_t ta) {
  9127. auto topic_name_buf = buffer();
  9128. msg.set_topic_name(as::buffer(topic_name_buf));
  9129. life_keeper = std::make_tuple(force_move(life_keeper), force_move(topic_name_buf));
  9130. msg.add_prop(v5::property::topic_alias(ta));
  9131. };
  9132. if (msg.topic().empty()) {
  9133. if (auto ta_opt = get_topic_alias_from_props(msg.props())) {
  9134. LockGuard<Mutex> lck (topic_alias_send_mtx_);
  9135. std::string t;
  9136. if (topic_alias_send_) t = topic_alias_send_.value().find(ta_opt.value());
  9137. if (t.empty()) {
  9138. MQTT_LOG("mqtt_impl", error)
  9139. << MQTT_ADD_VALUE(address, this)
  9140. << "publish topic_name is empty, topic alias " << ta_opt.value()
  9141. << " is not registered." ;
  9142. throw protocol_error();
  9143. }
  9144. }
  9145. else {
  9146. MQTT_LOG("mqtt_impl", error)
  9147. << MQTT_ADD_VALUE(address, this)
  9148. << "publish topic_name is empty, no topic alias set.";
  9149. throw protocol_error();
  9150. }
  9151. }
  9152. else {
  9153. if (auto ta_opt = get_topic_alias_from_props(msg.props())) {
  9154. MQTT_LOG("mqtt_impl", trace)
  9155. << MQTT_ADD_VALUE(address, this)
  9156. << "topia alias : " << msg.topic() << " - " << ta_opt.value() << " is registered." ;
  9157. LockGuard<Mutex> lck (topic_alias_send_mtx_);
  9158. if (topic_alias_send_) {
  9159. topic_alias_send_.value().insert_or_update(
  9160. msg.topic(),
  9161. ta_opt.value()
  9162. );
  9163. }
  9164. }
  9165. else if (auto_map_topic_alias_send_) {
  9166. LockGuard<Mutex> lck (topic_alias_send_mtx_);
  9167. if (topic_alias_send_) {
  9168. auto lru_ta = topic_alias_send_.value().get_lru_alias();
  9169. if (auto ta_opt = topic_alias_send_.value().find(msg.topic())) {
  9170. MQTT_LOG("mqtt_impl", trace)
  9171. << MQTT_ADD_VALUE(address, this)
  9172. << "topia alias : " << msg.topic() << " - " << ta_opt.value() << " is found." ;
  9173. topic_alias_send_.value().insert_or_update(msg.topic(), ta_opt.value()); // update ts
  9174. clear_topic_name_and_add_topic_alias(ta_opt.value());
  9175. }
  9176. else {
  9177. topic_alias_send_.value().insert_or_update(msg.topic(), lru_ta); // remap topic alias
  9178. msg.add_prop(v5::property::topic_alias(lru_ta));
  9179. }
  9180. }
  9181. }
  9182. else if (auto_replace_topic_alias_send_) {
  9183. LockGuard<Mutex> lck (topic_alias_send_mtx_);
  9184. if (topic_alias_send_) {
  9185. if (auto ta_opt = topic_alias_send_.value().find(msg.topic())) {
  9186. MQTT_LOG("mqtt_impl", trace)
  9187. << MQTT_ADD_VALUE(address, this)
  9188. << "topia alias : " << msg.topic() << " - " << ta_opt.value() << " is found." ;
  9189. topic_alias_send_.value().insert_or_update(msg.topic(), ta_opt.value()); // update ts
  9190. clear_topic_name_and_add_topic_alias(ta_opt.value());
  9191. }
  9192. }
  9193. }
  9194. }
  9195. return std::make_tuple(force_move(msg), force_move(life_keeper));
  9196. }
  9197. template <typename PublishMessage>
  9198. std::enable_if_t<
  9199. !std::is_same<
  9200. PublishMessage,
  9201. v5::basic_publish_message<PacketIdBytes>
  9202. >::value,
  9203. std::tuple<PublishMessage, any>
  9204. >
  9205. apply_topic_alias(PublishMessage msg, any life_keeper) {
  9206. return std::make_tuple(force_move(msg), force_move(life_keeper));
  9207. }
  9208. template <typename PublishMessage, typename SerializePublish, typename ReceiveMaximumProc>
  9209. bool preprocess_publish_message(
  9210. PublishMessage const& msg,
  9211. any life_keeper,
  9212. SerializePublish&& serialize_publish,
  9213. ReceiveMaximumProc&& receive_maximum_proc,
  9214. bool register_pid = false
  9215. ) {
  9216. auto qos_value = msg.get_qos();
  9217. if (qos_value == qos::at_least_once || qos_value == qos::exactly_once) {
  9218. auto store_msg = msg;
  9219. remove_topic_alias(store_msg, life_keeper);
  9220. store_msg.set_dup(true);
  9221. auto packet_id = store_msg.packet_id();
  9222. LockGuard<Mutex> lck (store_mtx_);
  9223. if (register_pid) {
  9224. auto ret = pid_man_.register_id(packet_id);
  9225. (void)ret;
  9226. BOOST_ASSERT(ret);
  9227. }
  9228. store_.insert(
  9229. packet_id,
  9230. qos_value == qos::at_least_once
  9231. ? control_packet_type::puback
  9232. : control_packet_type::pubrec,
  9233. store_msg,
  9234. force_move(life_keeper)
  9235. );
  9236. (this->*std::forward<decltype(serialize_publish)>(serialize_publish))(store_msg);
  9237. return std::forward<decltype(receive_maximum_proc)>(receive_maximum_proc)(force_move(store_msg));
  9238. }
  9239. return true;
  9240. }
  9241. template <typename ConstBufferSequence>
  9242. typename std::enable_if<
  9243. as::is_const_buffer_sequence<ConstBufferSequence>::value
  9244. >::type
  9245. send_publish(
  9246. packet_id_t packet_id,
  9247. as::const_buffer topic_name,
  9248. ConstBufferSequence payloads,
  9249. publish_options pubopts,
  9250. v5::properties props,
  9251. any life_keeper) {
  9252. auto do_send_publish =
  9253. [&](auto msg, auto&& serialize_publish, auto&& receive_maximum_proc) {
  9254. auto msg_lk = apply_topic_alias(msg, life_keeper);
  9255. if (maximum_packet_size_send_ < size<PacketIdBytes>(std::get<0>(msg_lk))) {
  9256. if (packet_id != 0) {
  9257. LockGuard<Mutex> lck_store (store_mtx_);
  9258. pid_man_.release_id(packet_id);
  9259. }
  9260. throw packet_size_error();
  9261. }
  9262. if (preprocess_publish_message(
  9263. msg,
  9264. life_keeper,
  9265. std::forward<decltype(serialize_publish)>(serialize_publish),
  9266. std::forward<decltype(receive_maximum_proc)>(receive_maximum_proc)
  9267. )
  9268. ) {
  9269. do_sync_write(force_move(std::get<0>(msg_lk)));
  9270. }
  9271. };
  9272. switch (version_) {
  9273. case protocol_version::v3_1_1:
  9274. do_send_publish(
  9275. v3_1_1::basic_publish_message<PacketIdBytes>(
  9276. packet_id,
  9277. topic_name,
  9278. force_move(payloads),
  9279. pubopts
  9280. ),
  9281. &endpoint::on_serialize_publish_message,
  9282. [] (auto&&) { return true; }
  9283. );
  9284. break;
  9285. case protocol_version::v5:
  9286. do_send_publish(
  9287. v5::basic_publish_message<PacketIdBytes>(
  9288. packet_id,
  9289. topic_name,
  9290. force_move(payloads),
  9291. pubopts,
  9292. force_move(props)
  9293. ),
  9294. &endpoint::on_serialize_v5_publish_message,
  9295. [this] (v5::basic_publish_message<PacketIdBytes>&& msg) {
  9296. if (publish_send_count_.load() == publish_send_max_) {
  9297. LockGuard<Mutex> lck (publish_send_queue_mtx_);
  9298. publish_send_queue_.emplace_back(force_move(msg), false);
  9299. return false;
  9300. }
  9301. MQTT_LOG("mqtt_impl", trace)
  9302. << MQTT_ADD_VALUE(address, this)
  9303. << "increment publish_send_count_:" << publish_send_count_.load();
  9304. ++publish_send_count_;
  9305. return true;
  9306. }
  9307. );
  9308. break;
  9309. default:
  9310. BOOST_ASSERT(false);
  9311. break;
  9312. }
  9313. }
  9314. void send_puback(
  9315. packet_id_t packet_id,
  9316. v5::puback_reason_code reason,
  9317. v5::properties props
  9318. ) {
  9319. switch (version_) {
  9320. case protocol_version::v3_1_1: {
  9321. auto msg = v3_1_1::basic_puback_message<PacketIdBytes>(packet_id);
  9322. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9323. throw packet_size_error();
  9324. }
  9325. do_sync_write(force_move(msg));
  9326. } break;
  9327. case protocol_version::v5: {
  9328. auto msg = v5::basic_puback_message<PacketIdBytes>(packet_id, reason, force_move(props));
  9329. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9330. throw packet_size_error();
  9331. }
  9332. do_sync_write(force_move(msg));
  9333. erase_publish_received(packet_id);
  9334. } break;
  9335. default:
  9336. BOOST_ASSERT(false);
  9337. break;
  9338. }
  9339. on_pub_res_sent(packet_id);
  9340. }
  9341. void send_pubrec(
  9342. packet_id_t packet_id,
  9343. v5::pubrec_reason_code reason,
  9344. v5::properties props
  9345. ) {
  9346. switch (version_) {
  9347. case protocol_version::v3_1_1: {
  9348. auto msg = v3_1_1::basic_pubrec_message<PacketIdBytes>(packet_id);
  9349. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9350. throw packet_size_error();
  9351. }
  9352. do_sync_write(force_move(msg));
  9353. } break;
  9354. case protocol_version::v5: {
  9355. auto msg = v5::basic_pubrec_message<PacketIdBytes>(packet_id, reason, force_move(props));
  9356. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9357. throw packet_size_error();
  9358. }
  9359. do_sync_write(force_move(msg));
  9360. erase_publish_received(packet_id);
  9361. } break;
  9362. default:
  9363. BOOST_ASSERT(false);
  9364. break;
  9365. }
  9366. }
  9367. void send_pubrel(
  9368. packet_id_t packet_id,
  9369. v5::pubrel_reason_code reason,
  9370. v5::properties props,
  9371. any life_keeper
  9372. ) {
  9373. auto impl =
  9374. [&](auto msg, auto const& serialize) {
  9375. {
  9376. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9377. throw packet_size_error();
  9378. }
  9379. LockGuard<Mutex> lck (store_mtx_);
  9380. // insert if not registerd (start from pubrel sending case)
  9381. if (pid_man_.register_id(packet_id)) {
  9382. LockGuard<Mutex> lck_resend_pubrel (resend_pubrel_mtx_);
  9383. resend_pubrel_.insert(packet_id);
  9384. }
  9385. // publish store is erased when pubrec is received.
  9386. // pubrel store is erased when pubcomp is received.
  9387. // If invalid client send pubrec twice with the same packet id,
  9388. // then send corresponding pubrel twice is a possible client/server
  9389. // implementation.
  9390. // In this case, overwrite store_.
  9391. if (store_.insert_or_update(
  9392. packet_id,
  9393. control_packet_type::pubcomp,
  9394. msg,
  9395. force_move(life_keeper)
  9396. ) == store_insert_update_result::updated
  9397. ) {
  9398. MQTT_LOG("mqtt_impl", warning)
  9399. << MQTT_ADD_VALUE(address, this)
  9400. << "overwrite pubrel"
  9401. << " packet_id:" << packet_id;
  9402. }
  9403. }
  9404. (this->*serialize)(msg);
  9405. do_sync_write(force_move(msg));
  9406. };
  9407. switch (version_) {
  9408. case protocol_version::v3_1_1:
  9409. impl(
  9410. v3_1_1::basic_pubrel_message<PacketIdBytes>(packet_id),
  9411. &endpoint::on_serialize_pubrel_message
  9412. );
  9413. break;
  9414. case protocol_version::v5:
  9415. impl(
  9416. v5::basic_pubrel_message<PacketIdBytes>(packet_id, reason, force_move(props)),
  9417. &endpoint::on_serialize_v5_pubrel_message
  9418. );
  9419. break;
  9420. default:
  9421. BOOST_ASSERT(false);
  9422. break;
  9423. }
  9424. }
  9425. void store_pubrel(
  9426. packet_id_t packet_id,
  9427. v5::pubrel_reason_code reason,
  9428. v5::properties props,
  9429. any life_keeper
  9430. ) {
  9431. auto impl =
  9432. [&](auto msg, auto const& serialize) {
  9433. {
  9434. LockGuard<Mutex> lck (store_mtx_);
  9435. // insert if not registerd (start from pubrel sending case)
  9436. pid_man_.register_id(packet_id);
  9437. auto ret = store_.insert(
  9438. packet_id,
  9439. control_packet_type::pubcomp,
  9440. msg,
  9441. force_move(life_keeper)
  9442. );
  9443. (void)ret;
  9444. BOOST_ASSERT(ret);
  9445. }
  9446. (this->*serialize)(msg);
  9447. };
  9448. switch (version_) {
  9449. case protocol_version::v3_1_1:
  9450. impl(
  9451. v3_1_1::basic_pubrel_message<PacketIdBytes>(packet_id),
  9452. &endpoint::on_serialize_pubrel_message
  9453. );
  9454. break;
  9455. case protocol_version::v5:
  9456. impl(
  9457. v5::basic_pubrel_message<PacketIdBytes>(packet_id, reason, force_move(props)),
  9458. &endpoint::on_serialize_v5_pubrel_message
  9459. );
  9460. break;
  9461. default:
  9462. BOOST_ASSERT(false);
  9463. break;
  9464. }
  9465. }
  9466. void send_pubcomp(
  9467. packet_id_t packet_id,
  9468. v5::pubcomp_reason_code reason,
  9469. v5::properties props
  9470. ) {
  9471. switch (version_) {
  9472. case protocol_version::v3_1_1: {
  9473. auto msg = v3_1_1::basic_pubcomp_message<PacketIdBytes>(packet_id);
  9474. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9475. throw packet_size_error();
  9476. }
  9477. do_sync_write(force_move(msg));
  9478. } break;
  9479. case protocol_version::v5: {
  9480. auto msg = v5::basic_pubcomp_message<PacketIdBytes>(packet_id, reason, force_move(props));
  9481. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9482. throw packet_size_error();
  9483. }
  9484. do_sync_write(force_move(msg));
  9485. } break;
  9486. default:
  9487. BOOST_ASSERT(false);
  9488. break;
  9489. }
  9490. on_pub_res_sent(packet_id);
  9491. }
  9492. void send_subscribe(
  9493. std::vector<std::tuple<as::const_buffer, subscribe_options>> params,
  9494. packet_id_t packet_id,
  9495. v5::properties props
  9496. ) {
  9497. for(auto const& p : params)
  9498. {
  9499. (void)p;
  9500. BOOST_ASSERT(
  9501. std::get<1>(p).get_qos() == qos::at_most_once ||
  9502. std::get<1>(p).get_qos() == qos::at_least_once ||
  9503. std::get<1>(p).get_qos() == qos::exactly_once
  9504. );
  9505. }
  9506. switch (version_) {
  9507. case protocol_version::v3_1_1: {
  9508. auto msg = v3_1_1::basic_subscribe_message<PacketIdBytes>(force_move(params), packet_id);
  9509. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9510. {
  9511. LockGuard<Mutex> lck_store (store_mtx_);
  9512. pid_man_.release_id(packet_id);
  9513. }
  9514. throw packet_size_error();
  9515. }
  9516. {
  9517. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  9518. sub_unsub_inflight_.insert(packet_id);
  9519. }
  9520. do_sync_write(force_move(msg));
  9521. } break;
  9522. case protocol_version::v5: {
  9523. auto msg = v5::basic_subscribe_message<PacketIdBytes>(force_move(params), packet_id, force_move(props));
  9524. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9525. {
  9526. LockGuard<Mutex> lck_store (store_mtx_);
  9527. pid_man_.release_id(packet_id);
  9528. }
  9529. throw packet_size_error();
  9530. }
  9531. {
  9532. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  9533. sub_unsub_inflight_.insert(packet_id);
  9534. }
  9535. do_sync_write(force_move(msg));
  9536. } break;
  9537. default:
  9538. BOOST_ASSERT(false);
  9539. break;
  9540. }
  9541. }
  9542. void send_suback(
  9543. variant<std::vector<suback_return_code>, std::vector<v5::suback_reason_code>> params,
  9544. packet_id_t packet_id,
  9545. v5::properties props
  9546. ) {
  9547. switch (version_) {
  9548. case protocol_version::v3_1_1: {
  9549. auto msg = v3_1_1::basic_suback_message<PacketIdBytes>(
  9550. force_move(variant_get<std::vector<suback_return_code>>(params)),
  9551. packet_id
  9552. );
  9553. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9554. throw packet_size_error();
  9555. }
  9556. do_sync_write(force_move(msg));
  9557. } break;
  9558. case protocol_version::v5: {
  9559. auto msg = v5::basic_suback_message<PacketIdBytes>(
  9560. force_move(variant_get<std::vector<v5::suback_reason_code>>(params)),
  9561. packet_id,
  9562. force_move(props)
  9563. );
  9564. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9565. throw packet_size_error();
  9566. }
  9567. do_sync_write(force_move(msg));
  9568. } break;
  9569. default:
  9570. BOOST_ASSERT(false);
  9571. break;
  9572. }
  9573. }
  9574. void send_unsubscribe(
  9575. std::vector<as::const_buffer> params,
  9576. packet_id_t packet_id,
  9577. v5::properties props
  9578. ) {
  9579. switch (version_) {
  9580. case protocol_version::v3_1_1: {
  9581. auto msg = v3_1_1::basic_unsubscribe_message<PacketIdBytes>(force_move(params), packet_id);
  9582. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9583. {
  9584. LockGuard<Mutex> lck_store (store_mtx_);
  9585. pid_man_.release_id(packet_id);
  9586. }
  9587. throw packet_size_error();
  9588. }
  9589. {
  9590. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  9591. sub_unsub_inflight_.insert(packet_id);
  9592. }
  9593. do_sync_write(force_move(msg));
  9594. } break;
  9595. case protocol_version::v5: {
  9596. auto msg = v5::basic_unsubscribe_message<PacketIdBytes>(force_move(params), packet_id, force_move(props));
  9597. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9598. {
  9599. LockGuard<Mutex> lck_store (store_mtx_);
  9600. pid_man_.release_id(packet_id);
  9601. }
  9602. throw packet_size_error();
  9603. }
  9604. {
  9605. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  9606. sub_unsub_inflight_.insert(packet_id);
  9607. }
  9608. do_sync_write(force_move(msg));
  9609. } break;
  9610. default:
  9611. BOOST_ASSERT(false);
  9612. break;
  9613. }
  9614. }
  9615. void send_unsuback(
  9616. packet_id_t packet_id
  9617. ) {
  9618. switch (version_) {
  9619. case protocol_version::v3_1_1: {
  9620. auto msg = v3_1_1::basic_unsuback_message<PacketIdBytes>(packet_id);
  9621. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9622. throw packet_size_error();
  9623. }
  9624. do_sync_write(force_move(msg));
  9625. } break;
  9626. case protocol_version::v5:
  9627. BOOST_ASSERT(false);
  9628. break;
  9629. default:
  9630. BOOST_ASSERT(false);
  9631. break;
  9632. }
  9633. }
  9634. void send_unsuback(
  9635. std::vector<v5::unsuback_reason_code> params,
  9636. packet_id_t packet_id,
  9637. v5::properties props
  9638. ) {
  9639. switch (version_) {
  9640. case protocol_version::v3_1_1:
  9641. BOOST_ASSERT(false);
  9642. break;
  9643. case protocol_version::v5: {
  9644. auto msg = v5::basic_unsuback_message<PacketIdBytes>(force_move(params), packet_id, force_move(props));
  9645. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9646. throw packet_size_error();
  9647. }
  9648. do_sync_write(force_move(msg));
  9649. } break;
  9650. default:
  9651. BOOST_ASSERT(false);
  9652. break;
  9653. }
  9654. }
  9655. void send_pingreq() {
  9656. switch (version_) {
  9657. case protocol_version::v3_1_1: {
  9658. auto msg = v3_1_1::pingreq_message();
  9659. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9660. throw packet_size_error();
  9661. }
  9662. do_sync_write(force_move(msg));
  9663. set_pingresp_timer();
  9664. } break;
  9665. case protocol_version::v5: {
  9666. auto msg = v5::pingreq_message();
  9667. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9668. throw packet_size_error();
  9669. }
  9670. do_sync_write(force_move(msg));
  9671. set_pingresp_timer();
  9672. } break;
  9673. default:
  9674. BOOST_ASSERT(false);
  9675. break;
  9676. }
  9677. }
  9678. void send_pingresp() {
  9679. switch (version_) {
  9680. case protocol_version::v3_1_1: {
  9681. auto msg = v3_1_1::pingresp_message();
  9682. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9683. throw packet_size_error();
  9684. }
  9685. do_sync_write(force_move(msg));
  9686. } break;
  9687. case protocol_version::v5: {
  9688. auto msg = v5::pingresp_message();
  9689. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9690. throw packet_size_error();
  9691. }
  9692. do_sync_write(force_move(msg));
  9693. } break;
  9694. default:
  9695. BOOST_ASSERT(false);
  9696. break;
  9697. }
  9698. }
  9699. void send_auth(
  9700. v5::auth_reason_code reason,
  9701. v5::properties props
  9702. ) {
  9703. switch (version_) {
  9704. case protocol_version::v3_1_1:
  9705. BOOST_ASSERT(false);
  9706. break;
  9707. case protocol_version::v5: {
  9708. auto msg = v5::auth_message(reason, force_move(props));
  9709. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9710. throw packet_size_error();
  9711. }
  9712. do_sync_write(force_move(msg));
  9713. } break;
  9714. default:
  9715. BOOST_ASSERT(false);
  9716. break;
  9717. }
  9718. }
  9719. void send_disconnect(
  9720. v5::disconnect_reason_code reason,
  9721. v5::properties props
  9722. ) {
  9723. switch (version_) {
  9724. case protocol_version::v3_1_1: {
  9725. auto msg = v3_1_1::disconnect_message();
  9726. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9727. throw packet_size_error();
  9728. }
  9729. do_sync_write(force_move(msg));
  9730. } break;
  9731. case protocol_version::v5: {
  9732. auto msg = v5::disconnect_message(reason, force_move(props));
  9733. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9734. throw packet_size_error();
  9735. }
  9736. do_sync_write(force_move(msg));
  9737. } break;
  9738. default:
  9739. BOOST_ASSERT(false);
  9740. break;
  9741. }
  9742. }
  9743. void send_store() {
  9744. // packet_id has already been registered
  9745. LockGuard<Mutex> lck (store_mtx_);
  9746. store_.for_each(
  9747. [&] (
  9748. basic_store_message_variant<PacketIdBytes> const& message,
  9749. any const& /*life_keeper*/
  9750. ) {
  9751. auto erase = false;
  9752. MQTT_NS::visit(
  9753. make_lambda_visitor(
  9754. [&](v3_1_1::basic_publish_message<PacketIdBytes> const& m) {
  9755. MQTT_LOG("mqtt_api", info)
  9756. << MQTT_ADD_VALUE(address, this)
  9757. << "async_send_store publish v3.1.1";
  9758. if (maximum_packet_size_send_ < size<PacketIdBytes>(m)) {
  9759. pid_man_.release_id(m.packet_id());
  9760. MQTT_LOG("mqtt_impl", warning)
  9761. << MQTT_ADD_VALUE(address, this)
  9762. << "over maximum packet size message removed. packet_id:" << m.packet_id();
  9763. erase = true;
  9764. return;
  9765. }
  9766. do_sync_write(m);
  9767. },
  9768. [&](v3_1_1::basic_pubrel_message<PacketIdBytes> const& m) {
  9769. MQTT_LOG("mqtt_api", info)
  9770. << MQTT_ADD_VALUE(address, this)
  9771. << "async_send_store pubrel v3.1.1";
  9772. do_sync_write(m);
  9773. },
  9774. [&](v5::basic_publish_message<PacketIdBytes> const& m) {
  9775. MQTT_LOG("mqtt_api", info)
  9776. << MQTT_ADD_VALUE(address, this)
  9777. << "async_send_store publish v5";
  9778. any life_keeper;
  9779. auto msg_lk = apply_topic_alias(m, force_move(life_keeper));
  9780. if (maximum_packet_size_send_ < size<PacketIdBytes>(std::get<0>(msg_lk))) {
  9781. pid_man_.release_id(m.packet_id());
  9782. MQTT_LOG("mqtt_impl", warning)
  9783. << MQTT_ADD_VALUE(address, this)
  9784. << "over maximum packet size message removed. packet_id:" << m.packet_id();
  9785. erase = true;
  9786. return;
  9787. }
  9788. if (publish_send_count_.load() == publish_send_max_) {
  9789. LockGuard<Mutex> lck (publish_send_queue_mtx_);
  9790. publish_send_queue_.emplace_back(
  9791. force_move(std::get<0>(msg_lk)),
  9792. false,
  9793. force_move(std::get<1>(msg_lk))
  9794. );
  9795. }
  9796. else {
  9797. MQTT_LOG("mqtt_impl", trace)
  9798. << MQTT_ADD_VALUE(address, this)
  9799. << "increment publish_send_count_:" << publish_send_count_.load();
  9800. ++publish_send_count_;
  9801. do_sync_write(force_move(std::get<0>(msg_lk)));
  9802. }
  9803. },
  9804. [&](v5::basic_pubrel_message<PacketIdBytes> const& m) {
  9805. MQTT_LOG("mqtt_api", info)
  9806. << MQTT_ADD_VALUE(address, this)
  9807. << "async_send_store pubrel v5";
  9808. {
  9809. LockGuard<Mutex> lck_resend_pubrel (resend_pubrel_mtx_);
  9810. resend_pubrel_.insert(m.packet_id());
  9811. }
  9812. do_sync_write(m);
  9813. }
  9814. ),
  9815. message
  9816. );
  9817. return erase;
  9818. }
  9819. );
  9820. }
  9821. // Blocking write
  9822. template <typename MessageVariant>
  9823. void do_sync_write(MessageVariant&& mv) {
  9824. boost::system::error_code ec;
  9825. if (can_send()) {
  9826. on_pre_send();
  9827. total_bytes_sent_ += socket_->write(const_buffer_sequence<PacketIdBytes>(mv), ec);
  9828. // If ec is set as error, the error will be handled by async_read.
  9829. // If `handle_error(ec);` is called here, error_handler would be called twice.
  9830. }
  9831. }
  9832. // Non blocking (async) senders
  9833. void async_send_connect(
  9834. buffer client_id,
  9835. optional<buffer> user_name,
  9836. optional<buffer> password,
  9837. optional<will> const& w,
  9838. std::uint16_t keep_alive_sec,
  9839. v5::properties props,
  9840. async_handler_t func
  9841. ) {
  9842. shutdown_requested_ = false;
  9843. switch (version_) {
  9844. case protocol_version::v3_1_1:
  9845. do_async_write(
  9846. v3_1_1::connect_message(
  9847. keep_alive_sec,
  9848. force_move(client_id),
  9849. clean_session(),
  9850. w,
  9851. force_move(user_name),
  9852. force_move(password)
  9853. ),
  9854. force_move(func)
  9855. );
  9856. break;
  9857. case protocol_version::v5:
  9858. update_values_and_props_on_start_connection(props);
  9859. do_async_write(
  9860. v5::connect_message(
  9861. keep_alive_sec,
  9862. force_move(client_id),
  9863. clean_start(),
  9864. w,
  9865. force_move(user_name),
  9866. force_move(password),
  9867. force_move(props)
  9868. ),
  9869. force_move(func)
  9870. );
  9871. break;
  9872. default:
  9873. BOOST_ASSERT(false);
  9874. break;
  9875. }
  9876. }
  9877. void async_send_connack(
  9878. bool session_present,
  9879. variant<connect_return_code, v5::connect_reason_code> reason_code,
  9880. v5::properties props,
  9881. async_handler_t func
  9882. ) {
  9883. switch (version_) {
  9884. case protocol_version::v3_1_1: {
  9885. auto msg = v3_1_1::connack_message(
  9886. session_present,
  9887. variant_get<connect_return_code>(reason_code)
  9888. );
  9889. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9890. socket_->post(
  9891. [func = force_move(func)] {
  9892. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  9893. }
  9894. );
  9895. return;
  9896. }
  9897. do_async_write(
  9898. force_move(msg),
  9899. force_move(func)
  9900. );
  9901. } break;
  9902. case protocol_version::v5: {
  9903. update_values_and_props_on_start_connection(props);
  9904. auto msg = v5::connack_message(
  9905. session_present,
  9906. variant_get<v5::connect_reason_code>(reason_code),
  9907. force_move(props)
  9908. );
  9909. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  9910. socket_->post(
  9911. [func = force_move(func)] {
  9912. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  9913. }
  9914. );
  9915. return;
  9916. }
  9917. do_async_write(
  9918. force_move(msg),
  9919. force_move(func)
  9920. );
  9921. } break;
  9922. default:
  9923. BOOST_ASSERT(false);
  9924. break;
  9925. }
  9926. }
  9927. template <typename ConstBufferSequence>
  9928. typename std::enable_if<
  9929. as::is_const_buffer_sequence<ConstBufferSequence>::value
  9930. >::type
  9931. async_send_publish(
  9932. packet_id_t packet_id,
  9933. as::const_buffer topic_name,
  9934. ConstBufferSequence payloads,
  9935. publish_options pubopts,
  9936. v5::properties props,
  9937. any life_keeper,
  9938. async_handler_t func
  9939. ) {
  9940. auto do_async_send_publish =
  9941. [&](auto msg, auto&& serialize_publish, auto&& receive_maximum_proc) {
  9942. auto msg_lk = apply_topic_alias(msg, life_keeper);
  9943. if (maximum_packet_size_send_ < size<PacketIdBytes>(std::get<0>(msg_lk))) {
  9944. if (packet_id != 0) {
  9945. LockGuard<Mutex> lck_store (store_mtx_);
  9946. pid_man_.release_id(packet_id);
  9947. }
  9948. socket_->post(
  9949. [func = force_move(func)] {
  9950. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  9951. }
  9952. );
  9953. return;
  9954. }
  9955. if (preprocess_publish_message(
  9956. msg,
  9957. life_keeper,
  9958. std::forward<decltype(serialize_publish)>(serialize_publish),
  9959. std::forward<decltype(receive_maximum_proc)>(receive_maximum_proc)
  9960. )
  9961. ) {
  9962. do_async_write(
  9963. force_move(std::get<0>(msg_lk)),
  9964. [life_keeper = force_move(std::get<1>(msg_lk)), func](error_code ec) {
  9965. if (func) func(ec);
  9966. }
  9967. );
  9968. }
  9969. };
  9970. switch (version_) {
  9971. case protocol_version::v3_1_1:
  9972. do_async_send_publish(
  9973. v3_1_1::basic_publish_message<PacketIdBytes>(
  9974. packet_id,
  9975. topic_name,
  9976. force_move(payloads),
  9977. pubopts
  9978. ),
  9979. &endpoint::on_serialize_publish_message,
  9980. [] (auto&&) { return true; }
  9981. );
  9982. break;
  9983. case protocol_version::v5:
  9984. do_async_send_publish(
  9985. v5::basic_publish_message<PacketIdBytes>(
  9986. packet_id,
  9987. topic_name,
  9988. force_move(payloads),
  9989. pubopts,
  9990. force_move(props)
  9991. ),
  9992. &endpoint::on_serialize_v5_publish_message,
  9993. [this, func] (v5::basic_publish_message<PacketIdBytes>&& msg) mutable {
  9994. if (publish_send_count_.load() == publish_send_max_) {
  9995. {
  9996. LockGuard<Mutex> lck (publish_send_queue_mtx_);
  9997. publish_send_queue_.emplace_back(force_move(msg), true);
  9998. }
  9999. socket_->post(
  10000. [func = force_move(func)] {
  10001. // message has already been stored so func should be called with success here
  10002. if (func) func(boost::system::errc::make_error_code(boost::system::errc::success));
  10003. }
  10004. );
  10005. return false;
  10006. }
  10007. MQTT_LOG("mqtt_impl", trace)
  10008. << MQTT_ADD_VALUE(address, this)
  10009. << "increment publish_send_count_:" << publish_send_count_.load();
  10010. ++publish_send_count_;
  10011. return true;
  10012. }
  10013. );
  10014. break;
  10015. default:
  10016. BOOST_ASSERT(false);
  10017. break;
  10018. }
  10019. }
  10020. void async_send_puback(
  10021. packet_id_t packet_id,
  10022. v5::puback_reason_code reason,
  10023. v5::properties props,
  10024. async_handler_t func
  10025. ) {
  10026. switch (version_) {
  10027. case protocol_version::v3_1_1: {
  10028. auto msg = v3_1_1::basic_puback_message<PacketIdBytes>(packet_id);
  10029. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10030. socket_->post(
  10031. [func = force_move(func)] {
  10032. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10033. }
  10034. );
  10035. return;
  10036. }
  10037. do_async_write(
  10038. force_move(msg),
  10039. [this, self = this->shared_from_this(), packet_id, func = force_move(func)]
  10040. (error_code ec) {
  10041. if (func) func(ec);
  10042. on_pub_res_sent(packet_id);
  10043. }
  10044. );
  10045. } break;
  10046. case protocol_version::v5: {
  10047. auto msg = v5::basic_puback_message<PacketIdBytes>(packet_id, reason, force_move(props));
  10048. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10049. socket_->post(
  10050. [func = force_move(func)] {
  10051. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10052. }
  10053. );
  10054. return;
  10055. }
  10056. do_async_write(
  10057. force_move(msg),
  10058. [this, self = this->shared_from_this(), packet_id, func = force_move(func)]
  10059. (error_code ec) {
  10060. erase_publish_received(packet_id);
  10061. if (func) func(ec);
  10062. on_pub_res_sent(packet_id);
  10063. }
  10064. );
  10065. } break;
  10066. default:
  10067. BOOST_ASSERT(false);
  10068. break;
  10069. }
  10070. }
  10071. void async_send_pubrec(
  10072. packet_id_t packet_id,
  10073. v5::pubrec_reason_code reason,
  10074. v5::properties props,
  10075. async_handler_t func
  10076. ) {
  10077. switch (version_) {
  10078. case protocol_version::v3_1_1: {
  10079. auto msg = v3_1_1::basic_pubrec_message<PacketIdBytes>(packet_id);
  10080. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10081. socket_->post(
  10082. [func = force_move(func)] {
  10083. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10084. }
  10085. );
  10086. return;
  10087. }
  10088. do_async_write(
  10089. force_move(msg),
  10090. force_move(func)
  10091. );
  10092. } break;
  10093. case protocol_version::v5: {
  10094. auto msg = v5::basic_pubrec_message<PacketIdBytes>(packet_id, reason, force_move(props));
  10095. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10096. socket_->post(
  10097. [func = force_move(func)] {
  10098. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10099. }
  10100. );
  10101. return;
  10102. }
  10103. do_async_write(
  10104. force_move(msg),
  10105. [this, self = this->shared_from_this(), packet_id, func = force_move(func)]
  10106. (error_code ec) {
  10107. erase_publish_received(packet_id);
  10108. if (func) func(ec);
  10109. }
  10110. );
  10111. } break;
  10112. default:
  10113. BOOST_ASSERT(false);
  10114. break;
  10115. }
  10116. }
  10117. void async_send_pubrel(
  10118. packet_id_t packet_id,
  10119. v5::pubrel_reason_code reason,
  10120. v5::properties props,
  10121. any life_keeper,
  10122. async_handler_t func
  10123. ) {
  10124. auto msg = basic_pubrel_message<PacketIdBytes>(packet_id);
  10125. auto impl =
  10126. [&](auto msg, auto const& serialize) {
  10127. {
  10128. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10129. socket_->post(
  10130. [func = force_move(func)] {
  10131. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10132. }
  10133. );
  10134. return;
  10135. }
  10136. LockGuard<Mutex> lck (store_mtx_);
  10137. // insert if not registerd (start from pubrel sending case)
  10138. if (pid_man_.register_id(packet_id)) {
  10139. LockGuard<Mutex> lck_resend_pubrel (resend_pubrel_mtx_);
  10140. resend_pubrel_.insert(packet_id);
  10141. }
  10142. if (store_.insert_or_update(
  10143. packet_id,
  10144. control_packet_type::pubcomp,
  10145. msg,
  10146. life_keeper
  10147. ) == store_insert_update_result::updated
  10148. ) {
  10149. // publish store is erased when pubrec is received.
  10150. // pubrel store is erased when pubcomp is received.
  10151. // If invalid client send pubrec twice with the same packet id,
  10152. // then send corresponding pubrel twice is a possible client/server
  10153. // implementation.
  10154. // In this case, overwrite store_.
  10155. MQTT_LOG("mqtt_impl", warning)
  10156. << MQTT_ADD_VALUE(address, this)
  10157. << "overwrite pubrel"
  10158. << " packet_id:" << packet_id;
  10159. }
  10160. }
  10161. (this->*serialize)(msg);
  10162. do_async_write(
  10163. force_move(msg),
  10164. [life_keeper = force_move(life_keeper), func = force_move(func)](error_code ec) {
  10165. if(func) func(ec);
  10166. }
  10167. );
  10168. };
  10169. switch (version_) {
  10170. case protocol_version::v3_1_1:
  10171. impl(
  10172. v3_1_1::basic_pubrel_message<PacketIdBytes>(packet_id),
  10173. &endpoint::on_serialize_pubrel_message
  10174. );
  10175. break;
  10176. case protocol_version::v5:
  10177. impl(
  10178. v5::basic_pubrel_message<PacketIdBytes>(packet_id, reason, force_move(props)),
  10179. &endpoint::on_serialize_v5_pubrel_message
  10180. );
  10181. break;
  10182. default:
  10183. BOOST_ASSERT(false);
  10184. break;
  10185. }
  10186. }
  10187. void async_send_pubcomp(
  10188. packet_id_t packet_id,
  10189. v5::pubcomp_reason_code reason,
  10190. v5::properties props,
  10191. async_handler_t func
  10192. ) {
  10193. switch (version_) {
  10194. case protocol_version::v3_1_1: {
  10195. auto msg = v3_1_1::basic_pubcomp_message<PacketIdBytes>(packet_id);
  10196. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10197. socket_->post(
  10198. [func = force_move(func)] {
  10199. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10200. }
  10201. );
  10202. return;
  10203. }
  10204. do_async_write(
  10205. force_move(msg),
  10206. [this, self = this->shared_from_this(), packet_id, func = force_move(func)]
  10207. (error_code ec) {
  10208. if (func) func(ec);
  10209. on_pub_res_sent(packet_id);
  10210. }
  10211. );
  10212. } break;
  10213. case protocol_version::v5: {
  10214. auto msg = v5::basic_pubcomp_message<PacketIdBytes>(packet_id, reason, force_move(props));
  10215. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10216. socket_->post(
  10217. [func = force_move(func)] {
  10218. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10219. }
  10220. );
  10221. return;
  10222. }
  10223. do_async_write(
  10224. force_move(msg),
  10225. [this, self = this->shared_from_this(), packet_id, func = force_move(func)]
  10226. (error_code ec) {
  10227. if (func) func(ec);
  10228. on_pub_res_sent(packet_id);
  10229. }
  10230. );
  10231. } break;
  10232. default:
  10233. BOOST_ASSERT(false);
  10234. break;
  10235. }
  10236. }
  10237. void async_send_subscribe(
  10238. std::vector<std::tuple<as::const_buffer, subscribe_options>> params,
  10239. packet_id_t packet_id,
  10240. v5::properties props,
  10241. async_handler_t func
  10242. ) {
  10243. switch (version_) {
  10244. case protocol_version::v3_1_1: {
  10245. auto msg = v3_1_1::basic_subscribe_message<PacketIdBytes>(force_move(params), packet_id);
  10246. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10247. {
  10248. LockGuard<Mutex> lck_store (store_mtx_);
  10249. pid_man_.release_id(packet_id);
  10250. }
  10251. socket_->post(
  10252. [func = force_move(func)] {
  10253. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10254. }
  10255. );
  10256. return;
  10257. }
  10258. {
  10259. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  10260. sub_unsub_inflight_.insert(packet_id);
  10261. }
  10262. do_async_write(
  10263. force_move(msg),
  10264. force_move(func)
  10265. );
  10266. } break;
  10267. case protocol_version::v5: {
  10268. auto msg = v5::basic_subscribe_message<PacketIdBytes>(force_move(params), packet_id, force_move(props));
  10269. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10270. {
  10271. LockGuard<Mutex> lck_store (store_mtx_);
  10272. pid_man_.release_id(packet_id);
  10273. }
  10274. socket_->post(
  10275. [func = force_move(func)] {
  10276. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10277. }
  10278. );
  10279. return;
  10280. }
  10281. {
  10282. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  10283. sub_unsub_inflight_.insert(packet_id);
  10284. }
  10285. do_async_write(
  10286. force_move(msg),
  10287. force_move(func)
  10288. );
  10289. } break;
  10290. default:
  10291. BOOST_ASSERT(false);
  10292. break;
  10293. }
  10294. }
  10295. void async_send_suback(
  10296. variant<std::vector<suback_return_code>, std::vector<v5::suback_reason_code>> params,
  10297. packet_id_t packet_id,
  10298. v5::properties props,
  10299. async_handler_t func
  10300. ) {
  10301. switch (version_) {
  10302. case protocol_version::v3_1_1: {
  10303. auto msg = v3_1_1::basic_suback_message<PacketIdBytes>(
  10304. force_move(variant_get<std::vector<suback_return_code>>(params)),
  10305. packet_id
  10306. );
  10307. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10308. socket_->post(
  10309. [func = force_move(func)] {
  10310. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10311. }
  10312. );
  10313. return;
  10314. }
  10315. do_async_write(
  10316. force_move(msg),
  10317. force_move(func)
  10318. );
  10319. } break;
  10320. case protocol_version::v5: {
  10321. auto msg = v5::basic_suback_message<PacketIdBytes>(
  10322. force_move(variant_get<std::vector<v5::suback_reason_code>>(params)),
  10323. packet_id,
  10324. force_move(props)
  10325. );
  10326. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10327. socket_->post(
  10328. [func = force_move(func)] {
  10329. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10330. }
  10331. );
  10332. return;
  10333. }
  10334. do_async_write(
  10335. force_move(msg),
  10336. force_move(func)
  10337. );
  10338. } break;
  10339. default:
  10340. BOOST_ASSERT(false);
  10341. break;
  10342. }
  10343. }
  10344. void async_send_unsubscribe(
  10345. std::vector<as::const_buffer> params,
  10346. packet_id_t packet_id,
  10347. v5::properties props,
  10348. async_handler_t func
  10349. ) {
  10350. switch (version_) {
  10351. case protocol_version::v3_1_1: {
  10352. auto msg = v3_1_1::basic_unsubscribe_message<PacketIdBytes>(force_move(params), packet_id);
  10353. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10354. {
  10355. LockGuard<Mutex> lck_store (store_mtx_);
  10356. pid_man_.release_id(packet_id);
  10357. }
  10358. socket_->post(
  10359. [func = force_move(func)] {
  10360. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10361. }
  10362. );
  10363. return;
  10364. }
  10365. {
  10366. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  10367. sub_unsub_inflight_.insert(packet_id);
  10368. }
  10369. do_async_write(
  10370. force_move(msg),
  10371. force_move(func)
  10372. );
  10373. } break;
  10374. case protocol_version::v5: {
  10375. auto msg = v5::basic_unsubscribe_message<PacketIdBytes>(force_move(params), packet_id, force_move(props));
  10376. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10377. {
  10378. LockGuard<Mutex> lck_store (store_mtx_);
  10379. pid_man_.release_id(packet_id);
  10380. }
  10381. socket_->post(
  10382. [func = force_move(func)] {
  10383. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10384. }
  10385. );
  10386. return;
  10387. }
  10388. {
  10389. LockGuard<Mutex> lck (sub_unsub_inflight_mtx_);
  10390. sub_unsub_inflight_.insert(packet_id);
  10391. }
  10392. do_async_write(
  10393. force_move(msg),
  10394. force_move(func)
  10395. );
  10396. } break;
  10397. default:
  10398. BOOST_ASSERT(false);
  10399. break;
  10400. }
  10401. }
  10402. void async_send_unsuback(
  10403. packet_id_t packet_id,
  10404. async_handler_t func
  10405. ) {
  10406. switch (version_) {
  10407. case protocol_version::v3_1_1: {
  10408. auto msg = v3_1_1::basic_unsuback_message<PacketIdBytes>(packet_id);
  10409. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10410. socket_->post(
  10411. [func = force_move(func)] {
  10412. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10413. }
  10414. );
  10415. return;
  10416. }
  10417. do_async_write(
  10418. force_move(msg),
  10419. force_move(func)
  10420. );
  10421. } break;
  10422. case protocol_version::v5:
  10423. BOOST_ASSERT(false);
  10424. break;
  10425. default:
  10426. BOOST_ASSERT(false);
  10427. break;
  10428. }
  10429. }
  10430. void async_send_unsuback(
  10431. std::vector<v5::unsuback_reason_code> params,
  10432. packet_id_t packet_id,
  10433. v5::properties props,
  10434. async_handler_t func
  10435. ) {
  10436. switch (version_) {
  10437. case protocol_version::v3_1_1:
  10438. BOOST_ASSERT(false);
  10439. break;
  10440. case protocol_version::v5: {
  10441. auto msg = v5::basic_unsuback_message<PacketIdBytes>(force_move(params), packet_id, force_move(props));
  10442. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10443. socket_->post(
  10444. [func = force_move(func)] {
  10445. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10446. }
  10447. );
  10448. return;
  10449. }
  10450. do_async_write(
  10451. force_move(msg),
  10452. force_move(func)
  10453. );
  10454. } break;
  10455. default:
  10456. BOOST_ASSERT(false);
  10457. break;
  10458. }
  10459. }
  10460. void async_send_pingreq(async_handler_t func) {
  10461. switch (version_) {
  10462. case protocol_version::v3_1_1: {
  10463. auto msg = v3_1_1::pingreq_message();
  10464. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10465. socket_->post(
  10466. [func = force_move(func)] {
  10467. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10468. }
  10469. );
  10470. return;
  10471. }
  10472. do_async_write(force_move(msg), force_move(func));
  10473. set_pingresp_timer();
  10474. } break;
  10475. case protocol_version::v5: {
  10476. auto msg = v5::pingreq_message();
  10477. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10478. socket_->post(
  10479. [func = force_move(func)] {
  10480. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10481. }
  10482. );
  10483. return;
  10484. }
  10485. do_async_write(force_move(msg), force_move(func));
  10486. set_pingresp_timer();
  10487. } break;
  10488. default:
  10489. BOOST_ASSERT(false);
  10490. break;
  10491. }
  10492. }
  10493. void async_send_pingresp(async_handler_t func) {
  10494. switch (version_) {
  10495. case protocol_version::v3_1_1: {
  10496. auto msg = v3_1_1::pingresp_message();
  10497. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10498. socket_->post(
  10499. [func = force_move(func)] {
  10500. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10501. }
  10502. );
  10503. return;
  10504. }
  10505. do_async_write(force_move(msg), force_move(func));
  10506. } break;
  10507. case protocol_version::v5: {
  10508. auto msg = v5::pingresp_message();
  10509. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10510. socket_->post(
  10511. [func = force_move(func)] {
  10512. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10513. }
  10514. );
  10515. return;
  10516. }
  10517. do_async_write(force_move(msg), force_move(func));
  10518. } break;
  10519. default:
  10520. BOOST_ASSERT(false);
  10521. break;
  10522. }
  10523. }
  10524. void async_send_auth(
  10525. v5::auth_reason_code reason,
  10526. v5::properties props,
  10527. async_handler_t func
  10528. ) {
  10529. switch (version_) {
  10530. case protocol_version::v3_1_1:
  10531. BOOST_ASSERT(false);
  10532. break;
  10533. case protocol_version::v5: {
  10534. auto msg = v5::auth_message(reason, force_move(props));
  10535. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10536. socket_->post(
  10537. [func = force_move(func)] {
  10538. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10539. }
  10540. );
  10541. return;
  10542. }
  10543. do_async_write(force_move(msg), force_move(func));
  10544. } break;
  10545. default:
  10546. BOOST_ASSERT(false);
  10547. break;
  10548. }
  10549. }
  10550. void async_send_disconnect(
  10551. v5::disconnect_reason_code reason,
  10552. v5::properties props,
  10553. async_handler_t func
  10554. ) {
  10555. switch (version_) {
  10556. case protocol_version::v3_1_1: {
  10557. auto msg = v3_1_1::disconnect_message();
  10558. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10559. socket_->post(
  10560. [func = force_move(func)] {
  10561. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10562. }
  10563. );
  10564. return;
  10565. }
  10566. do_async_write(force_move(msg), force_move(func));
  10567. } break;
  10568. case protocol_version::v5: {
  10569. auto msg = v5::disconnect_message(reason, force_move(props));
  10570. if (maximum_packet_size_send_ < size<PacketIdBytes>(msg)) {
  10571. socket_->post(
  10572. [func = force_move(func)] {
  10573. if (func) func(boost::system::errc::make_error_code(boost::system::errc::message_size));
  10574. }
  10575. );
  10576. return;
  10577. }
  10578. do_async_write(force_move(msg), force_move(func));
  10579. } break;
  10580. default:
  10581. BOOST_ASSERT(false);
  10582. break;
  10583. }
  10584. }
  10585. void async_send_store(std::function<void()> func) {
  10586. // packet_id has already been registered
  10587. auto g = shared_scope_guard(
  10588. [func = force_move(func)] {
  10589. func();
  10590. }
  10591. );
  10592. LockGuard<Mutex> lck (store_mtx_);
  10593. if (store_.empty()) {
  10594. socket().post(
  10595. [g]{}
  10596. );
  10597. return;
  10598. }
  10599. store_.for_each(
  10600. [&] (
  10601. basic_store_message_variant<PacketIdBytes> const& message,
  10602. any const& /*life_keeper*/
  10603. ) {
  10604. auto erase = false;
  10605. MQTT_NS::visit(
  10606. make_lambda_visitor(
  10607. [&](v3_1_1::basic_publish_message<PacketIdBytes> const& m) {
  10608. MQTT_LOG("mqtt_api", info)
  10609. << MQTT_ADD_VALUE(address, this)
  10610. << "async_send_store publish v3.1.1";
  10611. if (maximum_packet_size_send_ < size<PacketIdBytes>(m)) {
  10612. pid_man_.release_id(m.packet_id());
  10613. MQTT_LOG("mqtt_impl", warning)
  10614. << MQTT_ADD_VALUE(address, this)
  10615. << "over maximum packet size message removed. packet_id:" << m.packet_id();
  10616. erase = true;
  10617. return;
  10618. }
  10619. do_async_write(
  10620. m,
  10621. [g]
  10622. (error_code /*ec*/) {
  10623. }
  10624. );
  10625. },
  10626. [&](v3_1_1::basic_pubrel_message<PacketIdBytes> const& m) {
  10627. MQTT_LOG("mqtt_api", info)
  10628. << MQTT_ADD_VALUE(address, this)
  10629. << "async_send_store pubrel v3.1.1";
  10630. do_async_write(
  10631. m,
  10632. [g]
  10633. (error_code /*ec*/) {
  10634. }
  10635. );
  10636. },
  10637. [&](v5::basic_publish_message<PacketIdBytes> const& m) {
  10638. MQTT_LOG("mqtt_api", info)
  10639. << MQTT_ADD_VALUE(address, this)
  10640. << "async_send_store publish v5";
  10641. any life_keeper;
  10642. auto msg_lk = apply_topic_alias(m, force_move(life_keeper));
  10643. if (maximum_packet_size_send_ < size<PacketIdBytes>(std::get<0>(msg_lk))) {
  10644. pid_man_.release_id(m.packet_id());
  10645. MQTT_LOG("mqtt_impl", warning)
  10646. << MQTT_ADD_VALUE(address, this)
  10647. << "over maximum packet size message removed. packet_id:" << m.packet_id();
  10648. erase = true;
  10649. return;
  10650. }
  10651. if (publish_send_count_.load() == publish_send_max_) {
  10652. LockGuard<Mutex> lck (publish_send_queue_mtx_);
  10653. publish_send_queue_.emplace_back(
  10654. force_move(std::get<0>(msg_lk)),
  10655. true,
  10656. force_move(std::get<1>(msg_lk))
  10657. );
  10658. }
  10659. else {
  10660. MQTT_LOG("mqtt_impl", trace)
  10661. << MQTT_ADD_VALUE(address, this)
  10662. << "increment publish_send_count_:" << publish_send_count_.load();
  10663. ++publish_send_count_;
  10664. do_async_write(
  10665. get_basic_message_variant<PacketIdBytes>(force_move(std::get<0>(msg_lk))),
  10666. [g, life_keeper = force_move(std::get<1>(msg_lk))]
  10667. (error_code /*ec*/) {
  10668. }
  10669. );
  10670. }
  10671. },
  10672. [&](v5::basic_pubrel_message<PacketIdBytes> const& m) {
  10673. MQTT_LOG("mqtt_api", info)
  10674. << MQTT_ADD_VALUE(address, this)
  10675. << "async_send_store pubrel v5";
  10676. {
  10677. LockGuard<Mutex> lck_resend_pubrel (resend_pubrel_mtx_);
  10678. resend_pubrel_.insert(m.packet_id());
  10679. }
  10680. do_async_write(
  10681. m,
  10682. [g]
  10683. (error_code /*ec*/) {
  10684. }
  10685. );
  10686. }
  10687. ),
  10688. message
  10689. );
  10690. return erase;
  10691. }
  10692. );
  10693. }
  10694. // Non blocking (async) write
  10695. class async_packet {
  10696. public:
  10697. async_packet(
  10698. basic_message_variant<PacketIdBytes> mv,
  10699. async_handler_t h = {})
  10700. : mv_(force_move(mv))
  10701. , handler_(force_move(h)) {}
  10702. basic_message_variant<PacketIdBytes> const& message() const {
  10703. return mv_;
  10704. }
  10705. basic_message_variant<PacketIdBytes>& message() {
  10706. return mv_;
  10707. }
  10708. async_handler_t const& handler() const { return handler_; }
  10709. async_handler_t& handler() { return handler_; }
  10710. private:
  10711. basic_message_variant<PacketIdBytes> mv_;
  10712. async_handler_t handler_;
  10713. };
  10714. struct write_completion_handler {
  10715. write_completion_handler(
  10716. std::shared_ptr<this_type> self,
  10717. async_handler_t func,
  10718. std::size_t num_of_messages,
  10719. std::size_t expected)
  10720. :self_(force_move(self)),
  10721. func_(force_move(func)),
  10722. num_of_messages_(num_of_messages),
  10723. bytes_to_transfer_(expected)
  10724. {
  10725. // write_completion_handler is only constructed in one place
  10726. // and a handler is provided in that location.
  10727. // Since we don't check that the handler is valid before calling it
  10728. // it's a bug if the handler is invalid when constructed.
  10729. BOOST_ASSERT(func_);
  10730. }
  10731. void operator()(error_code ec) const {
  10732. func_(ec);
  10733. for (std::size_t i = 0; i != num_of_messages_; ++i) {
  10734. self_->queue_.pop_front();
  10735. }
  10736. if (ec || // Error is handled by async_read.
  10737. !self_->connected_) {
  10738. while (!self_->queue_.empty()) {
  10739. // Handlers for outgoing packets need not be valid.
  10740. if (auto&& h = self_->queue_.front().handler()) h(ec);
  10741. self_->queue_.pop_front();
  10742. }
  10743. return;
  10744. }
  10745. if (!self_->queue_.empty()) {
  10746. self_->do_async_write();
  10747. }
  10748. }
  10749. void operator()(
  10750. error_code ec,
  10751. std::size_t bytes_transferred) const {
  10752. func_(ec);
  10753. self_->total_bytes_sent_ += bytes_transferred;
  10754. for (std::size_t i = 0; i != num_of_messages_; ++i) {
  10755. self_->queue_.pop_front();
  10756. }
  10757. if (ec || // Error is handled by async_read.
  10758. !self_->connected_) {
  10759. while (!self_->queue_.empty()) {
  10760. // Handlers for outgoing packets need not be valid.
  10761. if(auto&& h = self_->queue_.front().handler()) h(ec);
  10762. self_->queue_.pop_front();
  10763. }
  10764. return;
  10765. }
  10766. if (bytes_to_transfer_ != bytes_transferred) {
  10767. while (!self_->queue_.empty()) {
  10768. // Handlers for outgoing packets need not be valid.
  10769. if(auto&& h = self_->queue_.front().handler()) h(ec);
  10770. self_->queue_.pop_front();
  10771. }
  10772. throw write_bytes_transferred_error(bytes_to_transfer_, bytes_transferred);
  10773. }
  10774. if (!self_->queue_.empty()) {
  10775. self_->do_async_write();
  10776. }
  10777. }
  10778. std::shared_ptr<this_type> self_;
  10779. async_handler_t func_;
  10780. std::size_t num_of_messages_;
  10781. std::size_t bytes_to_transfer_;
  10782. };
  10783. void do_async_write() {
  10784. // Only attempt to send up to the user specified maximum items
  10785. using difference_t = typename decltype(queue_)::difference_type;
  10786. std::size_t iterator_count = (max_queue_send_count_ == 0)
  10787. ? queue_.size()
  10788. : std::min(max_queue_send_count_, queue_.size());
  10789. auto const& start = queue_.cbegin();
  10790. auto end = std::next(start, boost::numeric_cast<difference_t>(iterator_count));
  10791. // And further, only up to the specified maximum bytes
  10792. std::size_t total_bytes = 0;
  10793. std::size_t total_const_buffer_sequence = 0;
  10794. for (auto it = start; it != end; ++it) {
  10795. auto const& elem = *it;
  10796. auto const& mv = elem.message();
  10797. std::size_t const size = MQTT_NS::size<PacketIdBytes>(mv);
  10798. // If we hit the byte limit, we don't include this buffer for this send.
  10799. if (max_queue_send_size_ != 0 && max_queue_send_size_ < total_bytes + size) {
  10800. end = it;
  10801. iterator_count = boost::numeric_cast<std::size_t>(std::distance(start, end));
  10802. break;
  10803. }
  10804. total_bytes += size;
  10805. total_const_buffer_sequence += num_of_const_buffer_sequence(mv);
  10806. }
  10807. std::vector<as::const_buffer> buf;
  10808. std::vector<async_handler_t> handlers;
  10809. buf.reserve(total_const_buffer_sequence);
  10810. handlers.reserve(iterator_count);
  10811. for (auto it = start; it != end; ++it) {
  10812. auto const& elem = *it;
  10813. auto const& mv = elem.message();
  10814. auto const& cbs = const_buffer_sequence(mv);
  10815. std::copy(cbs.begin(), cbs.end(), std::back_inserter(buf));
  10816. handlers.emplace_back(elem.handler());
  10817. }
  10818. on_pre_send();
  10819. socket_->async_write(
  10820. force_move(buf),
  10821. write_completion_handler(
  10822. this->shared_from_this(),
  10823. [handlers = force_move(handlers)]
  10824. (error_code ec) {
  10825. for (auto const& h : handlers) {
  10826. if (h) h(ec);
  10827. }
  10828. },
  10829. iterator_count,
  10830. total_bytes
  10831. )
  10832. );
  10833. }
  10834. void do_async_write(basic_message_variant<PacketIdBytes> mv, async_handler_t func) {
  10835. // Move this job to the socket's strand so that it can be queued without mutexes.
  10836. socket_->post(
  10837. [this, self = this->shared_from_this(), mv = force_move(mv), func = force_move(func)]
  10838. () mutable {
  10839. if (can_send()) {
  10840. queue_.emplace_back(force_move(mv), force_move(func));
  10841. // Only need to start async writes if there was nothing in the queue before the above item.
  10842. if (queue_.size() > 1) return;
  10843. do_async_write();
  10844. }
  10845. else {
  10846. // offline async publish is successfully finished, because there's nothing to do.
  10847. if (func) func(boost::system::errc::make_error_code(boost::system::errc::success));
  10848. return;
  10849. }
  10850. }
  10851. );
  10852. }
  10853. static constexpr std::uint16_t make_uint16_t(char b1, char b2) {
  10854. return
  10855. static_cast<std::uint16_t>(
  10856. ((static_cast<std::uint16_t>(b1) & 0xff)) << 8 |
  10857. (static_cast<std::uint16_t>(b2) & 0xff)
  10858. );
  10859. }
  10860. void clean_sub_unsub_inflight() {
  10861. LockGuard<Mutex> lck_store (store_mtx_);
  10862. LockGuard<Mutex> lck_sub_unsub (sub_unsub_inflight_mtx_);
  10863. auto it = sub_unsub_inflight_.begin();
  10864. auto end = sub_unsub_inflight_.end();
  10865. while (it != end) {
  10866. pid_man_.release_id(*it);
  10867. it = sub_unsub_inflight_.erase(it);
  10868. }
  10869. }
  10870. void clean_sub_unsub_inflight_on_error(error_code ec) {
  10871. clean_sub_unsub_inflight();
  10872. on_error(ec);
  10873. }
  10874. void set_pingresp_timer() {
  10875. if (pingresp_timeout_ == std::chrono::steady_clock::duration::zero()) return;
  10876. if (tim_pingresp_set_) return;
  10877. tim_pingresp_set_ = true;
  10878. LockGuard<Mutex> lck (mtx_tim_pingresp_);
  10879. tim_pingresp_.expires_after(pingresp_timeout_);
  10880. std::weak_ptr<this_type> wp(std::static_pointer_cast<this_type>(this->shared_from_this()));
  10881. tim_pingresp_.async_wait(
  10882. [this, wp = force_move(wp)](error_code ec) mutable {
  10883. if (auto sp = wp.lock()) {
  10884. sp->tim_pingresp_set_ = false;
  10885. if (!ec) {
  10886. if (async_operation_) {
  10887. auto p = sp.get();
  10888. p->async_force_disconnect(
  10889. [sp = force_move(sp)](error_code) {
  10890. }
  10891. );
  10892. }
  10893. else {
  10894. auto p = sp.get();
  10895. p->socket().post(
  10896. [sp = force_move(sp)] () {
  10897. sp->force_disconnect();
  10898. }
  10899. );
  10900. }
  10901. }
  10902. }
  10903. }
  10904. );
  10905. }
  10906. void send_publish_queue_one() {
  10907. MQTT_LOG("mqtt_impl", trace)
  10908. << MQTT_ADD_VALUE(address, this)
  10909. << "derement publish_send_count_:" << publish_send_count_.load();
  10910. BOOST_ASSERT(publish_send_count_.load() > 0);
  10911. --publish_send_count_;
  10912. auto entry =
  10913. [&] () -> optional<publish_send_queue_elem> {
  10914. LockGuard<Mutex> lck (publish_send_queue_mtx_);
  10915. if (publish_send_queue_.empty()) return nullopt;
  10916. auto entry = force_move(publish_send_queue_.front());
  10917. publish_send_queue_.pop_front();
  10918. return entry;
  10919. } ();
  10920. if (!entry) return;
  10921. MQTT_LOG("mqtt_impl", trace)
  10922. << MQTT_ADD_VALUE(address, this)
  10923. << "increment publish_send_count_:" << publish_send_count_.load();
  10924. ++publish_send_count_;
  10925. if (entry.value().async) {
  10926. do_async_write(
  10927. force_move(entry.value().message),
  10928. [life_keeper = force_move(entry.value().life_keeper)]
  10929. (error_code) {
  10930. }
  10931. );
  10932. }
  10933. else {
  10934. do_sync_write(force_move(entry.value().message));
  10935. }
  10936. }
  10937. void erase_publish_received(packet_id_t packet_id) {
  10938. LockGuard<Mutex> lck (publish_received_mtx_);
  10939. publish_received_.erase(packet_id);
  10940. }
  10941. bool can_send() const {
  10942. return connected_ && ! shutdown_requested_;
  10943. }
  10944. static optional<topic_alias_t> get_topic_alias_from_prop(v5::property_variant const& prop) {
  10945. optional<topic_alias_t> val;
  10946. v5::visit_prop(
  10947. prop,
  10948. [&val](v5::property::topic_alias const& p) {
  10949. val = p.val();
  10950. },
  10951. [](auto&&) {
  10952. }
  10953. );
  10954. return val;
  10955. }
  10956. static optional<topic_alias_t> get_topic_alias_from_props(v5::properties const& props) {
  10957. optional<topic_alias_t> val;
  10958. v5::visit_props(
  10959. props,
  10960. [&val](v5::property::topic_alias const& p) {
  10961. val = p.val();
  10962. },
  10963. [](auto&&) {
  10964. }
  10965. );
  10966. return val;
  10967. }
  10968. public:
  10969. void set_preauthed_user_name(optional<std::string> const& user_name) {
  10970. preauthed_user_name_ = user_name;
  10971. }
  10972. optional<std::string> get_preauthed_user_name() const {
  10973. return preauthed_user_name_;
  10974. }
  10975. private:
  10976. optional<std::string> preauthed_user_name_;
  10977. protected:
  10978. // Ensure that only code that knows the *exact* type of an object
  10979. // inheriting from this abstract base class can destruct it.
  10980. // This avoids issues of the destructor not triggering destruction
  10981. // of derived classes, and any member variables contained in them.
  10982. // Note: Not virtual to avoid need for a vtable when possible.
  10983. ~endpoint() {
  10984. MQTT_LOG("mqtt_impl", trace)
  10985. << MQTT_ADD_VALUE(address, this)
  10986. << "endpoint destroy";
  10987. }
  10988. protected:
  10989. bool clean_start_{false};
  10990. private:
  10991. std::shared_ptr<MQTT_NS::socket> socket_;
  10992. std::atomic<bool> connected_{false};
  10993. std::atomic<bool> mqtt_connected_{false};
  10994. std::atomic<bool> shutdown_requested_{false};
  10995. std::atomic<bool> async_shutdown_handler_called_{false};
  10996. std::vector<async_handler_t> async_shutdown_handler_queue_;
  10997. std::string client_id_;
  10998. std::array<char, 10> buf_;
  10999. std::uint8_t fixed_header_;
  11000. std::size_t remaining_length_multiplier_;
  11001. std::size_t remaining_length_;
  11002. std::vector<char> payload_;
  11003. Mutex store_mtx_;
  11004. store<PacketIdBytes> store_;
  11005. std::set<packet_id_t> qos2_publish_handled_;
  11006. std::deque<async_packet> queue_;
  11007. packet_id_manager<packet_id_t> pid_man_;
  11008. Mutex sub_unsub_inflight_mtx_;
  11009. std::set<packet_id_t> sub_unsub_inflight_;
  11010. bool auto_pub_response_{true};
  11011. bool async_operation_{ false };
  11012. bool async_read_on_message_processed_ { true };
  11013. bool disconnect_requested_{false};
  11014. bool connect_requested_{false};
  11015. std::size_t max_queue_send_count_{1};
  11016. std::size_t max_queue_send_size_{0};
  11017. protocol_version version_{protocol_version::undetermined};
  11018. std::size_t packet_bulk_read_limit_ = 256;
  11019. std::size_t props_bulk_read_limit_ = packet_bulk_read_limit_;
  11020. std::size_t total_bytes_sent_ = 0;
  11021. std::size_t total_bytes_received_ = 0;
  11022. static constexpr std::uint8_t variable_length_continue_flag = 0b10000000;
  11023. std::chrono::steady_clock::duration pingresp_timeout_ = std::chrono::steady_clock::duration::zero();
  11024. Mutex mtx_tim_pingresp_;
  11025. as::steady_timer tim_pingresp_;
  11026. bool tim_pingresp_set_ = false;
  11027. Mutex mtx_tim_shutdown_;
  11028. as::steady_timer tim_shutdown_;
  11029. bool auto_map_topic_alias_send_ = false;
  11030. bool auto_replace_topic_alias_send_ = false;
  11031. mutable Mutex topic_alias_send_mtx_;
  11032. optional<topic_alias_send> topic_alias_send_;
  11033. mutable Mutex topic_alias_recv_mtx_;
  11034. optional<topic_alias_recv> topic_alias_recv_;
  11035. std::size_t maximum_packet_size_send_ = packet_size_no_limit;
  11036. std::size_t maximum_packet_size_recv_ = packet_size_no_limit;
  11037. std::atomic<receive_maximum_t> publish_send_count_{0};
  11038. receive_maximum_t publish_send_max_ = receive_maximum_max;
  11039. receive_maximum_t publish_recv_max_ = receive_maximum_max;
  11040. Mutex publish_received_mtx_;
  11041. std::set<packet_id_t> publish_received_;
  11042. struct publish_send_queue_elem {
  11043. publish_send_queue_elem(
  11044. basic_message_variant<PacketIdBytes> message,
  11045. bool async,
  11046. any life_keeper = any()
  11047. ): message{force_move(message)},
  11048. life_keeper{force_move(life_keeper)},
  11049. async{async}
  11050. {}
  11051. basic_message_variant<PacketIdBytes> message;
  11052. any life_keeper;
  11053. bool async;
  11054. };
  11055. Mutex publish_send_queue_mtx_;
  11056. std::deque<publish_send_queue_elem> publish_send_queue_;
  11057. mutable Mutex resend_pubrel_mtx_;
  11058. std::set<packet_id_t> resend_pubrel_;
  11059. };
  11060. } // namespace MQTT_NS
  11061. #include <boost/asio/unyield.hpp>
  11062. #if defined(__GNUC__)
  11063. #pragma GCC diagnostic pop
  11064. #endif // defined(__GNUC__)
  11065. #endif // MQTT_ENDPOINT_HPP