66from uuid import uuid4
77from signalwire .blade .connection import Connection
88from signalwire .blade .messages .connect import Connect
9+ from signalwire .blade .messages .ping import Ping
910from signalwire .blade .handler import register , unregister , trigger
1011from .helpers import setup_protocol
1112from .calling import Calling
1516from .constants import Constants , WebSocketEvents
1617
1718class Client :
19+ PING_DELAY = 10
20+
1821 def __init__ (self , project , token , host = Constants .HOST , connection = Connection ):
1922 self .loop = asyncio .get_event_loop ()
2023 self .host = host
@@ -34,6 +37,7 @@ def __init__(self, project, token, host=Constants.HOST, connection=Connection):
3437 self ._requests = {}
3538 self ._idle = False
3639 self ._executeQueue = asyncio .Queue ()
40+ self ._pingInterval = None
3741 log_level = os .getenv ('LOG_LEVEL' , 'INFO' ).upper ()
3842 logging .basicConfig (level = log_level )
3943
@@ -79,7 +83,7 @@ async def _connect(self):
7983 await self .connection .connect ()
8084 asyncio .create_task (self .on_socket_open ())
8185 await self .connection .read ()
82- trigger ( WebSocketEvents . CLOSE , suffix = self .uuid )
86+ self .on_socket_close ( )
8387 except aiohttp .client_exceptions .ClientConnectorError as error :
8488 trigger (WebSocketEvents .ERROR , error , suffix = self .uuid )
8589 logging .warn (f"{ self .host } seems down.." )
@@ -122,6 +126,12 @@ def attach_signals(self):
122126 except :
123127 pass
124128
129+ def on_socket_close (self ):
130+ if self ._pingInterval :
131+ self ._pingInterval .cancel ()
132+ self .contexts = []
133+ trigger (WebSocketEvents .CLOSE , suffix = self .uuid )
134+
125135 async def on_socket_open (self ):
126136 try :
127137 self ._idle = False
@@ -131,12 +141,24 @@ async def on_socket_open(self):
131141 self .signature = result ['authorization' ]['signature' ]
132142 self .protocol = await setup_protocol (self )
133143 await self ._clearExecuteQueue ()
144+ self ._pong = True
145+ self .keepalive ()
134146 logging .info ('Client connected!' )
135147 trigger (Constants .READY , self , suffix = self .uuid )
136148 except Exception as error :
137149 logging .error ('Client setup error: {0}' .format (str (error )))
138150 await self .connection .close ()
139151
152+ def keepalive (self ):
153+ async def send_ping ():
154+ if self ._pong is False :
155+ return await self .connection .close ()
156+ self ._pong = False
157+ await self .execute (Ping ())
158+ self ._pong = True
159+ asyncio .create_task (send_ping ())
160+ self ._pingInterval = self .loop .call_later (self .PING_DELAY , self .keepalive )
161+
140162 async def _clearExecuteQueue (self ):
141163 while True :
142164 if self ._executeQueue .empty ():
0 commit comments