File indexing completed on 2025-01-05 04:37:33
0001 /* 0002 SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "utpprotocol.h" 0007 #include <util/functions.h> 0008 0009 namespace utp 0010 { 0011 QString TypeToString(bt::Uint8 type) 0012 { 0013 switch (type) { 0014 case ST_DATA: 0015 return QStringLiteral("DATA"); 0016 case ST_FIN: 0017 return QStringLiteral("FIN"); 0018 case ST_STATE: 0019 return QStringLiteral("STATE"); 0020 case ST_RESET: 0021 return QStringLiteral("RESET"); 0022 case ST_SYN: 0023 return QStringLiteral("SYN"); 0024 default: 0025 return QStringLiteral("UNKNOWN"); 0026 } 0027 } 0028 0029 void Header::read(const bt::Uint8 *data) 0030 { 0031 type = (data[0] & 0xF0) >> 4; 0032 version = data[0] & 0x0F; 0033 extension = data[1]; 0034 connection_id = bt::ReadUint16(data, 2); 0035 timestamp_microseconds = bt::ReadUint32(data, 4); 0036 timestamp_difference_microseconds = bt::ReadUint32(data, 8); 0037 wnd_size = bt::ReadUint32(data, 12); 0038 seq_nr = bt::ReadUint16(data, 16); 0039 ack_nr = bt::ReadUint16(data, 18); 0040 } 0041 0042 void Header::write(bt::Uint8 *data) const 0043 { 0044 data[0] = ((type << 4) & 0xF0) | (version & 0x0F); 0045 data[1] = extension; 0046 bt::WriteUint16(data, 2, connection_id); 0047 bt::WriteUint32(data, 4, timestamp_microseconds); 0048 bt::WriteUint32(data, 8, timestamp_difference_microseconds); 0049 bt::WriteUint32(data, 12, wnd_size); 0050 bt::WriteUint16(data, 16, seq_nr); 0051 bt::WriteUint16(data, 18, ack_nr); 0052 } 0053 0054 bt::Uint32 Header::size() 0055 { 0056 return 20; 0057 } 0058 0059 PacketParser::PacketParser(const QByteArray &pkt) 0060 : packet((const bt::Uint8 *)pkt.data()) 0061 , sack_found(false) 0062 , size(pkt.size()) 0063 , data_off(0) 0064 , data_size(0) 0065 { 0066 hdr.read(packet); 0067 } 0068 0069 PacketParser::PacketParser(const bt::Uint8 *packet, bt::Uint32 size) 0070 : packet(packet) 0071 , sack_found(false) 0072 , size(size) 0073 , data_off(0) 0074 , data_size(0) 0075 { 0076 hdr.read(packet); 0077 } 0078 0079 PacketParser::~PacketParser() 0080 { 0081 } 0082 0083 bool PacketParser::parse() 0084 { 0085 if (size < Header::size()) 0086 return false; 0087 0088 data_off = Header::size(); 0089 0090 // go over all header extensions to increase the data offset and watch out for selective acks 0091 int ext_id = hdr.extension; 0092 while (data_off < size && ext_id != 0) { 0093 const bt::Uint8 *ptr = packet + data_off; 0094 if (ext_id == SELECTIVE_ACK_ID) { 0095 sack_found = true; 0096 sack.extension = ptr[0]; 0097 sack.length = ptr[1]; 0098 if (data_off + 2 + sack.length > size) 0099 return false; 0100 sack.bitmask = (bt::Uint8 *)ptr + 2; 0101 } 0102 0103 data_off += 2 + ptr[1]; 0104 ext_id = ptr[0]; 0105 } 0106 0107 data_size = size - data_off; 0108 return true; 0109 } 0110 0111 const utp::SelectiveAck *PacketParser::selectiveAck() const 0112 { 0113 return sack_found ? &sack : nullptr; 0114 } 0115 0116 }