It is still missing extension headers. Signed-off-by: Baptiste Jonglez <[email protected]> --- ryu/lib/packet/utp.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 ryu/lib/packet/utp.py
diff --git a/ryu/lib/packet/utp.py b/ryu/lib/packet/utp.py new file mode 100644 index 0000000..b41573a --- /dev/null +++ b/ryu/lib/packet/utp.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- + +import struct + +from ryu.lib.packet import packet_base +from ryu.lib.packet import packet_utils + + +class utp(packet_base.PacketBase): + """µTP header encoder/decoder class, see http://www.bittorrent.org/beps/bep_0029.html + + An instance has the following attributes at least. + Most of them are same to the on-wire counterparts but in host byte order. + + This does not currently implement extension headers. + + ============== ==================== + Attribute Description + ============== ==================== + type Type of the packet + version Version of the protocol + extension Type of the next extension header + connection_id Connection ID for all packets of this flow + timestamp_microseconds Timestamp set by the sender + timestamp_difference_microseconds Latest one-way-delay from remote to local + wnd_size Advertised receive window + seq_nr Sequence number (in packets) + ack_nr Sequence number of the last received packet + ============== ==================== + """ + + # Type and version are 4 bits each, so group them together... + _PACK_STR = '!BBHIiIHH' + _MIN_LEN = struct.calcsize(_PACK_STR) + + def __init__(self, type=4, version=1, extension=0, connection_id=0, + timestamp_microseconds=0, timestamp_difference_microseconds=0, + wnd_size=0, seq_nr=0, ack_nr=0): + super(utp, self).__init__() + self.type = type + self.version = version + self.extension = extension + self.connection_id = connection_id + self.timestamp_microseconds = timestamp_microseconds + self.timestamp_difference_microseconds = timestamp_difference_microseconds + self.wnd_size = wnd_size + self.seq_nr = seq_nr + self.ack_nr = ack_nr + + @classmethod + def detect_utp(cls, payload): + """Detection heuristic for the µTP protocol, inspired from wireshark (BT-uTP). + Note that the heuristic is somewhat weak and will produce false + positives. For instance, it will match random UDP packets of + sufficient size with probability 4/256. + """ + if len(payload) < 20: + return False + (type_version,) = struct.unpack_from("!B", payload, 0) + type = type_version >> 4 + version = type_version & 0x0F + if (version != 1): + return False + if (type < 0 or type > 4): + return False + return True + + @classmethod + def parser(cls, buf): + (type_version, extension, connection_id, timestamp_microseconds, + timestamp_difference_microseconds, wnd_size, seq_nr, + ack_nr) = struct.unpack_from(cls._PACK_STR, buf) + type = type_version >> 4 + version = type_version & 0x0F + msg = cls(type, version, extension, connection_id, timestamp_microseconds, + timestamp_difference_microseconds, wnd_size, seq_nr, ack_nr) + # TODO: parse options + length = msg._MIN_LEN + return msg, None, buf[length:] + + def serialize(self, payload, prev): + type_version = (self.type << 4) | self.version + h = struct.pack(utp._PACK_STR, type_version, self.extension, + self.connection_id, self.timestamp_microseconds, + self.timestamp_difference_microseconds, self.wnd_size, + self.seq_nr, self.ack_nr) + return h -- 2.6.4 ------------------------------------------------------------------------------ _______________________________________________ Ryu-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ryu-devel
