| 257 | |
| 258 | |
| 259 | class Http3Client(Http3Connection): |
| 260 | ReceiveData = ResponseData |
| 261 | ReceiveEndOfMessage = ResponseEndOfMessage |
| 262 | ReceiveProtocolError = ResponseProtocolError |
| 263 | ReceiveTrailers = ResponseTrailers |
| 264 | |
| 265 | our_stream_id: dict[int, int] |
| 266 | their_stream_id: dict[int, int] |
| 267 | |
| 268 | def __init__(self, context: context.Context): |
| 269 | super().__init__(context, context.server) |
| 270 | self.our_stream_id = {} |
| 271 | self.their_stream_id = {} |
| 272 | |
| 273 | def _handle_event(self, event: events.Event) -> layer.CommandGenerator[None]: |
| 274 | # QUIC and HTTP/3 would actually allow for direct stream ID mapping, but since we want |
| 275 | # to support H2<->H3, we need to translate IDs. |
| 276 | # NOTE: We always create bidirectional streams, as we can't safely infer unidirectionality. |
| 277 | if isinstance(event, HttpEvent): |
| 278 | ours = self.our_stream_id.get(event.stream_id, None) |
| 279 | if ours is None: |
| 280 | ours = self.h3_conn.get_next_available_stream_id() |
| 281 | self.our_stream_id[event.stream_id] = ours |
| 282 | self.their_stream_id[ours] = event.stream_id |
| 283 | event.stream_id = ours |
| 284 | |
| 285 | for cmd in super()._handle_event(event): |
| 286 | if isinstance(cmd, ReceiveHttp): |
| 287 | cmd.event.stream_id = self.their_stream_id[cmd.event.stream_id] |
| 288 | yield cmd |
| 289 | |
| 290 | def parse_headers(self, event: HeadersReceived) -> RequestHeaders | ResponseHeaders: |
| 291 | # same as HTTP/2 |
| 292 | status_code, headers = parse_h2_response_headers(event.headers) |
| 293 | response = http.Response( |
| 294 | http_version=b"HTTP/3", |
| 295 | status_code=status_code, |
| 296 | reason=b"", |
| 297 | headers=headers, |
| 298 | content=None, |
| 299 | trailers=None, |
| 300 | timestamp_start=time.time(), |
| 301 | timestamp_end=None, |
| 302 | ) |
| 303 | return ResponseHeaders(event.stream_id, response, event.stream_ended) |
| 304 | |
| 305 | |
| 306 | __all__ = [ |
no outgoing calls
searching dependent graphs…