/** Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 1 9 ĠSK ĠTele com ĠCo ., ĠLtd . ĠAll Ġrights Ġreserved . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp : www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . device gateway Ċ Ċ import Ġcom . google . common . annotations . Visible ForTesting Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . Header Client Interceptor Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . Policy Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . Server Policy Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . utils . Back Off Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . utils . Channel Builder Utils Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . utils . Message Request Converter . to Attachment Message Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . utils . Message Request Converter . to Directives Ċ import Ġcom . sk t . n ugu . sdk . client . port . transport . grpc 2 . utils . Message Request Converter . toString Message Ċ import Ġcom . sk t . n ugu . sdk . core . interfaces . auth . Auth Delegate Ċ import Ġcom . sk t . n ugu . sdk . core . interfaces . connection . Connection Status Listener . Changed Reason Ċ import Ġcom . sk t . n ugu . sdk . core . interfaces . message . Message Consumer Ċ import Ġcom . sk t . n ugu . sdk . core . interfaces . message . Call Ċ import Ġcom . sk t . n ugu . sdk . core . interfaces . message . request . Attachment Message Request Ċ import Ġcom . sk t . n ugu . sdk . core . interfaces . message . request . Event Message Request Ċ import Ġcom . sk t . n ugu . sdk . core . interfaces . transport . Call Options Ċ import Ġcom . sk t . n ugu . sdk . core . utils . Logger Ċ import Ġdevice gateway . grpc . Attachment Message Ċ import Ġdevice gateway . grpc . Directive Message Ċ import Ġio . grpc . Managed Channel Ċ import Ġio . grpc . Status Ċ import Ġjava . net . Connect Exception Ċ import Ġjava . net . Socket TimeoutException Ċ import Ġjava . net . Unknown Host Exception Ċ import Ġjava . util . concurrent . Concurrent Linked Queue Ċ import Ġjava . util . concurrent . Executors Ċ import Ġjava . util . concurrent . atomic . Atomic Boolean Ċ import Ġjavax . net . ssl . SSL Handshake Exception Ċ Ċ /** Ċ Ġ* Ġ ĠImplementation Ġof ĠDevice Gateway Ċ Ġ**/ Ċ internal Ġclass ĠDevice Gateway Client ( policy : ĠPolicy , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġvar Ġmessage Consumer : ĠMessage Consumer ?, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġvar Ġtransport Observer : ĠDevice Gateway Transport . Transport Observer ?, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġauth Delegate : ĠAuth Delegate , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġcall Options : ĠCall Options ?, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġis Start Receive Server Initi ated Directive : Ġ() Ġ-> ĠBoolean ) ĊĠĠĠ Ġ: ĊĠĠĠ ĠDevice Gateway Transport , ĠHeader Client Interceptor . Delegate Ġ{ ĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Device Gateway Client " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġpolicies Ġ= ĠConcurrent Linked Queue ( policy . server Policy ) ĊĠĠĠ Ġprivate Ġvar Ġbackoff Ġ: ĠBack Off Ġ= ĠBack Off . DEFAULT () ĊĊĠĠĠ Ġprivate Ġvar Ġcurrent Channel : ĠManaged Channel ? Ġ= Ġnull ĊĊĠĠĠ Ġprivate Ġvar Ġping Service : ĠPing Service ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġevents Service : ĠEvents Service ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġdirectives Service : ĠDirect ives Service ? Ġ= Ġnull ĊĊĠĠĠ Ġprivate Ġvar Ġcurrent Policy Ġ: ĠServer Policy ? Ġ= Ġnext Policy () ĊĠĠĠ Ġprivate Ġvar Ġhealth Check Policy Ġ= Ġpolicy . health Check Policy ĊĊĠĠĠ Ġprivate Ġval Ġis Connected Ġ= ĠAtomic Boolean ( false ) ĊĠĠĠ Ġprivate Ġvar Ġfirst Response Received Ġ= ĠAtomic Boolean ( false ) ĊĊĠĠĠ Ġprivate Ġval Ġscheduler Ġ Ġ= ĠExec utors . new Single Thread Scheduled Executor () ĊĊĠĠĠ Ġprivate Ġvar Ġpending Headers : ĠMap < String , ĠString >? Ġ= Ġnull ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSet Ġa Ġpolicy . ĊĠĠĠĠ Ġ* Ġ@ return Ġthe ĠServer Policy ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġnext Policy (): ĠServer Policy ? Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ next Policy ]") ĊĠĠĠĠĠĠĠ Ġcurrent Policy Ġ= Ġpolicies . poll () ĊĠĠĠĠĠĠĠ Ġcurrent Policy ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbackoff Ġ= ĠBack Off . Builder ( max Attempts Ġ= Ġit . retry Count Limit ). build () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġcurrent Policy ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Channel ( policy : ĠServer Policy , ĠonError : Ġ(( Throwable ) Ġ-> ĠUnit )? Ġ= Ġnull ) Ġ: ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġsynchronized ( this ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( current Channel Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Channel Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠChannel Builder Utils . create Channel Builder With ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpolicy , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġauth Delegate , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ Device Gateway Client ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ). build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( th : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠonError ?. invoke ( th ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif (! is Start Receive Server Initi ated Directive ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle On Connected () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Directives Service () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠConnect Ġto ĠDevice Gateway . ĊĠĠĠĠ Ġ* Ġ@ return Ġtrue Ġis Ġsuccess , Ġotherwise Ġfalse ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġconnect (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ connect ] Ġis Connected Ġ= Ġ${ isConnected ()}, Ġis Start Receive Server Initi ated Directive Ġ= Ġ${ is Start Receive Server Initi ated Directive () }") ĊĊĠĠĠĠĠĠĠ Ġif Ġ( isConnected ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . w ( TAG , Ġ"[ connect ] Ġalready Ġconnected ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġprocess Connection () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdisconnect Ġfrom ĠDevice Gateway ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġdisconnect () Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ disconnect ]") ĊĠĠĠĠĠĠĠ Ġprocess Disconnect () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġwhether Ġthis Ġobject Ġis Ġcurrently Ġconnected Ġto ĠDevice Gateway . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġis Connected (): ĠBoolean Ġ= Ġis Connected . get () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSends Ġa Ġmessage Ġrequest . ĊĠĠĠĠ Ġ* Ġ@ param Ġrequest Ġthe Ġmessage Request Ġto Ġbe Ġsent ĊĠĠĠĠ Ġ* Ġ@ return Ġtrue Ġis Ġsuccess , Ġotherwise Ġfalse ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġsend ( call : ĠCall ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= Ġcall . request () ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( request ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠAttachment Message Request Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġget Events Service ()?. send Attachment Message ( call )?. also Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . onComplete ( com . sk t . n ugu . sdk . core . interfaces . message . Status . OK ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ?: Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠEvent Message Request Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġget Events Service ()?. send Event Message ( call . also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . headers ()?. let Ġ{ Ġheaders Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpending Headers Ġ= Ġheaders ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) Ġ?: Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfalse ĊĠĠĠĠĠĠĠ Ġ}. also Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ" sendMessage Ġ: Ġ${ call . request (). toString Message ()}, Ġresult Ġ: Ġ$ result ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReceive Ġan Ġerror . ĊĠĠĠĠ Ġ* Ġ@ param Ġthe Ġstatus Ġof Ġgrpc ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun ĠonError ( status : ĠStatus , Ġwho : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . w ( TAG , Ġ"[ onError ] ĠError =${ status . code }, Ġwho =$ who ") ĊĊĠĠĠĠĠĠĠ Ġwhen ( status . code ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . UN AUTHENT IC ATED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnothing Ġto Ġdo ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . CANCEL LED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThis Ġis Ġnot Ġan Ġerror Ġbecause Ġit Ġis Ġgenerated Ġby Ġthe Ġcaller . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . w ( TAG , Ġ" The Ġoperation Ġwas Ġcancelled ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransport Observer ?. on Re connecting ( Ġwhen ( status . code ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . OK Ġ-> ĠChanged Reason . SUCCESS ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . UN AVAILABLE Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcause Ġ= Ġstatus . cause ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġreason Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( isConnected ()) ĠChanged Reason . SERVER _ SIDE _ DIS CONNECT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠChanged Reason . CONNECTION _ ERROR ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreason . cause Ġ= Ġcause ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( cause Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( cause Ġis ĠUnknown Host Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreason Ġ= ĠChanged Reason . DNS _ TIME DOUT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ Ġelse Ġif ( cause Ġis ĠSocket TimeoutException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreason Ġ= ĠChanged Reason . CONNECTION _ TIME DOUT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif ( Ġcause Ġis ĠConnect Exception Ġ|| Ġcause Ġis ĠSSL Handshake Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreason Ġ= ĠChanged Reason . CONNECTION _ ERROR ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcause Ġ= Ġcause . cause ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreason ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . UNKNOWN Ġ-> ĠChanged Reason . SERVER _ SIDE _ DIS CONNECT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . DEAD LINE _ EX CE EDED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( isConnected ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( Ping Service . name Ġ== Ġwho ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠChanged Reason . PING _ TIME DOUT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠChanged Reason . REQUEST _ TIME DOUT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠChanged Reason . CONNECTION _ TIME DOUT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . UN IMPLEMENTED Ġ-> ĠChanged Reason . FAILURE _ PROTOCOL _ ERROR ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . NOT _ FOUND Ġ, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . AL READY _ EXISTS Ġ, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . RESOURCE _ EX HA UST ED Ġ, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . FAILED _ PRE CONDITION Ġ, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . ABORT ED Ġ, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . PERMISSION _ DEN IED , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . INTERNAL Ġ-> ĠChanged Reason . SERVER _ INTERNAL _ ERROR ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . OUT _ OF _ RANGE , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . DATA _ LO SS , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . INVALID _ ARGUMENT Ġ-> ĠChanged Reason . INTERNAL _ ERROR ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠNotImplementedError () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġis Connected . set ( false ) ĊĠĠĠĠĠĠĠ Ġfirst Response Received . set ( false ) ĊĊĠĠĠĠĠĠĠ Ġbackoff . await Retry ( status . code , Ġobject Ġ: ĠBack Off . Observer Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun ĠonError ( error : ĠBack Off . Backoff Error ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . w ( TAG , Ġ"[ await Retry ] Ġerror =$ error , Ġcode =${ status . code }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen ( error ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBack Off . Backoff Error . Already Shutdown , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBack Off . Backoff Error . Already Started , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBack Off . Backoff Error . Schedule Cancelled Ġ-> Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠUnit ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( status . code ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStatus . Code . UN AUTHENT IC ATED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransport Observer ?. onError ( Changed Reason . INVALID _ AUTH ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Disconnect () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnext Policy () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Connection () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Retry ( retries At tempted : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . w ( TAG , Ġ"[ await Retry ] Ġon Retry Ġcount =$ retries At tempted , Ġconnected =${ isConnected ()}, Ġtid =${ Thread . currentThread (). id }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Disconnect () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Connection () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġshutdown () Ġ{ ĊĠĠĠĠĠĠĠ Ġmessage Consumer Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġtransport Observer Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġbackoff . shutdown () ĊĠĠĠĠĠĠĠ Ġscheduler . shutdown () ĊĠĠĠĠĠĠĠ Ġprocess Disconnect () ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ shutdown ]") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠHandler Ġfor Ġconnection Ġcompleted ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Visible ForTesting ĊĠĠĠ Ġinternal Ġfun Ġhandle On Connected () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( isConnected . compare AndSet ( false , Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ handle On Connected ] Ġis Connected Ġis Ġchanged ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġtransport Observer ?. on Connected () ĊĠĠĠĠĠĠĠ Ġdirectives Service ?. start () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprocess Disconnect () Ġ{ ĊĠĠĠĠĠĠĠ Ġis Connected . set ( false ) ĊĠĠĠĠĠĠĠ Ġfirst Response Received . set ( false ) ĊĊĠĠĠĠĠĠĠ Ġsynchronized ( this ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġping Service ?. shutdown () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġping Service Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdirectives Service ?. shutdown () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdirectives Service Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevents Service ?. shutdown () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevents Service Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ ĠChannel Builder Utils . shutdown ( current Channel ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Channel Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpending Headers Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprocess Connection (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpolicy Ġ= Ġcurrent Policy Ġ?: Ġrun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . w ( TAG , Ġ"[ connect ] Ġno Ġmore Ġpolicy ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġreason Ġ= ĠChanged Reason . UN RE COVER ABLE _ ERROR ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreason . cause Ġ= ĠThrowable (" no Ġmore Ġpolicy ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtransport Observer ?. onError ( reason ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ connect ] Ġpolicy Ġ= Ġ$ policy ") ĊĠĠĠĠĠĠĠ Ġreturn Ġcreate Channel ( policy ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . w ( TAG , Ġ"[ connect ] ĠCan 't Ġcreate Ġa Ġnew Ġchannel . ĠException : Ġ$ it ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġreason Ġ= ĠChanged Reason . CONNECTION _ ERROR ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreason . cause Ġ= Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtransport Observer ?. onError ( reason ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠNotification Ġthat Ġsending Ġa Ġping Ġto ĠDevice Gateway Ġhas Ġbeen Ġacknowled ged Ġby ĠDevice Gateway . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġon Ping Request Ack nowled ged () Ġ= Ġhandle On Connected (). also Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ" on Ping Request Ack nowled ged , Ġis Connected :${ isConnected () }") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġattachment Ġreceived ĊĠĠĠĠ Ġ* Ġ@ param Ġattachment Message ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġon Receive Attachment ( attachment Message : ĠAttachment Message ) Ġ{ ĊĠĠĠĠĠĠĠ Ġmessage Consumer ?. consume Attachment ( attachment Message . to Attachment Message ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdirective Ġreceived ĊĠĠĠĠ Ġ* Ġ@ param Ġdirective Message ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġon Receive Directives ( directive Message : ĠDirective Message ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠThe Ġbackoff Ġreset Ġis Ġat Ġthe Ġpoint Ġof Ġreceiving Ġthe Ġfirst Ġdirective Ġfrom Ġthe Ġserver . ĊĠĠĠĠĠĠĠ Ġif ( first Response Received . compare AndSet ( false , Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbackoff . reset () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġmessage Consumer ?. consume Directives ( directive Message . to Directives ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Headers () Ġ= Ġpending Headers ĊĊĠĠĠ Ġoverride Ġfun Ġstart Directives Service () Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ start Directives Service ] Ġis Connected =${ isConnected () }") ĊĠĠĠĠĠĠĠ Ġbuild Directives Service () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Events Service () Ġ: ĠEvents Service ? Ġ{ ĊĠĠĠĠĠĠĠ Ġif ( events Service Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Channel ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġevents Service Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠEvents Service ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ Device Gateway Client , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġscheduler , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall Options ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġevents Service ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġbuild Directives Service () Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ build Directives Service ] Ġcurrent Channel =$ current Channel ") ĊĊĠĠĠĠĠĠĠ Ġping Service ?. shutdown () ĊĠĠĠĠĠĠĠ Ġdirectives Service ?. shutdown () ĊĠĠĠĠĠĠĠ Ġcurrent Channel ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdirectives Service Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDirect ives Service ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ Device Gateway Client ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġping Service Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPing Service ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhealth Check Policy , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ Device Gateway Client ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġstop Directives Service () Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d ( TAG , Ġ"[ stop Directives Service ]") ĊĠĠĠĠĠĠĠ Ġprocess Disconnect () ĊĠĠĠĠĠĠĠ Ġprocess Connection () ĊĠĠĠ Ġ} Ċ } Ċ