Avoid sending pings when we have traffic (#463)

This commit is contained in:
J. Nick Koston 2023-07-10 21:00:24 -10:00 committed by GitHub
parent 8ac62a321f
commit 6b0d84110e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -135,6 +135,8 @@ class APIConnection:
"_connect_task", "_connect_task",
"_fatal_exception", "_fatal_exception",
"_expected_disconnect", "_expected_disconnect",
"_loop",
"_send_pending_ping",
) )
def __init__( def __init__(
@ -172,6 +174,8 @@ class APIConnection:
self._connect_task: Optional[asyncio.Task[None]] = None self._connect_task: Optional[asyncio.Task[None]] = None
self._fatal_exception: Optional[Exception] = None self._fatal_exception: Optional[Exception] = None
self._expected_disconnect = False self._expected_disconnect = False
self._send_pending_ping = False
self._loop = asyncio.get_event_loop()
@property @property
def connection_state(self) -> ConnectionState: def connection_state(self) -> ConnectionState:
@ -271,7 +275,7 @@ class APIConnection:
sockaddr = astuple(addr.sockaddr) sockaddr = astuple(addr.sockaddr)
try: try:
coro = asyncio.get_event_loop().sock_connect(self._socket, sockaddr) coro = self._loop.sock_connect(self._socket, sockaddr)
async with async_timeout.timeout(TCP_CONNECT_TIMEOUT): async with async_timeout.timeout(TCP_CONNECT_TIMEOUT):
await coro await coro
except OSError as err: except OSError as err:
@ -290,7 +294,7 @@ class APIConnection:
async def _connect_init_frame_helper(self) -> None: async def _connect_init_frame_helper(self) -> None:
"""Step 3 in connect process: initialize the frame helper and init read loop.""" """Step 3 in connect process: initialize the frame helper and init read loop."""
fh: Union[APIPlaintextFrameHelper, APINoiseFrameHelper] fh: Union[APIPlaintextFrameHelper, APINoiseFrameHelper]
loop = asyncio.get_event_loop() loop = self._loop
if self._params.noise_psk is None: if self._params.noise_psk is None:
_, fh = await loop.create_connection( _, fh = await loop.create_connection(
@ -357,13 +361,10 @@ class APIConnection:
f"Server sent a different name '{resp.name}'", resp.name f"Server sent a different name '{resp.name}'", resp.name
) )
async def _connect_start_ping(self) -> None: def _async_schedule_keep_alive(self) -> None:
"""Step 5 in connect process: start the ping loop."""
self._async_schedule_keep_alive(asyncio.get_running_loop())
def _async_schedule_keep_alive(self, loop: asyncio.AbstractEventLoop) -> None:
"""Start the keep alive task.""" """Start the keep alive task."""
self._ping_timer = loop.call_later( self._send_pending_ping = True
self._ping_timer = self._loop.call_later(
self._keep_alive_interval, self._async_send_keep_alive self._keep_alive_interval, self._async_send_keep_alive
) )
@ -372,14 +373,14 @@ class APIConnection:
if not self._is_socket_open: if not self._is_socket_open:
return return
loop = asyncio.get_running_loop() if self._send_pending_ping:
self.send_message(PING_REQUEST_MESSAGE) self.send_message(PING_REQUEST_MESSAGE)
if self._pong_timer is None: if self._pong_timer is None:
# Do not reset the timer if it's already set # Do not reset the timer if it's already set
# since the only thing we want to reset the timer # since the only thing we want to reset the timer
# is if we receive a pong. # is if we receive a pong.
self._pong_timer = loop.call_later( self._pong_timer = self._loop.call_later(
self._keep_alive_timeout, self._async_pong_not_received self._keep_alive_timeout, self._async_pong_not_received
) )
else: else:
@ -399,7 +400,7 @@ class APIConnection:
self._keep_alive_interval, self._keep_alive_interval,
) )
self._async_schedule_keep_alive(loop) self._async_schedule_keep_alive()
def _async_cancel_pong_timer(self) -> None: def _async_cancel_pong_timer(self) -> None:
"""Cancel the pong timer.""" """Cancel the pong timer."""
@ -434,7 +435,7 @@ class APIConnection:
await self._connect_socket_connect(addr) await self._connect_socket_connect(addr)
await self._connect_init_frame_helper() await self._connect_init_frame_helper()
await self._connect_hello() await self._connect_hello()
await self._connect_start_ping() self._async_schedule_keep_alive()
if login: if login:
await self.login(check_connected=False) await self.login(check_connected=False)
@ -599,7 +600,7 @@ class APIConnection:
:raises TimeoutAPIError: if a timeout occured :raises TimeoutAPIError: if a timeout occured
""" """
fut = asyncio.get_event_loop().create_future() fut = self._loop.create_future()
responses = [] responses = []
def on_message(resp: message.Message) -> None: def on_message(resp: message.Message) -> None:
@ -725,6 +726,11 @@ class APIConnection:
# as we know the connection is still alive # as we know the connection is still alive
self._async_cancel_pong_timer() self._async_cancel_pong_timer()
if self._send_pending_ping:
# Any valid message from the remove cancels the pending ping
# since we know the connection is still alive
self._send_pending_ping = False
for handler in self._message_handlers.get(msg_type, [])[:]: for handler in self._message_handlers.get(msg_type, [])[:]:
handler(msg) handler(msg)