| 16 | |
| 17 | |
| 18 | class Frame(NamedTuple): |
| 19 | fin: bool |
| 20 | opcode: frames.Opcode |
| 21 | data: BytesLike |
| 22 | rsv1: bool = False |
| 23 | rsv2: bool = False |
| 24 | rsv3: bool = False |
| 25 | |
| 26 | @property |
| 27 | def new_frame(self) -> frames.Frame: |
| 28 | return frames.Frame( |
| 29 | self.opcode, |
| 30 | self.data, |
| 31 | self.fin, |
| 32 | self.rsv1, |
| 33 | self.rsv2, |
| 34 | self.rsv3, |
| 35 | ) |
| 36 | |
| 37 | def __str__(self) -> str: |
| 38 | return str(self.new_frame) |
| 39 | |
| 40 | def check(self) -> None: |
| 41 | return self.new_frame.check() |
| 42 | |
| 43 | @classmethod |
| 44 | async def read( |
| 45 | cls, |
| 46 | reader: Callable[[int], Awaitable[bytes]], |
| 47 | *, |
| 48 | mask: bool, |
| 49 | max_size: int | None = None, |
| 50 | extensions: Sequence[extensions.Extension] | None = None, |
| 51 | ) -> Frame: |
| 52 | """ |
| 53 | Read a WebSocket frame. |
| 54 | |
| 55 | Args: |
| 56 | reader: Coroutine that reads exactly the requested number of |
| 57 | bytes, unless the end of file is reached. |
| 58 | mask: Whether the frame should be masked i.e. whether the read |
| 59 | happens on the server side. |
| 60 | max_size: Maximum payload size in bytes. |
| 61 | extensions: List of extensions, applied in reverse order. |
| 62 | |
| 63 | Raises: |
| 64 | PayloadTooBig: If the frame exceeds ``max_size``. |
| 65 | ProtocolError: If the frame contains incorrect values. |
| 66 | |
| 67 | """ |
| 68 | |
| 69 | # Read the header. |
| 70 | data = await reader(2) |
| 71 | head1, head2 = struct.unpack("!BB", data) |
| 72 | |
| 73 | # While not Pythonic, this is marginally faster than calling bool(). |
| 74 | fin = True if head1 & 0b10000000 else False |
| 75 | rsv1 = True if head1 & 0b01000000 else False |
no outgoing calls
searching dependent graphs…