def deserialize(datagram, source): """ De-serialize a stream of byte to a message. :param datagram: the incoming udp message :param source: the source address and port (ip, port) :return: the message :rtype: Message """ try: fmt = "!BBH" pos = struct.calcsize(fmt) s = struct.Struct(fmt) values = s.unpack_from(datagram) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if Serializer.is_response(code): message = Response() message.code = code elif Serializer.is_request(code): message = Request() message.code = code else: message = Message() message.source = source message.destination = None message.version = version message.type = message_type message.mid = mid if token_length > 0: fmt = "%ss" % token_length s = struct.Struct(fmt) token_value = s.unpack_from(datagram[pos:])[0] message.token = token_value.decode("utf-8") else: message.token = None pos += token_length current_option = 0 values = datagram[pos:] length_packet = len(values) pos = 0 while pos < length_packet: next_byte = struct.unpack("B", values[pos].to_bytes(1, "big"))[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint num, option_length, pos = Serializer.read_option_value_len_from_byte(next_byte, pos, values) current_option += num # read option try: option_item = defines.OptionRegistry.LIST[current_option] except KeyError: (opt_critical, _, _) = defines.OptionRegistry.get_option_flags(current_option) if opt_critical: raise AttributeError("Critical option %s unknown" % current_option) else: # If the non-critical option is unknown # (vendor-specific, proprietary) - just skip it #log.err("unrecognized option %d" % current_option) pass else: if option_length == 0: value = None elif option_item.value_type == defines.INTEGER: tmp = values[pos: pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b.to_bytes(1, "big"))[0] elif option_item.value_type == defines.OPAQUE: tmp = values[pos: pos + option_length] value = tmp else: value = values[pos: pos + option_length] option = Option() option.number = current_option option.value = Serializer.convert_to_raw(current_option, value, option_length) message.add_option(option) if option.number == defines.OptionRegistry.CONTENT_TYPE.number: message.payload_type = option.value finally: pos += option_length else: if length_packet <= pos: # log.err("Payload Marker with no payload") raise AttributeError("Packet length %s, pos %s" % (length_packet, pos)) message.payload = "" payload = values[pos:] try: if message.payload_type == defines.Content_types["application/octet-stream"]: message.payload = payload else: message.payload = payload.decode("utf-8") except AttributeError: message.payload = payload.decode("utf-8") pos += len(payload) return message except AttributeError: return defines.Codes.BAD_REQUEST.number except struct.error: return defines.Codes.BAD_REQUEST.number
def deserialize(datagram, source): """ De-serialize a stream of byte to a message. :type datagram: String :param datagram: :param source: """ try: fmt = "!BBH" pos = 4 length = len(datagram) while pos < length: fmt += "c" pos += 1 s = struct.Struct(fmt) values = s.unpack_from(datagram) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if Serializer.is_response(code): message = Response() message.code = code elif Serializer.is_request(code): message = Request() message.code = code else: message = Message() message.source = source message.destination = None message.version = version message.type = message_type message.mid = mid pos = 3 if token_length > 0: message.token = "".join(values[pos: pos + token_length]) else: message.token = None pos += token_length current_option = 0 length_packet = len(values) while pos < length_packet: next_byte = struct.unpack("B", values[pos])[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint delta = (next_byte & 0xF0) >> 4 # the second 4 bits represent the option length # length = self._reader.read(4).uint length = (next_byte & 0x0F) num, pos = Serializer.read_option_value_from_nibble(delta, pos, values) option_length, pos = Serializer.read_option_value_from_nibble(length, pos, values) current_option += num # read option try: option_item = defines.OptionRegistry.LIST[current_option] except KeyError: # log.err("unrecognized option") raise AttributeError if option_length == 0: value = None elif option_item.value_type == defines.INTEGER: tmp = values[pos: pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b)[0] elif option_item.value_type == defines.OPAQUE: tmp = values[pos: pos + option_length] value = bytearray(tmp) else: tmp = values[pos: pos + option_length] value = "" for b in tmp: value += str(b) pos += option_length option = Option() option.number = current_option option.value = Serializer.convert_to_raw(current_option, value, option_length) message.add_option(option) else: if length_packet <= pos: # log.err("Payload Marker with no payload") raise AttributeError message.payload = "" payload = values[pos:] for b in payload: message.payload += str(b) pos += 1 return message except AttributeError: return defines.Codes.BAD_REQUEST.number except struct.error: return defines.Codes.BAD_REQUEST.number
def deserialize(datagram, source): """ De-serialize a stream of byte to a message. :param datagram: the incoming udp message :param source: the source address and port (ip, port) :return: the message :rtype: Message """ try: fmt = "!BBH" pos = 4 length = len(datagram) while pos < length: fmt += "c" pos += 1 s = struct.Struct(fmt) values = s.unpack_from(datagram) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if Serializer.is_response(code): message = Response() message.code = code elif Serializer.is_request(code): message = Request() message.code = code else: message = Message() message.source = source message.destination = None message.version = version message.type = message_type message.mid = mid pos = 3 if token_length > 0: message.token = "".join(values[pos:pos + token_length]) else: message.token = None pos += token_length current_option = 0 length_packet = len(values) while pos < length_packet: next_byte = struct.unpack("B", values[pos])[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint delta = (next_byte & 0xF0) >> 4 # the second 4 bits represent the option length # length = self._reader.read(4).uint length = (next_byte & 0x0F) num, pos = Serializer.read_option_value_from_nibble( delta, pos, values) option_length, pos = Serializer.read_option_value_from_nibble( length, pos, values) current_option += num # read option try: option_item = defines.OptionRegistry.LIST[ current_option] except KeyError: # log.err("unrecognized option") raise AttributeError if option_length == 0: value = None elif option_item.value_type == defines.INTEGER: tmp = values[pos:pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b)[0] elif option_item.value_type == defines.OPAQUE: tmp = values[pos:pos + option_length] value = bytearray(tmp) else: tmp = values[pos:pos + option_length] value = "" for b in tmp: value += str(b) pos += option_length option = Option() option.number = current_option option.value = Serializer.convert_to_raw( current_option, value, option_length) message.add_option(option) else: if length_packet <= pos: # log.err("Payload Marker with no payload") raise AttributeError message.payload = "" payload = values[pos:] for b in payload: message.payload += str(b) pos += 1 return message except AttributeError: return defines.Codes.BAD_REQUEST.number except struct.error: return defines.Codes.BAD_REQUEST.number
def deserialize(self, raw, host, port): """ De-serialize a stream of byte to a message. :param raw: received bytes :param host: source host :param port: source port :return: the message """ self._reader = BitStream(bytes=raw, length=(len(raw) * 8)) version = self._reader.read(defines.VERSION_BITS).uint message_type = self._reader.read(defines.TYPE_BITS).uint token_length = self._reader.read(defines.TOKEN_LENGTH_BITS).uint code = self._reader.read(defines.CODE_BITS).uint mid = self._reader.read(defines.MESSAGE_ID_BITS).uint if self.is_response(code): message = Response() message.code = code elif self.is_request(code): message = Request() message.code = code else: message = Message() message.source = (host, port) message.destination = None message.version = version message.type = message_type message._mid = mid if token_length > 0: message.token = self._reader.read(token_length * 8).bytes else: message.token = None current_option = 0 try: while self._reader.pos < self._reader.len: next_byte = self._reader.peek(8).uint if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta delta = self._reader.read(4).uint # the second 4 bits represent the option length length = self._reader.read(4).uint current_option += self.read_option_value_from_nibble(delta) option_length = self.read_option_value_from_nibble(length) # read option try: option_name, option_type, option_repeatable, default = defines.options[current_option] except KeyError: log.err("unrecognized option") return message, "BAD_OPTION" if option_length == 0: value = None elif option_type == defines.INTEGER: value = self._reader.read(option_length * 8).uint else: value = self._reader.read(option_length * 8).bytes option = Option() option.number = current_option option.value = self.convert_to_raw(current_option, value, option_length) message.add_option(option) else: self._reader.pos += 8 # skip payload marker if self._reader.len <= self._reader.pos: log.err("Payload Marker with no payload") return message, "BAD_REQUEST" to_end = self._reader.len - self._reader.pos message.payload = self._reader.read(to_end).bytes return message except ReadError, e: log.err("Error parsing message: " + str(e))
def deserialize(self, raw, host, port): """ De-serialize a stream of byte to a message. :param raw: received bytes :param host: source host :param port: source port :return: the message """ fmt = "!BBH" pos = 4 length = len(raw) while pos < length: fmt += "c" pos += 1 s = struct.Struct(fmt) self._reader = raw values = s.unpack_from(self._reader) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if self.is_response(code): message = Response() message.code = code elif self.is_request(code): message = Request() message.code = code else: message = Message() message.source = (host, port) message.destination = None message.version = version message.type = message_type message._mid = mid pos = 3 if token_length > 0: message.token = "".join(values[pos: pos + token_length]) else: message.token = None pos += token_length current_option = 0 length_packet = len(values) while pos < length_packet: next_byte = struct.unpack("B", values[pos])[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint delta = (next_byte & 0xF0) >> 4 # the second 4 bits represent the option length # length = self._reader.read(4).uint length = (next_byte & 0x0F) num, pos = self.read_option_value_from_nibble(delta, pos, values) option_length, pos = self.read_option_value_from_nibble(length, pos, values) current_option += num # read option try: option_name, option_type, option_repeatable, default = defines.options[current_option] except KeyError: # log.err("unrecognized option") return message, "BAD_OPTION" if option_length == 0: value = None elif option_type == defines.INTEGER: tmp = values[pos: pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b)[0] else: tmp = values[pos: pos + option_length] value = "" for b in tmp: value += str(b) pos += option_length option = Option() option.number = current_option option.value = self.convert_to_raw(current_option, value, option_length) message.add_option(option) else: if length_packet <= pos: # log.err("Payload Marker with no payload") return message, "BAD_REQUEST" message.payload = "" payload = values[pos:] for b in payload: message.payload += str(b) pos += 1 return message
def deserialize(datagram, source): """ De-serialize a stream of byte to a message. :param datagram: the incoming udp message :param source: the source address and port (ip, port) :return: the message :rtype: Message """ try: fmt = "!BBH" pos = struct.calcsize(fmt) s = struct.Struct(fmt) values = s.unpack_from(datagram) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if Serializer.is_response(code): message = Response() message.code = code elif Serializer.is_request(code): message = Request() message.code = code else: message = Message() message.source = source message.destination = None message.version = version message.type = message_type message.mid = mid if token_length > 0: fmt = "%ss" % token_length s = struct.Struct(fmt) token_value = s.unpack_from(datagram[pos:])[0] message.token = token_value else: message.token = None pos += token_length current_option = 0 values = datagram[pos:] length_packet = len(values) pos = 0 while pos < length_packet: next_byte = struct.unpack("B", values[pos])[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint num, option_length, pos = Serializer.read_option_value_len_from_byte(next_byte, pos, values) current_option += num # read option try: option_item = defines.OptionRegistry.LIST[current_option] except KeyError: (opt_critical, _, _) = defines.OptionRegistry.get_option_flags(current_option) if opt_critical: raise AttributeError("Critical option %s unknown" % current_option) else: # If the non-critical option is unknown # (vendor-specific, proprietary) - just skip it #log.err("unrecognized option %d" % current_option) pass else: if option_length == 0: value = None elif option_item.value_type == defines.INTEGER: tmp = values[pos: pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b)[0] elif option_item.value_type == defines.OPAQUE: tmp = values[pos: pos + option_length] value = bytearray(tmp) else: tmp = values[pos: pos + option_length] value = "" for b in tmp: value += str(b) option = Option() option.number = current_option option.value = Serializer.convert_to_raw(current_option, value, option_length) message.add_option(option) if option.number == defines.OptionRegistry.CONTENT_TYPE.number: message.payload_type = option.value finally: pos += option_length else: if length_packet <= pos: # log.err("Payload Marker with no payload") raise AttributeError("Packet length %s, pos %s" % (length_packet, pos)) message.payload = "" payload = values[pos:] for b in payload: message.payload += str(b) pos += 1 return message except AttributeError: return defines.Codes.BAD_REQUEST.number except struct.error: return defines.Codes.BAD_REQUEST.number