1 /*
2 SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 #include "utpprotocol.h"
7 #include <util/functions.h>
8
9 namespace utp
10 {
TypeToString(bt::Uint8 type)11 QString TypeToString(bt::Uint8 type)
12 {
13 switch (type) {
14 case ST_DATA:
15 return QStringLiteral("DATA");
16 case ST_FIN:
17 return QStringLiteral("FIN");
18 case ST_STATE:
19 return QStringLiteral("STATE");
20 case ST_RESET:
21 return QStringLiteral("RESET");
22 case ST_SYN:
23 return QStringLiteral("SYN");
24 default:
25 return QStringLiteral("UNKNOWN");
26 }
27 }
28
read(const bt::Uint8 * data)29 void Header::read(const bt::Uint8 *data)
30 {
31 type = (data[0] & 0xF0) >> 4;
32 version = data[0] & 0x0F;
33 extension = data[1];
34 connection_id = bt::ReadUint16(data, 2);
35 timestamp_microseconds = bt::ReadUint32(data, 4);
36 timestamp_difference_microseconds = bt::ReadUint32(data, 8);
37 wnd_size = bt::ReadUint32(data, 12);
38 seq_nr = bt::ReadUint16(data, 16);
39 ack_nr = bt::ReadUint16(data, 18);
40 }
41
write(bt::Uint8 * data) const42 void Header::write(bt::Uint8 *data) const
43 {
44 data[0] = ((type << 4) & 0xF0) | (version & 0x0F);
45 data[1] = extension;
46 bt::WriteUint16(data, 2, connection_id);
47 bt::WriteUint32(data, 4, timestamp_microseconds);
48 bt::WriteUint32(data, 8, timestamp_difference_microseconds);
49 bt::WriteUint32(data, 12, wnd_size);
50 bt::WriteUint16(data, 16, seq_nr);
51 bt::WriteUint16(data, 18, ack_nr);
52 }
53
size()54 bt::Uint32 Header::size()
55 {
56 return 20;
57 }
58
PacketParser(const QByteArray & pkt)59 PacketParser::PacketParser(const QByteArray &pkt)
60 : packet((const bt::Uint8 *)pkt.data())
61 , sack_found(false)
62 , size(pkt.size())
63 , data_off(0)
64 , data_size(0)
65 {
66 hdr.read(packet);
67 }
68
PacketParser(const bt::Uint8 * packet,bt::Uint32 size)69 PacketParser::PacketParser(const bt::Uint8 *packet, bt::Uint32 size)
70 : packet(packet)
71 , sack_found(false)
72 , size(size)
73 , data_off(0)
74 , data_size(0)
75 {
76 hdr.read(packet);
77 }
78
~PacketParser()79 PacketParser::~PacketParser()
80 {
81 }
82
parse()83 bool PacketParser::parse()
84 {
85 if (size < Header::size())
86 return false;
87
88 data_off = Header::size();
89
90 // go over all header extensions to increase the data offset and watch out for selective acks
91 int ext_id = hdr.extension;
92 while (data_off < size && ext_id != 0) {
93 const bt::Uint8 *ptr = packet + data_off;
94 if (ext_id == SELECTIVE_ACK_ID) {
95 sack_found = true;
96 sack.extension = ptr[0];
97 sack.length = ptr[1];
98 if (data_off + 2 + sack.length > size)
99 return false;
100 sack.bitmask = (bt::Uint8 *)ptr + 2;
101 }
102
103 data_off += 2 + ptr[1];
104 ext_id = ptr[0];
105 }
106
107 data_size = size - data_off;
108 return true;
109 }
110
selectiveAck() const111 const utp::SelectiveAck *PacketParser::selectiveAck() const
112 {
113 return sack_found ? &sack : nullptr;
114 }
115
116 }
117