def _on_packet_recv(self, conn_id, packet): self._touch_keepalive(conn_id) try: if len(packet) < MIN_FRAME_SIZE: raise SnakeMQBrokenMessage("too small") frame_type = ord(packet[:FRAME_TYPE_SIZE]) payload = memview(packet)[FRAME_TYPE_SIZE:] # TODO allow parse_* calls only after protocol version negotiation if frame_type == FRAME_TYPE_PROTOCOL_VERSION: self.parse_protocol_version(payload, conn_id) elif frame_type == FRAME_TYPE_INCOMPATIBLE_PROTOCOL: self.parse_incompatible_protocol(conn_id) elif frame_type == FRAME_TYPE_IDENTIFICATION: self.parse_identification(payload, conn_id) elif frame_type == FRAME_TYPE_MESSAGE: self.parse_message(payload, conn_id) elif frame_type == FRAME_TYPE_PING: self.send_pong(conn_id) except SnakeMQException as exc: self.log.error("conn=%s ident=%s %r" % (conn_id, self._ident_by_conn.get(conn_id), exc)) self.on_error(conn_id, exc) self.packeter.link.close(conn_id)
def parse_protocol_version(self, payload, conn_id): if len(payload) != FRAME_FORMAT_PROTOCOL_VERSION_SIZE: raise SnakeMQBrokenMessage("protocol version") protocol = struct.unpack(FRAME_FORMAT_PROTOCOL_VERSION, memstr(payload[:FRAME_FORMAT_PROTOCOL_VERSION_SIZE]))[0] if protocol != snakemq.version.PROTOCOL_VERSION: self.send_incompatible_protocol(conn_id) raise SnakeMQIncompatibleProtocol( "remote side protocol version is %i" % protocol) self.log.debug("conn=%s remote version %X" % (conn_id, protocol))
def parse_message(self, payload, conn_id): if len(payload) < FRAME_FORMAT_MESSAGE_SIZE: raise SnakeMQBrokenMessage("message") try: ident = self._ident_by_conn[conn_id] except KeyError: raise SnakeMQNoIdent(conn_id) muuid, ttl, flags = struct.unpack(FRAME_FORMAT_MESSAGE, memstr(payload[:FRAME_FORMAT_MESSAGE_SIZE])) if ttl == INFINITE_TTL: ttl = None message = Message(data=memstr(payload[FRAME_FORMAT_MESSAGE_SIZE:]), uuid=muuid, ttl=ttl, flags=flags) self.on_message_recv(conn_id, ident, message)