package Ġorg . n kn . sdk Ċ Ċ import Ġandroid . util . Log Ċ import Ġorg . n kn . sdk . cache . multi Client Cache Ċ import Ġkotlinx . coroutines .* Ċ import Ġorg . json . JSONObject Ċ import Ġorg . n kn . sdk . configure .* Ċ import Ġorg . n kn . sdk . network . Rpc Api Ċ import Ġorg . n kn . sdk . network . Ws Api Ċ import Ġorg . n kn . sdk . protocol . PID _ SIZE Ċ import Ġorg . n kn . sdk . utils . Utils ĊĊ Ċ const Ġval ĠTAG Ġ= Ġ" Client " Ċ const Ġval Ġidentifier Regex Ġ= Ġ""" ^ __ \ d + __ """ Ċ fun Ġgen Identifier ( base : ĠString ?, Ġid : ĠInt ?): ĠString Ġ{ ĊĠĠĠ Ġif Ġ( id Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġbase !! ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġ"__ ${ id } __ " Ġ+ Ġ( if Ġ( base . isNull OrEmpty ()) Ġ"" Ġelse Ġ".$ base ") Ċ } Ċ Ċ fun Ġremove Identifier Prefix ( addr : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġreturn Ġaddr . replace ( Regex ("$ identifier Regex ."), Ġ"") Ċ } Ċ Ċ fun Ġget Identifier Prefix ( addr : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġreturn ĠRegex ("$ identifier Regex . "). find ( addr )?. value Ġ?: Ġ"" Ċ } ĊĊ Ċ class ĠClient Ġ@ Jvm Over loads Ġconstructor ( ĊĠĠĠ Ġseed : ĠString , ĊĠĠĠ Ġidentifier : ĠString ?, ĊĠĠĠ Ġval Ġseed Rpc Server : ĠList < String >? Ġ= Ġorg . n kn . sdk . configure . seed , ĊĠĠĠ Ġencrypt : ĠBoolean ? Ġ= ĠEN CRYPT , ĊĠĠĠ Ġval Ġmsg Hold ing Seconds : ĠInt ? Ġ= ĠMSG _ H OLD ING _ SECONDS , ĊĠĠĠ Ġval Ġreconnect Interval Min : ĠLong ? Ġ= ĠRE CONNECT _ INTERVAL _ MIN , ĊĠĠĠ Ġval Ġreconnect Interval Max : ĠLong ? Ġ= ĠRE CONNECT _ INTERVAL _ MAX , ĊĠĠĠ Ġresponse Timeout : ĠInt ? Ġ= ĠRESP ONSE _ TIMEOUT , ĊĠĠĠ Ġnum Sub Clients : ĠInt ? Ġ= Ġ 3 , ĊĠĠĠ Ġvar Ġlistener : ĠClient Listener ? Ġ= Ġnull , ĊĠĠĠ Ġmsg Cache Expire : ĠLong ? Ġ= Ġ 3 0 0 0 0 Ċ ) Ġ{ ĊĠĠĠ Ġval ĠhashCode Ġ= Ġthis . hashCode () ĊĠĠĠ Ġval Ġclients : ĠMutable List < Ws Api > ĊĠĠĠ Ġval Ġdefault Client Ġ= ĠW s Api ( ĊĠĠĠĠĠĠĠ Ġseed , ĊĠĠĠĠĠĠĠ Ġidentifier , ĊĠĠĠĠĠĠĠ Ġseed Rpc Server , ĊĠĠĠĠĠĠĠ Ġencrypt , ĊĠĠĠĠĠĠĠ Ġmsg Hold ing Seconds , ĊĠĠĠĠĠĠĠ Ġreconnect Interval Min , ĊĠĠĠĠĠĠĠ Ġreconnect Interval Max , ĊĠĠĠĠĠĠĠ Ġresponse Timeout , ĊĠĠĠĠĠĠĠ ĠMulti Client Listener () ĊĠĠĠ Ġ) ĊĠĠĠ Ġval Ġidentifier : ĠString Ġ= Ġidentifier Ġ?: Ġ"" ĊĠĠĠ Ġval Ġaddress Ġ= ĊĠĠĠĠĠĠĠ Ġif Ġ( this . identifier . isNull OrEmpty ()) Ġthis . default Client . key . publicKey Hash Ġelse Ġ"${ this . identifier }.${ this . default Client . key . publicKey Hash }" ĊĠĠĠ Ġvar Ġis Read ly Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar Ġconnect Jobs : ĠArrayList < Job > Ġ= ĠArrayList () ĊĠĠĠ Ġprivate Ġval Ġrpc Api Ġ= ĠRpc Api () ĊĊĠĠĠ Ġinner Ġclass ĠMulti Client Listener Ġ: ĠClient Listener () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Connect () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Read ly Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( multi Client Cache . get ( hashCode . toString ()) Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ""" Client Ġlistener Ġ" on Connect """ ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmulti Client Cache . put ( hashCode . toString (), Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlistener ?. on Connect () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Message ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsrc : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata : ĠString ?, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpid : ĠByteArray , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtype : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġencrypted : ĠBoolean ĊĊĠĠĠĠĠĠĠ Ġ): ĠAny ? Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpid Hash Ġ= ĠUtils . hex Encode ( pid ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( multi Client Cache . get ( pid Hash ) Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmulti Client Cache . put ( pid Hash , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġsrc Id Ġ= Ġremove Identifier Prefix ( src ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġlistener ?. on Message ( src Id , Ġdata , Ġpid , Ġtype , Ġencrypted ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Binary Message ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsrc : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata : ĠByteArray ?, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpid : ĠByteArray , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtype : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġencrypted : ĠBoolean ĊĠĠĠĠĠĠĠ Ġ): ĠAny ? Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpid Hash Ġ= ĠUtils . hex Encode ( pid ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( multi Client Cache . get ( pid Hash ) Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmulti Client Cache . put ( pid Hash , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġsrc Id Ġ= Ġremove Identifier Prefix ( src ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġlistener ?. on Binary Message ( src Id , Ġdata , Ġpid , Ġtype , Ġencrypted ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Closing () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlistener ?. on Closing () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Closed () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmulti Client Cache . remove ( hashCode . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlistener ?. on Closed () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun ĠonError ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmulti Client Cache . remove ( hashCode . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlistener ?. onError ( e ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Block () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlistener ?. on Block () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġclients Ġ= Ġmutable ListOf ( default Client ) ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġnum Sub Clients !! ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclients . add ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠW s Api ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġseed , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgen Identifier ( identifier , Ġi ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġseed Rpc Server , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġencrypt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmsg Hold ing Seconds , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreconnect Interval Min , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreconnect Interval Max , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponse Timeout , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMulti Client Listener () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġconnect () Ġ{ ĊĠĠĠĠĠĠĠ ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġclients ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconnect Jobs . add ( launch Ġ{ Ġi . connect () Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġclose () Ġ{ ĊĠĠĠĠĠĠĠ ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġclients ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclients . map Ġ{ Ġitem Ġ-> Ġlaunch Ġ{ Ġitem . close () Ġ} Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsend ( ĊĠĠĠĠĠĠĠ Ġdest : ĠString , ĊĠĠĠĠĠĠĠ Ġdata : ĠString , ĊĠĠĠĠĠĠĠ Ġpid : ĠByteArray ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġreply To Pid : ĠByteArray ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġno Reply : ĠBoolean ? Ġ= Ġfalse , ĊĠĠĠĠĠĠĠ Ġencrypt : ĠBoolean ? Ġ= Ġtrue , ĊĠĠĠĠĠĠĠ Ġmsg Hold ing Seconds : ĠInt ? Ġ= Ġthis . msg Hold ing Seconds ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġmsg Pid Ġ= Ġpid ĊĠĠĠĠĠĠĠ Ġif Ġ( pid Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmsg Pid Ġ= ĠUtils . random Bytes ( PID _ SIZE ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( is Read ly ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclients . map Ġ{ Ġitem Ġ-> Ġitem . send ( getIdentifier Prefix ( item . address ) Ġ+ Ġdest , Ġdata , Ġmsg Pid , Ġreply To Pid , Ġno Reply , Ġencrypt , Ġmsg Hold ing Seconds ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// todo Ġawait Ġconnect ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠThrowable (" not Ġconnected Ġyet ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsend ( ĊĠĠĠĠĠĠĠ Ġdest s : ĠArray < String >, ĊĠĠĠĠĠĠĠ Ġdata : ĠString , ĊĠĠĠĠĠĠĠ Ġpid : ĠByteArray ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġreply To Pid : ĠByteArray ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġno Reply : ĠBoolean ? Ġ= Ġfalse , ĊĠĠĠĠĠĠĠ Ġencrypt : ĠBoolean ? Ġ= Ġtrue , ĊĠĠĠĠĠĠĠ Ġmsg Hold ing Seconds : ĠInt ? Ġ= Ġthis . msg Hold ing Seconds ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġmsg Pid Ġ= Ġpid ĊĠĠĠĠĠĠĠ Ġif Ġ( pid Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmsg Pid Ġ= ĠUtils . random Bytes ( PID _ SIZE ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( is Read ly ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġclients . indices ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclients [ i ]. send ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdest s . map Ġ{ Ġdest Ġ-> Ġget Identifier Prefix ( clients [ i ]. address ) Ġ+ Ġdest Ġ}. to Typed Array (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdata , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmsg Pid , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreply To Pid , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġno Reply , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġencrypt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmsg Hold ing Seconds ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// todo Ġawait Ġconnect ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠThrowable (" not Ġconnected Ġyet ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Sub scribers ( topic : ĠString , Ġoffset : ĠInt Ġ= Ġ 0 , Ġlimit : ĠInt Ġ= Ġ 1 0 0 0 , Ġmeta : ĠBoolean Ġ= Ġfalse , Ġtx Pool : ĠBoolean Ġ= Ġfalse ): ĠJSONObject ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġrpc Api . getSub scribers ( topic , Ġoffset , Ġlimit , Ġmeta , Ġtx Pool ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Sub scribers Count ( topic : ĠString ): ĠJSONObject ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġrpc Api . getSub scribers Count ( topic ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Subscription ( topic : ĠString , Ġsubscriber : ĠString ): ĠJSONObject ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġrpc Api . get Subscription ( topic , Ġsubscriber ) ĊĠĠĠ Ġ} Ċ Ċ }