[quic] improve H3 close connection

This commit is contained in:
Manuel Meitinger 2022-11-07 04:12:35 +01:00
parent 97ca30ce6f
commit 206e2f50eb
3 changed files with 18 additions and 9 deletions

View File

@ -162,19 +162,23 @@ class Http3Connection(HttpConnection):
yield from self.h3_conn.transmit()
# report a protocol error for all remaining open streams when a connection is closed
elif isinstance(event, events.ConnectionClosed):
elif isinstance(event, QuicConnectionClosed):
self._handle_event = self.done # type: ignore
if isinstance(event, QuicConnectionClosed):
msg = event.reason_phrase or error_code_to_str(event.error_code)
else:
msg = "peer closed connection"
for stream_id in self.h3_conn.get_reserved_stream_ids():
yield ReceiveHttp(self.ReceiveProtocolError(stream_id, msg))
# turn `QuicErrorCode.NO_ERROR` into `H3ErrorCode.H3_NO_ERROR`
self.h3_conn.close_connection(
event.error_code or H3ErrorCode.H3_NO_ERROR,
event.frame_type,
event.reason_phrase,
)
yield from self.h3_conn.transmit()
else:
raise AssertionError(f"Unexpected event: {event!r}")
@expect(QuicStreamEvent, HttpEvent, events.ConnectionClosed)
@expect(HttpEvent, QuicStreamEvent, QuicConnectionClosed)
def done(self, _) -> layer.CommandGenerator[None]:
yield from ()

View File

@ -143,11 +143,16 @@ class LayeredH3Connection(H3Connection):
events[index] = TrailersReceived(event.headers, event.stream_id, event.stream_ended, event.push_id)
return events
def close_connection(self, error_code: int = QuicErrorCode.NO_ERROR, reason_phrase: str = "") -> None:
def close_connection(
self,
error_code: int = QuicErrorCode.NO_ERROR,
frame_type: Optional[int] = None,
reason_phrase: str = "",
) -> None:
"""Closes the underlying QUIC connection and ignores any incoming events."""
self._is_done = True
self._quic.close(error_code=error_code, reason_phrase=reason_phrase)
self._quic.close(error_code, frame_type, reason_phrase)
def end_stream(self, stream_id: int) -> None:
"""Ends the given stream locally."""

View File

@ -927,7 +927,7 @@ class QuicLayer(tunnel.TunnelLayer):
# if `_close_event` is not set, the underlying connection has been closed
# we turn this into a QUIC close event as well
close_event = self.quic._close_event or quic_events.ConnectionTerminated(
QuicErrorCode.APPLICATION_ERROR, None, "Connection closed."
QuicErrorCode.NO_ERROR, None, "Connection closed."
)
yield from self.event_to_child(
QuicConnectionClosed(self.conn, close_event.error_code, close_event.frame_type, close_event.reason_phrase)