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 }