| 1354 | protocol = None # type: WebSocketProtocol |
| 1355 | |
| 1356 | def __init__( |
| 1357 | self, |
| 1358 | request: httpclient.HTTPRequest, |
| 1359 | on_message_callback: Optional[Callable[[Union[None, str, bytes]], None]] = None, |
| 1360 | compression_options: Optional[Dict[str, Any]] = None, |
| 1361 | ping_interval: Optional[float] = None, |
| 1362 | ping_timeout: Optional[float] = None, |
| 1363 | max_message_size: int = _default_max_message_size, |
| 1364 | subprotocols: Optional[List[str]] = [], |
| 1365 | ) -> None: |
| 1366 | self.connect_future = Future() # type: Future[WebSocketClientConnection] |
| 1367 | self.read_queue = Queue(1) # type: Queue[Union[None, str, bytes]] |
| 1368 | self.key = base64.b64encode(os.urandom(16)) |
| 1369 | self._on_message_callback = on_message_callback |
| 1370 | self.close_code = None # type: Optional[int] |
| 1371 | self.close_reason = None # type: Optional[str] |
| 1372 | self.params = _WebSocketParams( |
| 1373 | ping_interval=ping_interval, |
| 1374 | ping_timeout=ping_timeout, |
| 1375 | max_message_size=max_message_size, |
| 1376 | compression_options=compression_options, |
| 1377 | ) |
| 1378 | |
| 1379 | scheme, sep, rest = request.url.partition(":") |
| 1380 | scheme = {"ws": "http", "wss": "https"}[scheme] |
| 1381 | request.url = scheme + sep + rest |
| 1382 | request.headers.update( |
| 1383 | { |
| 1384 | "Upgrade": "websocket", |
| 1385 | "Connection": "Upgrade", |
| 1386 | "Sec-WebSocket-Key": self.key, |
| 1387 | "Sec-WebSocket-Version": "13", |
| 1388 | } |
| 1389 | ) |
| 1390 | if subprotocols is not None: |
| 1391 | request.headers["Sec-WebSocket-Protocol"] = ",".join(subprotocols) |
| 1392 | if compression_options is not None: |
| 1393 | # Always offer to let the server set our max_wbits (and even though |
| 1394 | # we don't offer it, we will accept a client_no_context_takeover |
| 1395 | # from the server). |
| 1396 | # TODO: set server parameters for deflate extension |
| 1397 | # if requested in self.compression_options. |
| 1398 | request.headers[ |
| 1399 | "Sec-WebSocket-Extensions" |
| 1400 | ] = "permessage-deflate; client_max_window_bits" |
| 1401 | |
| 1402 | # Websocket connection is currently unable to follow redirects |
| 1403 | request.follow_redirects = False |
| 1404 | |
| 1405 | self.tcp_client = TCPClient() |
| 1406 | super().__init__( |
| 1407 | None, |
| 1408 | request, |
| 1409 | lambda: None, |
| 1410 | self._on_http_response, |
| 1411 | 104857600, |
| 1412 | self.tcp_client, |
| 1413 | 65536, |