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 ) : 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 ) : num , option_length , pos = Serializer . read_option_value_len_from_byte ( next_byte , pos , values ) current_option += num 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 : 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 : 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
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