Fix no timeout for handshake (#176)

This commit is contained in:
Otto Winter 2022-02-09 16:29:50 +01:00 committed by GitHub
parent 02160847e7
commit 3752b8280e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 3 deletions

View File

@ -179,7 +179,7 @@ class APINoiseFrameHelper(APIFrameHelper):
_LOGGER.debug("Received frame %s", frame.hex()) _LOGGER.debug("Received frame %s", frame.hex())
return frame return frame
async def perform_handshake(self, expected_name: Optional[str]) -> None: async def _perform_handshake(self, expected_name: Optional[str]) -> None:
await self._write_frame(b"") # ClientHello await self._write_frame(b"") # ClientHello
prologue = b"NoiseAPIInit" + b"\x00\x00" prologue = b"NoiseAPIInit" + b"\x00\x00"
@ -236,6 +236,13 @@ class APINoiseFrameHelper(APIFrameHelper):
_LOGGER.debug("Handshake complete!") _LOGGER.debug("Handshake complete!")
self._ready_event.set() self._ready_event.set()
async def perform_handshake(self, expected_name: Optional[str]) -> None:
# Allow up to 60 seconds for handhsake
try:
await asyncio.wait_for(self._perform_handshake(expected_name), timeout=60.0)
except asyncio.TimeoutError as err:
raise HandshakeAPIError("Timeout during handshake") from err
async def write_packet(self, packet: Packet) -> None: async def write_packet(self, packet: Packet) -> None:
# Wait for handshake to complete # Wait for handshake to complete
await self._ready_event.wait() await self._ready_event.wait()

View File

@ -164,7 +164,7 @@ class APIConnection:
except asyncio.TimeoutError as err: except asyncio.TimeoutError as err:
raise SocketAPIError(f"Timeout while connecting to {sockaddr}") from err raise SocketAPIError(f"Timeout while connecting to {sockaddr}") from err
_LOGGER.debug("%s: Opened socket for", self._params.address) _LOGGER.debug("%s: Opened socket", self._params.address)
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."""
@ -266,7 +266,7 @@ class APIConnection:
"Connection can only be used once, connection is not in init state" "Connection can only be used once, connection is not in init state"
) )
try: async def _do_connect() -> None:
addr = await self._connect_resolve_host() addr = await self._connect_resolve_host()
await self._connect_socket_connect(addr) await self._connect_socket_connect(addr)
await self._connect_init_frame_helper() await self._connect_init_frame_helper()
@ -274,6 +274,12 @@ class APIConnection:
await self._connect_start_ping() await self._connect_start_ping()
if login: if login:
await self.login() await self.login()
try:
# Allow 2 minutes for connect; this is only as a last measure
# to protect from issues if some part of the connect process mistakenly
# does not have a timeout
await asyncio.wait_for(_do_connect(), timeout=120.0)
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
# Always clean up the connection if an error occured during connect # Always clean up the connection if an error occured during connect
self._connection_state = ConnectionState.CLOSED self._connection_state = ConnectionState.CLOSED