1 /*
2 SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #ifndef UTP_UTPPROTOCOL_H
8 #define UTP_UTPPROTOCOL_H
9
10 #include <QString>
11 #include <QtGlobal>
12 #include <ktorrent_export.h>
13 #include <util/constants.h>
14
15 namespace utp
16 {
17 /*
18 UTP header:
19
20 0 4 8 16 24 32
21 +-------+-------+---------------+---------------+---------------+
22 | ver | type | extension | connection_id |
23 +-------+-------+---------------+---------------+---------------+
24 | timestamp_microseconds |
25 +---------------+---------------+---------------+---------------+
26 | timestamp_difference_microseconds |
27 +---------------+---------------+---------------+---------------+
28 | wnd_size |
29 +---------------+---------------+---------------+---------------+
30 | seq_nr | ack_nr |
31 +---------------+---------------+---------------+---------------+
32 */
33
34 struct KTORRENT_EXPORT Header {
35 unsigned int version : 4;
36 unsigned int type : 4;
37 bt::Uint8 extension;
38 bt::Uint16 connection_id;
39 bt::Uint32 timestamp_microseconds;
40 bt::Uint32 timestamp_difference_microseconds;
41 bt::Uint32 wnd_size;
42 bt::Uint16 seq_nr;
43 bt::Uint16 ack_nr;
44
45 void read(const bt::Uint8 *data);
46 void write(bt::Uint8 *data) const;
47 static bt::Uint32 size();
48 };
49
50 struct SelectiveAck {
51 bt::Uint8 *bitmask;
52 bt::Uint8 extension;
53 bt::Uint8 length;
54
SelectiveAckSelectiveAck55 SelectiveAck()
56 : bitmask(nullptr)
57 , extension(0)
58 , length(0)
59 {
60 }
61 };
62
63 struct ExtensionBits {
64 bt::Uint8 extension;
65 bt::Uint8 length;
66 bt::Uint8 extension_bitmask[8];
67 };
68
69 struct UnknownExtension {
70 bt::Uint8 extension;
71 bt::Uint8 length;
72 };
73
74 const bt::Uint8 SELECTIVE_ACK_ID = 1;
75 const bt::Uint8 EXTENSION_BITS_ID = 2;
76
77 // type field values
78 const bt::Uint8 ST_DATA = 0;
79 const bt::Uint8 ST_FIN = 1;
80 const bt::Uint8 ST_STATE = 2;
81 const bt::Uint8 ST_RESET = 3;
82 const bt::Uint8 ST_SYN = 4;
83
84 KTORRENT_EXPORT QString TypeToString(bt::Uint8 type);
85
86 enum ConnectionState {
87 CS_IDLE,
88 CS_SYN_SENT,
89 CS_CONNECTED,
90 CS_FINISHED,
91 CS_CLOSED,
92 };
93
94 const bt::Uint32 MIN_PACKET_SIZE = 150;
95 const bt::Uint32 MAX_PACKET_SIZE = 16384;
96
97 const bt::Uint32 DELAY_WINDOW_SIZE = 2 * 60 * 1000; // 2 minutes
98 const bt::Uint32 CCONTROL_TARGET = 100;
99 const bt::Uint32 MAX_CWND_INCREASE_PACKETS_PER_RTT = 500;
100 const bt::Uint32 MAX_TIMEOUT = 30000;
101 const bt::Uint32 CONNECT_TIMEOUT = 30000;
102 const bt::Uint32 KEEP_ALIVE_TIMEOUT = 30000;
103
104 const bt::Uint32 IP_AND_UDP_OVERHEAD = 28;
105
106 /*
107 Test if a bit is acked
108 UTP standard:
109 The bitmask has reverse byte order. The first byte represents packets [ack_nr + 2, ack_nr + 2 + 7] in reverse order. The least significant bit in the byte
110 represents ack_nr + 2, the most significant bit in the byte represents ack_nr + 2 + 7. The next byte in the mask represents [ack_nr + 2 + 8, ack_nr + 2 + 15] in
111 reverse order, and so on. The bitmask is not limited to 32 bits but can be of any size.
112
113 Here is the layout of a bitmask representing the first 32 packet acks represented in a selective ACK bitfield:
114
115 0 8 16
116 +---------------+---------------+---------------+---------------+
117 | 9 8 ... 3 2 | 17 ... 10 | 25 ... 18 | 33 ... 26 |
118 +---------------+---------------+---------------+---------------+
119
120 The number in the diagram maps the bit in the bitmask to the offset to add to ack_nr in order to calculate the sequence number that the bit is ACKing.
121 */
Acked(const SelectiveAck * sack,bt::Uint16 bit)122 inline bool Acked(const SelectiveAck *sack, bt::Uint16 bit)
123 {
124 // check bounds
125 if (bit < 2 || bit > 8 * sack->length + 1)
126 return false;
127
128 const bt::Uint8 *bitset = sack->bitmask;
129 int byte = (bit - 2) / 8;
130 int bit_off = (bit - 2) % 8;
131 return bitset[byte] & (0x01 << bit_off);
132 }
133
134 // Turn on a bit in the SelectiveAck
Ack(SelectiveAck * sack,bt::Uint16 bit)135 inline void Ack(SelectiveAck *sack, bt::Uint16 bit)
136 {
137 // check bounds
138 if (bit < 2 || bit > 8 * sack->length + 1)
139 return;
140
141 bt::Uint8 *bitset = sack->bitmask;
142 int byte = (bit - 2) / 8;
143 int bit_off = (bit - 2) % 8;
144 bitset[byte] |= (0x01 << bit_off);
145 }
146
147 /**
148 Helper class to parse packets
149 */
150 class KTORRENT_EXPORT PacketParser
151 {
152 public:
153 PacketParser(const QByteArray &packet);
154 PacketParser(const bt::Uint8 *packet, bt::Uint32 size);
155 ~PacketParser();
156
157 /// Parses the packet, returns false on error
158 bool parse();
159
header()160 const Header *header() const
161 {
162 return &hdr;
163 }
164 const SelectiveAck *selectiveAck() const;
dataOffset()165 bt::Uint32 dataOffset() const
166 {
167 return data_off;
168 }
dataSize()169 bt::Uint32 dataSize() const
170 {
171 return data_size;
172 }
173
174 private:
175 const bt::Uint8 *packet;
176 Header hdr;
177 SelectiveAck sack;
178 bool sack_found;
179 bt::Uint32 size;
180 bt::Uint32 data_off;
181 bt::Uint32 data_size;
182 };
183
184 /// <= for sequence numbers (taking into account wrapping around)
SeqNrCmpSE(bt::Uint16 a,bt::Uint16 b)185 inline bool SeqNrCmpSE(bt::Uint16 a, bt::Uint16 b)
186 {
187 if (qAbs(b - a) < 32768)
188 return a <= b;
189 else
190 return a > b;
191 }
192
193 /// < for sequence numbers (taking into account wrapping around)
SeqNrCmpS(bt::Uint16 a,bt::Uint16 b)194 inline bool SeqNrCmpS(bt::Uint16 a, bt::Uint16 b)
195 {
196 if (qAbs(b - a) < 32768)
197 return a < b;
198 else
199 return a > b;
200 }
201
202 /// Calculates difference between two sequence numbers (taking into account wrapping around)
SeqNrDiff(bt::Uint16 a,bt::Uint16 b)203 inline bt::Uint16 SeqNrDiff(bt::Uint16 a, bt::Uint16 b)
204 {
205 if (qAbs(b - a) < 32768)
206 return b - a;
207 else if (b > a)
208 return a + (65536 - b);
209 else
210 return b + (65536 - a);
211 }
212 }
213
214 #endif // UTP_UTPPROTOCOL_H
215