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