def ws_control_frame(self, opcode, data): if opcode in (PING, CLOSE): rcode = PONG if opcode == PING else CLOSE if opcode == CLOSE: self.ws_close_received = True self.stop_reading = True if data: try: close_code = unpack_from(b'!H', data)[0] except struct_error: data = pack(b'!H', PROTOCOL_ERROR) + b'close frame data must be atleast two bytes' else: try: utf8_decode(data[2:]) except ValueError: data = pack(b'!H', PROTOCOL_ERROR) + b'close frame data must be valid UTF-8' else: if close_code < 1000 or close_code in RESERVED_CLOSE_CODES or (1011 < close_code < 3000): data = pack(b'!H', PROTOCOL_ERROR) + b'close code reserved' else: close_code = NORMAL_CLOSE data = pack(b'!H', close_code) f = ReadOnlyFileBuffer(create_frame(1, rcode, data)) f.is_close_frame = opcode == CLOSE with self.cf_lock: self.control_frames.append(f) elif opcode == PONG: try: self.websocket_handler.handle_websocket_pong(self.websocket_connection_id, data) except Exception: self.log.exception('Error in PONG handler:') self.set_ws_state()
def websocket_close(self, code=NORMAL_CLOSE, reason=b''): if isinstance(reason, type('')): reason = reason.encode('utf-8') self.stop_reading = True reason = reason[:123] if code is None and not reason: f = ReadOnlyFileBuffer(create_frame(1, CLOSE, b'')) else: f = ReadOnlyFileBuffer(create_frame(1, CLOSE, pack(b'!H', code) + reason)) f.is_close_frame = True with self.cf_lock: self.control_frames.append(f) self.set_ws_state()