package Ġcom . apps pector . websocket . handler Ċ Ċ import Ġcom . apps pector . websocket . Dispatcher Ċ import Ġio . netty . channel . Channel Future Ċ import Ġio . netty . channel . Channel HandlerContext Ċ import Ġio . netty . channel . Simple Channel Inbound Handler Ċ import Ġio . netty . handler . codec . http .* Ċ import Ġio . netty . handler . codec . http . websocket x .* Ċ import Ġio . netty . util . Attribute Key Ċ import Ġio . netty . util . concurrent . Generic Future Listener Ċ Ċ class ĠWebSocket Handler ( private Ġval Ġdispatcher : ĠDispatcher , Ġprivate Ġval Ġhost : ĠString ) Ġ: ĠSimple Channel Inbound Handler < Any >() Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġattribute SessionId Ġ= ĠAttribute Key . newInstance < String >(" session ID ") ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġattribute Client Ġ= ĠAttribute Key . newInstance < Client >(" ws _ client ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġchannel Read 0 ( context : ĠChannel HandlerContext , Ġmsg : ĠAny ) Ġ{ ĊĠĠĠĠĠĠĠ Ġwhen Ġ( msg ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠFull HttpRequest Ġ-> Ġreceived Request ( context , Ġmsg ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠPing WebSocket Frame Ġ-> Ġp ong ( context , Ġmsg ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠClose WebSocket Frame Ġ-> Ġreceived Close ( context , Ġmsg ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠText WebSocket Frame Ġ-> Ġreceived Payload ( context , Ġmsg ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġp ong ( context : ĠChannel HandlerContext , Ġframe : ĠPing WebSocket Frame ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . channel (). write ( P ong WebSocket Frame ( frame . content (). retain ())) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġreceived Close ( context : ĠChannel HandlerContext , Ġframe : Close WebSocket Frame Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . write ( Close WebSocket Frame ( frame . statusCode (), Ġ"")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Listeners ( Generic Future Listener < Channel Future > Ġ{ Ġcontext . close () Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġreceived Payload ( context : ĠChannel HandlerContext , Ġframe : ĠText WebSocket Frame ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreceived Payload ( context , Ġframe . text ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġreceived Request ( context : ĠChannel HandlerContext , Ġrequest : ĠFull HttpRequest ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠqueryString Decoder Ġ= ĠQuery String Decoder ( request . uri ()) ĊĠĠĠĠĠĠĠ Ġval Ġparameters Ġ= ĠqueryString Decoder . parameters () ĊĊĠĠĠĠĠĠĠ Ġval Ġsession ID Ġ= Ġparameters [" sessionId "] ?. get OrNull ( 0 ) ĊĠĠĠĠĠĠĠ Ġif Ġ( session ID Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . write ( Default Full HttpResponse ( Http Version . HTTP _ 1 _ 1 , ĠHttpResponse Status . BAD _ REQUEST )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġchannel Ġ= Ġcontext . channel () ĊĠĠĠĠĠĠĠ Ġchannel . attr ( attribute SessionId ). set ( session ID ) ĊĠĠĠĠĠĠĠ Ġval Ġws Factory Ġ= ĠWebSocket Server Hand sh aker Factory ( request . uri (), Ġnull , Ġtrue ) ĊĠĠĠĠĠĠĠ Ġval Ġhand sh aker Ġ= Ġws Factory . new Hand sh aker ( request ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( hand sh aker Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠWebSocket Server Hand sh aker Factory . send Unsupported Version Response ( channel ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhand sh aker . handshake ( channel , Ġrequest ). await () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( request . uri (). startsWith ("/ create ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . attr ( attribute Client ). set ( Client . SDK ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdispatcher . create Session Group ( session ID , Ġchannel ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( request . uri (). startsWith ("/ join ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . attr ( attribute Client ). set ( Client . FRONT END ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdispatcher . join Session Group ( session ID , Ġchannel ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġreceived Payload ( context : ĠChannel HandlerContext , Ġpayload : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġchannel Ġ= Ġcontext . channel () ĊĠĠĠĠĠĠĠ Ġval Ġclient Ġ= Ġchannel . attr ( attribute Client ) ĊĠĠĠĠĠĠĠ Ġval ĠsessionId Ġ= Ġchannel . attr ( attribute SessionId ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( client . get () Ġ== ĠClient . SDK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdispatcher . dispatchEvent ( sessionId . get (), Ġpayload ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprint (" Message Ġfrom ĠFrontend : Ġ$ payload ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġchannel Registered ( context : ĠChannel HandlerContext ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġchannel Ġ= Ġcontext . channel () ĊĠĠĠĠĠĠĠ Ġval Ġclient Ġ= Ġchannel . attr ( attribute Client ) ĊĠĠĠĠĠĠĠ Ġval ĠsessionId Ġ= Ġchannel . attr ( attribute SessionId ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( client . get () Ġ== ĠClient . FRONT END ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdispatcher . join Session Group ( sessionId . get (), Ġchannel ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsuper . channel Registered ( context ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġchannel Inactive ( context : ĠChannel HandlerContext ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġchannel Ġ= Ġcontext . channel () ĊĠĠĠĠĠĠĠ Ġval Ġclient Ġ= Ġchannel . attr ( attribute Client ) ĊĠĠĠĠĠĠĠ Ġval ĠsessionId Ġ= Ġchannel . attr ( attribute SessionId ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( client . get () Ġ== ĠClient . SDK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdispatcher . remove Session Group ( sessionId . get ()) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdispatcher . remove Frontend ( sessionId . get (), Ġchannel ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsuper . channel Inactive ( context ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġenum Ġclass ĠClient Ġ{ ĊĠĠĠĠĠĠĠ ĠSDK , ĠFR ONT END ĊĠĠĠ Ġ} Ċ }