PageRenderTime 27ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/tools/third_party/websockets/src/websockets/protocol.py

https://gitlab.com/Spagnotti3/wpt
Python | 1291 lines | 1188 code | 52 blank | 51 comment | 50 complexity | 47db65b7e97ea5bc2c523ebdc0665f50 MD5 | raw file
  1. """
  2. :mod:`websockets.protocol` handles WebSocket control and data frames.
  3. See `sections 4 to 8 of RFC 6455`_.
  4. .. _sections 4 to 8 of RFC 6455: http://tools.ietf.org/html/rfc6455#section-4
  5. """
  6. import asyncio
  7. import codecs
  8. import collections
  9. import enum
  10. import logging
  11. import random
  12. import struct
  13. import sys
  14. import warnings
  15. from typing import (
  16. Any,
  17. AsyncIterable,
  18. AsyncIterator,
  19. Awaitable,
  20. Deque,
  21. Dict,
  22. Iterable,
  23. List,
  24. Optional,
  25. Union,
  26. cast,
  27. )
  28. from .exceptions import (
  29. ConnectionClosed,
  30. ConnectionClosedError,
  31. ConnectionClosedOK,
  32. InvalidState,
  33. PayloadTooBig,
  34. ProtocolError,
  35. )
  36. from .extensions.base import Extension
  37. from .framing import *
  38. from .handshake import *
  39. from .http import Headers
  40. from .typing import Data
  41. __all__ = ["WebSocketCommonProtocol"]
  42. logger = logging.getLogger(__name__)
  43. # A WebSocket connection goes through the following four states, in order:
  44. class State(enum.IntEnum):
  45. CONNECTING, OPEN, CLOSING, CLOSED = range(4)
  46. # In order to ensure consistency, the code always checks the current value of
  47. # WebSocketCommonProtocol.state before assigning a new value and never yields
  48. # between the check and the assignment.
  49. class WebSocketCommonProtocol(asyncio.Protocol):
  50. """
  51. :class:`~asyncio.Protocol` subclass implementing the data transfer phase.
  52. Once the WebSocket connection is established, during the data transfer
  53. phase, the protocol is almost symmetrical between the server side and the
  54. client side. :class:`WebSocketCommonProtocol` implements logic that's
  55. shared between servers and clients..
  56. Subclasses such as :class:`~websockets.server.WebSocketServerProtocol` and
  57. :class:`~websockets.client.WebSocketClientProtocol` implement the opening
  58. handshake, which is different between servers and clients.
  59. :class:`WebSocketCommonProtocol` performs four functions:
  60. * It runs a task that stores incoming data frames in a queue and makes
  61. them available with the :meth:`recv` coroutine.
  62. * It sends outgoing data frames with the :meth:`send` coroutine.
  63. * It deals with control frames automatically.
  64. * It performs the closing handshake.
  65. :class:`WebSocketCommonProtocol` supports asynchronous iteration::
  66. async for message in websocket:
  67. await process(message)
  68. The iterator yields incoming messages. It exits normally when the
  69. connection is closed with the close code 1000 (OK) or 1001 (going away).
  70. It raises a :exc:`~websockets.exceptions.ConnectionClosedError` exception
  71. when the connection is closed with any other code.
  72. Once the connection is open, a `Ping frame`_ is sent every
  73. ``ping_interval`` seconds. This serves as a keepalive. It helps keeping
  74. the connection open, especially in the presence of proxies with short
  75. timeouts on inactive connections. Set ``ping_interval`` to ``None`` to
  76. disable this behavior.
  77. .. _Ping frame: https://tools.ietf.org/html/rfc6455#section-5.5.2
  78. If the corresponding `Pong frame`_ isn't received within ``ping_timeout``
  79. seconds, the connection is considered unusable and is closed with
  80. code 1011. This ensures that the remote endpoint remains responsive. Set
  81. ``ping_timeout`` to ``None`` to disable this behavior.
  82. .. _Pong frame: https://tools.ietf.org/html/rfc6455#section-5.5.3
  83. The ``close_timeout`` parameter defines a maximum wait time in seconds for
  84. completing the closing handshake and terminating the TCP connection.
  85. :meth:`close` completes in at most ``4 * close_timeout`` on the server
  86. side and ``5 * close_timeout`` on the client side.
  87. ``close_timeout`` needs to be a parameter of the protocol because
  88. ``websockets`` usually calls :meth:`close` implicitly:
  89. - on the server side, when the connection handler terminates,
  90. - on the client side, when exiting the context manager for the connection.
  91. To apply a timeout to any other API, wrap it in :func:`~asyncio.wait_for`.
  92. The ``max_size`` parameter enforces the maximum size for incoming messages
  93. in bytes. The default value is 1 MiB. ``None`` disables the limit. If a
  94. message larger than the maximum size is received, :meth:`recv` will
  95. raise :exc:`~websockets.exceptions.ConnectionClosedError` and the
  96. connection will be closed with code 1009.
  97. The ``max_queue`` parameter sets the maximum length of the queue that
  98. holds incoming messages. The default value is ``32``. ``None`` disables
  99. the limit. Messages are added to an in-memory queue when they're received;
  100. then :meth:`recv` pops from that queue. In order to prevent excessive
  101. memory consumption when messages are received faster than they can be
  102. processed, the queue must be bounded. If the queue fills up, the protocol
  103. stops processing incoming data until :meth:`recv` is called. In this
  104. situation, various receive buffers (at least in ``asyncio`` and in the OS)
  105. will fill up, then the TCP receive window will shrink, slowing down
  106. transmission to avoid packet loss.
  107. Since Python can use up to 4 bytes of memory to represent a single
  108. character, each connection may use up to ``4 * max_size * max_queue``
  109. bytes of memory to store incoming messages. By default, this is 128 MiB.
  110. You may want to lower the limits, depending on your application's
  111. requirements.
  112. The ``read_limit`` argument sets the high-water limit of the buffer for
  113. incoming bytes. The low-water limit is half the high-water limit. The
  114. default value is 64 KiB, half of asyncio's default (based on the current
  115. implementation of :class:`~asyncio.StreamReader`).
  116. The ``write_limit`` argument sets the high-water limit of the buffer for
  117. outgoing bytes. The low-water limit is a quarter of the high-water limit.
  118. The default value is 64 KiB, equal to asyncio's default (based on the
  119. current implementation of ``FlowControlMixin``).
  120. As soon as the HTTP request and response in the opening handshake are
  121. processed:
  122. * the request path is available in the :attr:`path` attribute;
  123. * the request and response HTTP headers are available in the
  124. :attr:`request_headers` and :attr:`response_headers` attributes,
  125. which are :class:`~websockets.http.Headers` instances.
  126. If a subprotocol was negotiated, it's available in the :attr:`subprotocol`
  127. attribute.
  128. Once the connection is closed, the code is available in the
  129. :attr:`close_code` attribute and the reason in :attr:`close_reason`.
  130. All these attributes must be treated as read-only.
  131. """
  132. # There are only two differences between the client-side and server-side
  133. # behavior: masking the payload and closing the underlying TCP connection.
  134. # Set is_client = True/False and side = "client"/"server" to pick a side.
  135. is_client: bool
  136. side: str = "undefined"
  137. def __init__(
  138. self,
  139. *,
  140. ping_interval: Optional[float] = 20,
  141. ping_timeout: Optional[float] = 20,
  142. close_timeout: Optional[float] = None,
  143. max_size: Optional[int] = 2 ** 20,
  144. max_queue: Optional[int] = 2 ** 5,
  145. read_limit: int = 2 ** 16,
  146. write_limit: int = 2 ** 16,
  147. loop: Optional[asyncio.AbstractEventLoop] = None,
  148. # The following arguments are kept only for backwards compatibility.
  149. host: Optional[str] = None,
  150. port: Optional[int] = None,
  151. secure: Optional[bool] = None,
  152. legacy_recv: bool = False,
  153. timeout: Optional[float] = None,
  154. ) -> None:
  155. # Backwards compatibility: close_timeout used to be called timeout.
  156. if timeout is None:
  157. timeout = 10
  158. else:
  159. warnings.warn("rename timeout to close_timeout", DeprecationWarning)
  160. # If both are specified, timeout is ignored.
  161. if close_timeout is None:
  162. close_timeout = timeout
  163. self.ping_interval = ping_interval
  164. self.ping_timeout = ping_timeout
  165. self.close_timeout = close_timeout
  166. self.max_size = max_size
  167. self.max_queue = max_queue
  168. self.read_limit = read_limit
  169. self.write_limit = write_limit
  170. if loop is None:
  171. loop = asyncio.get_event_loop()
  172. self.loop = loop
  173. self._host = host
  174. self._port = port
  175. self._secure = secure
  176. self.legacy_recv = legacy_recv
  177. # Configure read buffer limits. The high-water limit is defined by
  178. # ``self.read_limit``. The ``limit`` argument controls the line length
  179. # limit and half the buffer limit of :class:`~asyncio.StreamReader`.
  180. # That's why it must be set to half of ``self.read_limit``.
  181. self.reader = asyncio.StreamReader(limit=read_limit // 2, loop=loop)
  182. # Copied from asyncio.FlowControlMixin
  183. self._paused = False
  184. self._drain_waiter: Optional[asyncio.Future[None]] = None
  185. self._drain_lock = asyncio.Lock(
  186. loop=loop if sys.version_info[:2] < (3, 8) else None
  187. )
  188. # This class implements the data transfer and closing handshake, which
  189. # are shared between the client-side and the server-side.
  190. # Subclasses implement the opening handshake and, on success, execute
  191. # :meth:`connection_open` to change the state to OPEN.
  192. self.state = State.CONNECTING
  193. logger.debug("%s - state = CONNECTING", self.side)
  194. # HTTP protocol parameters.
  195. self.path: str
  196. self.request_headers: Headers
  197. self.response_headers: Headers
  198. # WebSocket protocol parameters.
  199. self.extensions: List[Extension] = []
  200. self.subprotocol: Optional[str] = None
  201. # The close code and reason are set when receiving a close frame or
  202. # losing the TCP connection.
  203. self.close_code: int
  204. self.close_reason: str
  205. # Completed when the connection state becomes CLOSED. Translates the
  206. # :meth:`connection_lost` callback to a :class:`~asyncio.Future`
  207. # that can be awaited. (Other :class:`~asyncio.Protocol` callbacks are
  208. # translated by ``self.stream_reader``).
  209. self.connection_lost_waiter: asyncio.Future[None] = loop.create_future()
  210. # Queue of received messages.
  211. self.messages: Deque[Data] = collections.deque()
  212. self._pop_message_waiter: Optional[asyncio.Future[None]] = None
  213. self._put_message_waiter: Optional[asyncio.Future[None]] = None
  214. # Protect sending fragmented messages.
  215. self._fragmented_message_waiter: Optional[asyncio.Future[None]] = None
  216. # Mapping of ping IDs to waiters, in chronological order.
  217. self.pings: Dict[bytes, asyncio.Future[None]] = {}
  218. # Task running the data transfer.
  219. self.transfer_data_task: asyncio.Task[None]
  220. # Exception that occurred during data transfer, if any.
  221. self.transfer_data_exc: Optional[BaseException] = None
  222. # Task sending keepalive pings.
  223. self.keepalive_ping_task: asyncio.Task[None]
  224. # Task closing the TCP connection.
  225. self.close_connection_task: asyncio.Task[None]
  226. # Copied from asyncio.FlowControlMixin
  227. async def _drain_helper(self) -> None: # pragma: no cover
  228. if self.connection_lost_waiter.done():
  229. raise ConnectionResetError("Connection lost")
  230. if not self._paused:
  231. return
  232. waiter = self._drain_waiter
  233. assert waiter is None or waiter.cancelled()
  234. waiter = self.loop.create_future()
  235. self._drain_waiter = waiter
  236. await waiter
  237. # Copied from asyncio.StreamWriter
  238. async def _drain(self) -> None: # pragma: no cover
  239. if self.reader is not None:
  240. exc = self.reader.exception()
  241. if exc is not None:
  242. raise exc
  243. if self.transport is not None:
  244. if self.transport.is_closing():
  245. # Yield to the event loop so connection_lost() may be
  246. # called. Without this, _drain_helper() would return
  247. # immediately, and code that calls
  248. # write(...); yield from drain()
  249. # in a loop would never call connection_lost(), so it
  250. # would not see an error when the socket is closed.
  251. await asyncio.sleep(
  252. 0, loop=self.loop if sys.version_info[:2] < (3, 8) else None
  253. )
  254. await self._drain_helper()
  255. def connection_open(self) -> None:
  256. """
  257. Callback when the WebSocket opening handshake completes.
  258. Enter the OPEN state and start the data transfer phase.
  259. """
  260. # 4.1. The WebSocket Connection is Established.
  261. assert self.state is State.CONNECTING
  262. self.state = State.OPEN
  263. logger.debug("%s - state = OPEN", self.side)
  264. # Start the task that receives incoming WebSocket messages.
  265. self.transfer_data_task = self.loop.create_task(self.transfer_data())
  266. # Start the task that sends pings at regular intervals.
  267. self.keepalive_ping_task = self.loop.create_task(self.keepalive_ping())
  268. # Start the task that eventually closes the TCP connection.
  269. self.close_connection_task = self.loop.create_task(self.close_connection())
  270. @property
  271. def host(self) -> Optional[str]:
  272. alternative = "remote_address" if self.is_client else "local_address"
  273. warnings.warn(f"use {alternative}[0] instead of host", DeprecationWarning)
  274. return self._host
  275. @property
  276. def port(self) -> Optional[int]:
  277. alternative = "remote_address" if self.is_client else "local_address"
  278. warnings.warn(f"use {alternative}[1] instead of port", DeprecationWarning)
  279. return self._port
  280. @property
  281. def secure(self) -> Optional[bool]:
  282. warnings.warn(f"don't use secure", DeprecationWarning)
  283. return self._secure
  284. # Public API
  285. @property
  286. def local_address(self) -> Any:
  287. """
  288. Local address of the connection.
  289. This is a ``(host, port)`` tuple or ``None`` if the connection hasn't
  290. been established yet.
  291. """
  292. try:
  293. transport = self.transport
  294. except AttributeError:
  295. return None
  296. else:
  297. return transport.get_extra_info("sockname")
  298. @property
  299. def remote_address(self) -> Any:
  300. """
  301. Remote address of the connection.
  302. This is a ``(host, port)`` tuple or ``None`` if the connection hasn't
  303. been established yet.
  304. """
  305. try:
  306. transport = self.transport
  307. except AttributeError:
  308. return None
  309. else:
  310. return transport.get_extra_info("peername")
  311. @property
  312. def open(self) -> bool:
  313. """
  314. ``True`` when the connection is usable.
  315. It may be used to detect disconnections. However, this approach is
  316. discouraged per the EAFP_ principle.
  317. When ``open`` is ``False``, using the connection raises a
  318. :exc:`~websockets.exceptions.ConnectionClosed` exception.
  319. .. _EAFP: https://docs.python.org/3/glossary.html#term-eafp
  320. """
  321. return self.state is State.OPEN and not self.transfer_data_task.done()
  322. @property
  323. def closed(self) -> bool:
  324. """
  325. ``True`` once the connection is closed.
  326. Be aware that both :attr:`open` and :attr:`closed` are ``False`` during
  327. the opening and closing sequences.
  328. """
  329. return self.state is State.CLOSED
  330. async def wait_closed(self) -> None:
  331. """
  332. Wait until the connection is closed.
  333. This is identical to :attr:`closed`, except it can be awaited.
  334. This can make it easier to handle connection termination, regardless
  335. of its cause, in tasks that interact with the WebSocket connection.
  336. """
  337. await asyncio.shield(self.connection_lost_waiter)
  338. async def __aiter__(self) -> AsyncIterator[Data]:
  339. """
  340. Iterate on received messages.
  341. Exit normally when the connection is closed with code 1000 or 1001.
  342. Raise an exception in other cases.
  343. """
  344. try:
  345. while True:
  346. yield await self.recv()
  347. except ConnectionClosedOK:
  348. return
  349. async def recv(self) -> Data:
  350. """
  351. Receive the next message.
  352. Return a :class:`str` for a text frame and :class:`bytes` for a binary
  353. frame.
  354. When the end of the message stream is reached, :meth:`recv` raises
  355. :exc:`~websockets.exceptions.ConnectionClosed`. Specifically, it
  356. raises :exc:`~websockets.exceptions.ConnectionClosedOK` after a normal
  357. connection closure and
  358. :exc:`~websockets.exceptions.ConnectionClosedError` after a protocol
  359. error or a network failure.
  360. .. versionchanged:: 3.0
  361. :meth:`recv` used to return ``None`` instead. Refer to the
  362. changelog for details.
  363. Canceling :meth:`recv` is safe. There's no risk of losing the next
  364. message. The next invocation of :meth:`recv` will return it. This
  365. makes it possible to enforce a timeout by wrapping :meth:`recv` in
  366. :func:`~asyncio.wait_for`.
  367. :raises ~websockets.exceptions.ConnectionClosed: when the
  368. connection is closed
  369. :raises RuntimeError: if two coroutines call :meth:`recv` concurrently
  370. """
  371. if self._pop_message_waiter is not None:
  372. raise RuntimeError(
  373. "cannot call recv while another coroutine "
  374. "is already waiting for the next message"
  375. )
  376. # Don't await self.ensure_open() here:
  377. # - messages could be available in the queue even if the connection
  378. # is closed;
  379. # - messages could be received before the closing frame even if the
  380. # connection is closing.
  381. # Wait until there's a message in the queue (if necessary) or the
  382. # connection is closed.
  383. while len(self.messages) <= 0:
  384. pop_message_waiter: asyncio.Future[None] = self.loop.create_future()
  385. self._pop_message_waiter = pop_message_waiter
  386. try:
  387. # If asyncio.wait() is canceled, it doesn't cancel
  388. # pop_message_waiter and self.transfer_data_task.
  389. await asyncio.wait(
  390. [pop_message_waiter, self.transfer_data_task],
  391. loop=self.loop if sys.version_info[:2] < (3, 8) else None,
  392. return_when=asyncio.FIRST_COMPLETED,
  393. )
  394. finally:
  395. self._pop_message_waiter = None
  396. # If asyncio.wait(...) exited because self.transfer_data_task
  397. # completed before receiving a new message, raise a suitable
  398. # exception (or return None if legacy_recv is enabled).
  399. if not pop_message_waiter.done():
  400. if self.legacy_recv:
  401. return None # type: ignore
  402. else:
  403. # Wait until the connection is closed to raise
  404. # ConnectionClosed with the correct code and reason.
  405. await self.ensure_open()
  406. # Pop a message from the queue.
  407. message = self.messages.popleft()
  408. # Notify transfer_data().
  409. if self._put_message_waiter is not None:
  410. self._put_message_waiter.set_result(None)
  411. self._put_message_waiter = None
  412. return message
  413. async def send(
  414. self, message: Union[Data, Iterable[Data], AsyncIterable[Data]]
  415. ) -> None:
  416. """
  417. Send a message.
  418. A string (:class:`str`) is sent as a `Text frame`_. A bytestring or
  419. bytes-like object (:class:`bytes`, :class:`bytearray`, or
  420. :class:`memoryview`) is sent as a `Binary frame`_.
  421. .. _Text frame: https://tools.ietf.org/html/rfc6455#section-5.6
  422. .. _Binary frame: https://tools.ietf.org/html/rfc6455#section-5.6
  423. :meth:`send` also accepts an iterable or an asynchronous iterable of
  424. strings, bytestrings, or bytes-like objects. In that case the message
  425. is fragmented. Each item is treated as a message fragment and sent in
  426. its own frame. All items must be of the same type, or else
  427. :meth:`send` will raise a :exc:`TypeError` and the connection will be
  428. closed.
  429. Canceling :meth:`send` is discouraged. Instead, you should close the
  430. connection with :meth:`close`. Indeed, there only two situations where
  431. :meth:`send` yields control to the event loop:
  432. 1. The write buffer is full. If you don't want to wait until enough
  433. data is sent, your only alternative is to close the connection.
  434. :meth:`close` will likely time out then abort the TCP connection.
  435. 2. ``message`` is an asynchronous iterator. Stopping in the middle of
  436. a fragmented message will cause a protocol error. Closing the
  437. connection has the same effect.
  438. :raises TypeError: for unsupported inputs
  439. """
  440. await self.ensure_open()
  441. # While sending a fragmented message, prevent sending other messages
  442. # until all fragments are sent.
  443. while self._fragmented_message_waiter is not None:
  444. await asyncio.shield(self._fragmented_message_waiter)
  445. # Unfragmented message -- this case must be handled first because
  446. # strings and bytes-like objects are iterable.
  447. if isinstance(message, (str, bytes, bytearray, memoryview)):
  448. opcode, data = prepare_data(message)
  449. await self.write_frame(True, opcode, data)
  450. # Fragmented message -- regular iterator.
  451. elif isinstance(message, Iterable):
  452. # Work around https://github.com/python/mypy/issues/6227
  453. message = cast(Iterable[Data], message)
  454. iter_message = iter(message)
  455. try:
  456. message_chunk = next(iter_message)
  457. except StopIteration:
  458. return
  459. opcode, data = prepare_data(message_chunk)
  460. self._fragmented_message_waiter = asyncio.Future()
  461. try:
  462. # First fragment.
  463. await self.write_frame(False, opcode, data)
  464. # Other fragments.
  465. for message_chunk in iter_message:
  466. confirm_opcode, data = prepare_data(message_chunk)
  467. if confirm_opcode != opcode:
  468. raise TypeError("data contains inconsistent types")
  469. await self.write_frame(False, OP_CONT, data)
  470. # Final fragment.
  471. await self.write_frame(True, OP_CONT, b"")
  472. except Exception:
  473. # We're half-way through a fragmented message and we can't
  474. # complete it. This makes the connection unusable.
  475. self.fail_connection(1011)
  476. raise
  477. finally:
  478. self._fragmented_message_waiter.set_result(None)
  479. self._fragmented_message_waiter = None
  480. # Fragmented message -- asynchronous iterator
  481. elif isinstance(message, AsyncIterable):
  482. # aiter_message = aiter(message) without aiter
  483. # https://github.com/python/mypy/issues/5738
  484. aiter_message = type(message).__aiter__(message) # type: ignore
  485. try:
  486. # message_chunk = anext(aiter_message) without anext
  487. # https://github.com/python/mypy/issues/5738
  488. message_chunk = await type(aiter_message).__anext__( # type: ignore
  489. aiter_message
  490. )
  491. except StopAsyncIteration:
  492. return
  493. opcode, data = prepare_data(message_chunk)
  494. self._fragmented_message_waiter = asyncio.Future()
  495. try:
  496. # First fragment.
  497. await self.write_frame(False, opcode, data)
  498. # Other fragments.
  499. # https://github.com/python/mypy/issues/5738
  500. async for message_chunk in aiter_message: # type: ignore
  501. confirm_opcode, data = prepare_data(message_chunk)
  502. if confirm_opcode != opcode:
  503. raise TypeError("data contains inconsistent types")
  504. await self.write_frame(False, OP_CONT, data)
  505. # Final fragment.
  506. await self.write_frame(True, OP_CONT, b"")
  507. except Exception:
  508. # We're half-way through a fragmented message and we can't
  509. # complete it. This makes the connection unusable.
  510. self.fail_connection(1011)
  511. raise
  512. finally:
  513. self._fragmented_message_waiter.set_result(None)
  514. self._fragmented_message_waiter = None
  515. else:
  516. raise TypeError("data must be bytes, str, or iterable")
  517. async def close(self, code: int = 1000, reason: str = "") -> None:
  518. """
  519. Perform the closing handshake.
  520. :meth:`close` waits for the other end to complete the handshake and
  521. for the TCP connection to terminate. As a consequence, there's no need
  522. to await :meth:`wait_closed`; :meth:`close` already does it.
  523. :meth:`close` is idempotent: it doesn't do anything once the
  524. connection is closed.
  525. Wrapping :func:`close` in :func:`~asyncio.create_task` is safe, given
  526. that errors during connection termination aren't particularly useful.
  527. Canceling :meth:`close` is discouraged. If it takes too long, you can
  528. set a shorter ``close_timeout``. If you don't want to wait, let the
  529. Python process exit, then the OS will close the TCP connection.
  530. :param code: WebSocket close code
  531. :param reason: WebSocket close reason
  532. """
  533. try:
  534. await asyncio.wait_for(
  535. self.write_close_frame(serialize_close(code, reason)),
  536. self.close_timeout,
  537. loop=self.loop if sys.version_info[:2] < (3, 8) else None,
  538. )
  539. except asyncio.TimeoutError:
  540. # If the close frame cannot be sent because the send buffers
  541. # are full, the closing handshake won't complete anyway.
  542. # Fail the connection to shut down faster.
  543. self.fail_connection()
  544. # If no close frame is received within the timeout, wait_for() cancels
  545. # the data transfer task and raises TimeoutError.
  546. # If close() is called multiple times concurrently and one of these
  547. # calls hits the timeout, the data transfer task will be cancelled.
  548. # Other calls will receive a CancelledError here.
  549. try:
  550. # If close() is canceled during the wait, self.transfer_data_task
  551. # is canceled before the timeout elapses.
  552. await asyncio.wait_for(
  553. self.transfer_data_task,
  554. self.close_timeout,
  555. loop=self.loop if sys.version_info[:2] < (3, 8) else None,
  556. )
  557. except (asyncio.TimeoutError, asyncio.CancelledError):
  558. pass
  559. # Wait for the close connection task to close the TCP connection.
  560. await asyncio.shield(self.close_connection_task)
  561. async def ping(self, data: Optional[Data] = None) -> Awaitable[None]:
  562. """
  563. Send a ping.
  564. Return a :class:`~asyncio.Future` which will be completed when the
  565. corresponding pong is received and which you may ignore if you don't
  566. want to wait.
  567. A ping may serve as a keepalive or as a check that the remote endpoint
  568. received all messages up to this point::
  569. pong_waiter = await ws.ping()
  570. await pong_waiter # only if you want to wait for the pong
  571. By default, the ping contains four random bytes. This payload may be
  572. overridden with the optional ``data`` argument which must be a string
  573. (which will be encoded to UTF-8) or a bytes-like object.
  574. Canceling :meth:`ping` is discouraged. If :meth:`ping` doesn't return
  575. immediately, it means the write buffer is full. If you don't want to
  576. wait, you should close the connection.
  577. Canceling the :class:`~asyncio.Future` returned by :meth:`ping` has no
  578. effect.
  579. """
  580. await self.ensure_open()
  581. if data is not None:
  582. data = encode_data(data)
  583. # Protect against duplicates if a payload is explicitly set.
  584. if data in self.pings:
  585. raise ValueError("already waiting for a pong with the same data")
  586. # Generate a unique random payload otherwise.
  587. while data is None or data in self.pings:
  588. data = struct.pack("!I", random.getrandbits(32))
  589. self.pings[data] = self.loop.create_future()
  590. await self.write_frame(True, OP_PING, data)
  591. return asyncio.shield(self.pings[data])
  592. async def pong(self, data: Data = b"") -> None:
  593. """
  594. Send a pong.
  595. An unsolicited pong may serve as a unidirectional heartbeat.
  596. The payload may be set with the optional ``data`` argument which must
  597. be a string (which will be encoded to UTF-8) or a bytes-like object.
  598. Canceling :meth:`pong` is discouraged for the same reason as
  599. :meth:`ping`.
  600. """
  601. await self.ensure_open()
  602. data = encode_data(data)
  603. await self.write_frame(True, OP_PONG, data)
  604. # Private methods - no guarantees.
  605. def connection_closed_exc(self) -> ConnectionClosed:
  606. exception: ConnectionClosed
  607. if self.close_code == 1000 or self.close_code == 1001:
  608. exception = ConnectionClosedOK(self.close_code, self.close_reason)
  609. else:
  610. exception = ConnectionClosedError(self.close_code, self.close_reason)
  611. # Chain to the exception that terminated data transfer, if any.
  612. exception.__cause__ = self.transfer_data_exc
  613. return exception
  614. async def ensure_open(self) -> None:
  615. """
  616. Check that the WebSocket connection is open.
  617. Raise :exc:`~websockets.exceptions.ConnectionClosed` if it isn't.
  618. """
  619. # Handle cases from most common to least common for performance.
  620. if self.state is State.OPEN:
  621. # If self.transfer_data_task exited without a closing handshake,
  622. # self.close_connection_task may be closing the connection, going
  623. # straight from OPEN to CLOSED.
  624. if self.transfer_data_task.done():
  625. await asyncio.shield(self.close_connection_task)
  626. raise self.connection_closed_exc()
  627. else:
  628. return
  629. if self.state is State.CLOSED:
  630. raise self.connection_closed_exc()
  631. if self.state is State.CLOSING:
  632. # If we started the closing handshake, wait for its completion to
  633. # get the proper close code and reason. self.close_connection_task
  634. # will complete within 4 or 5 * close_timeout after close(). The
  635. # CLOSING state also occurs when failing the connection. In that
  636. # case self.close_connection_task will complete even faster.
  637. await asyncio.shield(self.close_connection_task)
  638. raise self.connection_closed_exc()
  639. # Control may only reach this point in buggy third-party subclasses.
  640. assert self.state is State.CONNECTING
  641. raise InvalidState("WebSocket connection isn't established yet")
  642. async def transfer_data(self) -> None:
  643. """
  644. Read incoming messages and put them in a queue.
  645. This coroutine runs in a task until the closing handshake is started.
  646. """
  647. try:
  648. while True:
  649. message = await self.read_message()
  650. # Exit the loop when receiving a close frame.
  651. if message is None:
  652. break
  653. # Wait until there's room in the queue (if necessary).
  654. if self.max_queue is not None:
  655. while len(self.messages) >= self.max_queue:
  656. self._put_message_waiter = self.loop.create_future()
  657. try:
  658. await asyncio.shield(self._put_message_waiter)
  659. finally:
  660. self._put_message_waiter = None
  661. # Put the message in the queue.
  662. self.messages.append(message)
  663. # Notify recv().
  664. if self._pop_message_waiter is not None:
  665. self._pop_message_waiter.set_result(None)
  666. self._pop_message_waiter = None
  667. except asyncio.CancelledError as exc:
  668. self.transfer_data_exc = exc
  669. # If fail_connection() cancels this task, avoid logging the error
  670. # twice and failing the connection again.
  671. raise
  672. except ProtocolError as exc:
  673. self.transfer_data_exc = exc
  674. self.fail_connection(1002)
  675. except (ConnectionError, EOFError) as exc:
  676. # Reading data with self.reader.readexactly may raise:
  677. # - most subclasses of ConnectionError if the TCP connection
  678. # breaks, is reset, or is aborted;
  679. # - IncompleteReadError, a subclass of EOFError, if fewer
  680. # bytes are available than requested.
  681. self.transfer_data_exc = exc
  682. self.fail_connection(1006)
  683. except UnicodeDecodeError as exc:
  684. self.transfer_data_exc = exc
  685. self.fail_connection(1007)
  686. except PayloadTooBig as exc:
  687. self.transfer_data_exc = exc
  688. self.fail_connection(1009)
  689. except Exception as exc:
  690. # This shouldn't happen often because exceptions expected under
  691. # regular circumstances are handled above. If it does, consider
  692. # catching and handling more exceptions.
  693. logger.error("Error in data transfer", exc_info=True)
  694. self.transfer_data_exc = exc
  695. self.fail_connection(1011)
  696. async def read_message(self) -> Optional[Data]:
  697. """
  698. Read a single message from the connection.
  699. Re-assemble data frames if the message is fragmented.
  700. Return ``None`` when the closing handshake is started.
  701. """
  702. frame = await self.read_data_frame(max_size=self.max_size)
  703. # A close frame was received.
  704. if frame is None:
  705. return None
  706. if frame.opcode == OP_TEXT:
  707. text = True
  708. elif frame.opcode == OP_BINARY:
  709. text = False
  710. else: # frame.opcode == OP_CONT
  711. raise ProtocolError("unexpected opcode")
  712. # Shortcut for the common case - no fragmentation
  713. if frame.fin:
  714. return frame.data.decode("utf-8") if text else frame.data
  715. # 5.4. Fragmentation
  716. chunks: List[Data] = []
  717. max_size = self.max_size
  718. if text:
  719. decoder_factory = codecs.getincrementaldecoder("utf-8")
  720. decoder = decoder_factory(errors="strict")
  721. if max_size is None:
  722. def append(frame: Frame) -> None:
  723. nonlocal chunks
  724. chunks.append(decoder.decode(frame.data, frame.fin))
  725. else:
  726. def append(frame: Frame) -> None:
  727. nonlocal chunks, max_size
  728. chunks.append(decoder.decode(frame.data, frame.fin))
  729. assert isinstance(max_size, int)
  730. max_size -= len(frame.data)
  731. else:
  732. if max_size is None:
  733. def append(frame: Frame) -> None:
  734. nonlocal chunks
  735. chunks.append(frame.data)
  736. else:
  737. def append(frame: Frame) -> None:
  738. nonlocal chunks, max_size
  739. chunks.append(frame.data)
  740. assert isinstance(max_size, int)
  741. max_size -= len(frame.data)
  742. append(frame)
  743. while not frame.fin:
  744. frame = await self.read_data_frame(max_size=max_size)
  745. if frame is None:
  746. raise ProtocolError("incomplete fragmented message")
  747. if frame.opcode != OP_CONT:
  748. raise ProtocolError("unexpected opcode")
  749. append(frame)
  750. # mypy cannot figure out that chunks have the proper type.
  751. return ("" if text else b"").join(chunks) # type: ignore
  752. async def read_data_frame(self, max_size: Optional[int]) -> Optional[Frame]:
  753. """
  754. Read a single data frame from the connection.
  755. Process control frames received before the next data frame.
  756. Return ``None`` if a close frame is encountered before any data frame.
  757. """
  758. # 6.2. Receiving Data
  759. while True:
  760. frame = await self.read_frame(max_size)
  761. # 5.5. Control Frames
  762. if frame.opcode == OP_CLOSE:
  763. # 7.1.5. The WebSocket Connection Close Code
  764. # 7.1.6. The WebSocket Connection Close Reason
  765. self.close_code, self.close_reason = parse_close(frame.data)
  766. try:
  767. # Echo the original data instead of re-serializing it with
  768. # serialize_close() because that fails when the close frame
  769. # is empty and parse_close() synthetizes a 1005 close code.
  770. await self.write_close_frame(frame.data)
  771. except ConnectionClosed:
  772. # It doesn't really matter if the connection was closed
  773. # before we could send back a close frame.
  774. pass
  775. return None
  776. elif frame.opcode == OP_PING:
  777. # Answer pings.
  778. ping_hex = frame.data.hex() or "[empty]"
  779. logger.debug(
  780. "%s - received ping, sending pong: %s", self.side, ping_hex
  781. )
  782. await self.pong(frame.data)
  783. elif frame.opcode == OP_PONG:
  784. # Acknowledge pings on solicited pongs.
  785. if frame.data in self.pings:
  786. logger.debug(
  787. "%s - received solicited pong: %s",
  788. self.side,
  789. frame.data.hex() or "[empty]",
  790. )
  791. # Acknowledge all pings up to the one matching this pong.
  792. ping_id = None
  793. ping_ids = []
  794. for ping_id, ping in self.pings.items():
  795. ping_ids.append(ping_id)
  796. if not ping.done():
  797. ping.set_result(None)
  798. if ping_id == frame.data:
  799. break
  800. else: # pragma: no cover
  801. assert False, "ping_id is in self.pings"
  802. # Remove acknowledged pings from self.pings.
  803. for ping_id in ping_ids:
  804. del self.pings[ping_id]
  805. ping_ids = ping_ids[:-1]
  806. if ping_ids:
  807. pings_hex = ", ".join(
  808. ping_id.hex() or "[empty]" for ping_id in ping_ids
  809. )
  810. plural = "s" if len(ping_ids) > 1 else ""
  811. logger.debug(
  812. "%s - acknowledged previous ping%s: %s",
  813. self.side,
  814. plural,
  815. pings_hex,
  816. )
  817. else:
  818. logger.debug(
  819. "%s - received unsolicited pong: %s",
  820. self.side,
  821. frame.data.hex() or "[empty]",
  822. )
  823. # 5.6. Data Frames
  824. else:
  825. return frame
  826. async def read_frame(self, max_size: Optional[int]) -> Frame:
  827. """
  828. Read a single frame from the connection.
  829. """
  830. frame = await Frame.read(
  831. self.reader.readexactly,
  832. mask=not self.is_client,
  833. max_size=max_size,
  834. extensions=self.extensions,
  835. )
  836. logger.debug("%s < %r", self.side, frame)
  837. return frame
  838. async def write_frame(
  839. self, fin: bool, opcode: int, data: bytes, *, _expected_state: int = State.OPEN
  840. ) -> None:
  841. # Defensive assertion for protocol compliance.
  842. if self.state is not _expected_state: # pragma: no cover
  843. raise InvalidState(
  844. f"Cannot write to a WebSocket in the {self.state.name} state"
  845. )
  846. frame = Frame(fin, opcode, data)
  847. logger.debug("%s > %r", self.side, frame)
  848. frame.write(
  849. self.transport.write, mask=self.is_client, extensions=self.extensions
  850. )
  851. try:
  852. # drain() cannot be called concurrently by multiple coroutines:
  853. # http://bugs.python.org/issue29930. Remove this lock when no
  854. # version of Python where this bugs exists is supported anymore.
  855. async with self._drain_lock:
  856. # Handle flow control automatically.
  857. await self._drain()
  858. except ConnectionError:
  859. # Terminate the connection if the socket died.
  860. self.fail_connection()
  861. # Wait until the connection is closed to raise ConnectionClosed
  862. # with the correct code and reason.
  863. await self.ensure_open()
  864. async def write_close_frame(self, data: bytes = b"") -> None:
  865. """
  866. Write a close frame if and only if the connection state is OPEN.
  867. This dedicated coroutine must be used for writing close frames to
  868. ensure that at most one close frame is sent on a given connection.
  869. """
  870. # Test and set the connection state before sending the close frame to
  871. # avoid sending two frames in case of concurrent calls.
  872. if self.state is State.OPEN:
  873. # 7.1.3. The WebSocket Closing Handshake is Started
  874. self.state = State.CLOSING
  875. logger.debug("%s - state = CLOSING", self.side)
  876. # 7.1.2. Start the WebSocket Closing Handshake
  877. await self.write_frame(True, OP_CLOSE, data, _expected_state=State.CLOSING)
  878. async def keepalive_ping(self) -> None:
  879. """
  880. Send a Ping frame and wait for a Pong frame at regular intervals.
  881. This coroutine exits when the connection terminates and one of the
  882. following happens:
  883. - :meth:`ping` raises :exc:`ConnectionClosed`, or
  884. - :meth:`close_connection` cancels :attr:`keepalive_ping_task`.
  885. """
  886. if self.ping_interval is None:
  887. return
  888. try:
  889. while True:
  890. await asyncio.sleep(
  891. self.ping_interval,
  892. loop=self.loop if sys.version_info[:2] < (3, 8) else None,
  893. )
  894. # ping() raises CancelledError if the connection is closed,
  895. # when close_connection() cancels self.keepalive_ping_task.
  896. # ping() raises ConnectionClosed if the connection is lost,
  897. # when connection_lost() calls abort_pings().
  898. ping_waiter = await self.ping()
  899. if self.ping_timeout is not None:
  900. try:
  901. await asyncio.wait_for(
  902. ping_waiter,
  903. self.ping_timeout,
  904. loop=self.loop if sys.version_info[:2] < (3, 8) else None,
  905. )
  906. except asyncio.TimeoutError:
  907. logger.debug("%s ! timed out waiting for pong", self.side)
  908. self.fail_connection(1011)
  909. break
  910. except asyncio.CancelledError:
  911. raise
  912. except ConnectionClosed:
  913. pass
  914. except Exception:
  915. logger.warning("Unexpected exception in keepalive ping task", exc_info=True)
  916. async def close_connection(self) -> None:
  917. """
  918. 7.1.1. Close the WebSocket Connection
  919. When the opening handshake succeeds, :meth:`connection_open` starts
  920. this coroutine in a task. It waits for the data transfer phase to
  921. complete then it closes the TCP connection cleanly.
  922. When the opening handshake fails, :meth:`fail_connection` does the
  923. same. There's no data transfer phase in that case.
  924. """
  925. try:
  926. # Wait for the data transfer phase to complete.
  927. if hasattr(self, "transfer_data_task"):
  928. try:
  929. await self.transfer_data_task
  930. except asyncio.CancelledError:
  931. pass
  932. # Cancel the keepalive ping task.
  933. if hasattr(self, "keepalive_ping_task"):
  934. self.keepalive_ping_task.cancel()
  935. # A client should wait for a TCP close from the server.
  936. if self.is_client and hasattr(self, "transfer_data_task"):
  937. if await self.wait_for_connection_lost():
  938. return
  939. logger.debug("%s ! timed out waiting for TCP close", self.side)
  940. # Half-close the TCP connection if possible (when there's no TLS).
  941. if self.transport.can_write_eof():
  942. logger.debug("%s x half-closing TCP connection", self.side)
  943. self.transport.write_eof()
  944. if await self.wait_for_connection_lost():
  945. return
  946. logger.debug("%s ! timed out waiting for TCP close", self.side)
  947. finally:
  948. # The try/finally ensures that the transport never remains open,
  949. # even if this coroutine is canceled (for example).
  950. # If connection_lost() was called, the TCP connection is closed.
  951. # However, if TLS is enabled, the transport still needs closing.
  952. # Else asyncio complains: ResourceWarning: unclosed transport.
  953. if self.connection_lost_waiter.done() and self.transport.is_closing():
  954. return
  955. # Close the TCP connection. Buffers are flushed asynchronously.
  956. logger.debug("%s x closing TCP connection", self.side)
  957. self.transport.close()
  958. if await self.wait_for_connection_lost():
  959. return
  960. logger.debug("%s ! timed out waiting for TCP close", self.side)
  961. # Abort the TCP connection. Buffers are discarded.
  962. logger.debug("%s x aborting TCP connection", self.side)
  963. self.transport.abort()
  964. # connection_lost() is called quickly after aborting.
  965. await self.wait_for_connection_lost()
  966. async def wait_for_connection_lost(self) -> bool:
  967. """
  968. Wait until the TCP connection is closed or ``self.close_timeout`` elapses.
  969. Return ``True`` if the connection is closed and ``False`` otherwise.
  970. """
  971. if not self.connection_lost_waiter.done():
  972. try:
  973. await asyncio.wait_for(
  974. asyncio.shield(self.connection_lost_waiter),
  975. self.close_timeout,
  976. loop=self.loop if sys.version_info[:2] < (3, 8) else None,
  977. )
  978. except asyncio.TimeoutError:
  979. pass
  980. # Re-check self.connection_lost_waiter.done() synchronously because
  981. # connection_lost() could run between the moment the timeout occurs
  982. # and the moment this coroutine resumes running.
  983. return self.connection_lost_waiter.done()
  984. def fail_connection(self, code: int = 1006, reason: str = "") -> None:
  985. """
  986. 7.1.7. Fail the WebSocket Connection
  987. This requires:
  988. 1. Stopping all processing of incoming data, which means cancelling
  989. :attr:`transfer_data_task`. The close code will be 1006 unless a
  990. close frame was received earlier.
  991. 2. Sending a close frame with an appropriate code if the opening
  992. handshake succeeded and the other side is likely to process it.
  993. 3. Closing the connection. :meth:`close_connection` takes care of
  994. this once :attr:`transfer_data_task` exits after being canceled.
  995. (The specification describes these steps in the opposite order.)
  996. """
  997. logger.debug(
  998. "%s ! failing %s WebSocket connection with code %d",
  999. self.side,
  1000. self.state.name,
  1001. code,
  1002. )
  1003. # Cancel transfer_data_task if the opening handshake succeeded.
  1004. # cancel() is idempotent and ignored if the task is done already.
  1005. if hasattr(self, "transfer_data_task"):
  1006. self.transfer_data_task.cancel()
  1007. # Send a close frame when the state is OPEN (a close frame was already
  1008. # sent if it's CLOSING), except when failing the connection because of
  1009. # an error reading from or writing to the network.
  1010. # Don't send a close frame if the connection is broken.
  1011. if code != 1006 and self.state is State.OPEN:
  1012. frame_data = serialize_close(code, reason)
  1013. # Write the close frame without draining the write buffer.
  1014. # Keeping fail_connection() synchronous guarantees it can't
  1015. # get stuck and simplifies the implementation of the callers.
  1016. # Not drainig the write buffer is acceptable in this context.
  1017. # This duplicates a few lines of code from write_close_frame()
  1018. # and write_frame().
  1019. self.state = State.CLOSING
  1020. logger.debug("%s - state = CLOSING", self.side)
  1021. frame = Frame(True, OP_CLOSE, frame_data)
  1022. logger.debug("%s > %r", self.side, frame)
  1023. fra