Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
    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))
Esempio n. 5
0
    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
Esempio n. 6
0
    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