Process an incoming frame.
(self, frame: Frame)
| 669 | raise AssertionError("discard() shouldn't step after EOF") |
| 670 | |
| 671 | def recv_frame(self, frame: Frame) -> None: |
| 672 | """ |
| 673 | Process an incoming frame. |
| 674 | |
| 675 | """ |
| 676 | if frame.opcode is OP_TEXT or frame.opcode is OP_BINARY: |
| 677 | if self.current_size is not None: |
| 678 | raise ProtocolError("expected a continuation frame") |
| 679 | if not frame.fin: |
| 680 | self.current_size = len(frame.data) |
| 681 | |
| 682 | elif frame.opcode is OP_CONT: |
| 683 | if self.current_size is None: |
| 684 | raise ProtocolError("unexpected continuation frame") |
| 685 | if frame.fin: |
| 686 | self.current_size = None |
| 687 | else: |
| 688 | self.current_size += len(frame.data) |
| 689 | |
| 690 | elif frame.opcode is OP_PING: |
| 691 | # 5.5.2. Ping: "Upon receipt of a Ping frame, an endpoint MUST |
| 692 | # send a Pong frame in response" |
| 693 | pong_frame = Frame(OP_PONG, frame.data) |
| 694 | self.send_frame(pong_frame) |
| 695 | |
| 696 | elif frame.opcode is OP_PONG: |
| 697 | # 5.5.3 Pong: "A response to an unsolicited Pong frame is not |
| 698 | # expected." |
| 699 | pass |
| 700 | |
| 701 | elif frame.opcode is OP_CLOSE: |
| 702 | # 7.1.5. The WebSocket Connection Close Code |
| 703 | # 7.1.6. The WebSocket Connection Close Reason |
| 704 | self.close_rcvd = Close.parse(frame.data) |
| 705 | if self.state is CLOSING: |
| 706 | assert self.close_sent is not None |
| 707 | self.close_rcvd_then_sent = False |
| 708 | |
| 709 | if self.current_size is not None: |
| 710 | raise ProtocolError("incomplete fragmented message") |
| 711 | |
| 712 | # 5.5.1 Close: "If an endpoint receives a Close frame and did |
| 713 | # not previously send a Close frame, the endpoint MUST send a |
| 714 | # Close frame in response. (When sending a Close frame in |
| 715 | # response, the endpoint typically echos the status code it |
| 716 | # received.)" |
| 717 | |
| 718 | if self.state is OPEN: |
| 719 | # Echo the original data instead of re-serializing it with |
| 720 | # Close.serialize() because that fails when the close frame |
| 721 | # is empty and Close.parse() synthesizes a 1005 close code. |
| 722 | # The rest is identical to send_close(). |
| 723 | self.send_frame(Frame(OP_CLOSE, frame.data)) |
| 724 | self.close_sent = self.close_rcvd |
| 725 | self.close_rcvd_then_sent = True |
| 726 | self.state = CLOSING |
| 727 | |
| 728 | # 7.1.2. Start the WebSocket Closing Handshake: "Once an |
no test coverage detected