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 
0007 #ifndef UTP_REMOTEWINDOW_H
0008 #define UTP_REMOTEWINDOW_H
0009 
0010 #include <QList>
0011 #include <QMutex>
0012 #include <QSharedPointer>
0013 #include <ktorrent_export.h>
0014 #include <util/constants.h>
0015 #include <utp/packetbuffer.h>
0016 #include <utp/timevalue.h>
0017 
0018 namespace utp
0019 {
0020 struct SelectiveAck;
0021 struct Header;
0022 
0023 struct UnackedPacket {
0024     UnackedPacket(const PacketBuffer &packet, bt::Uint16 seq_nr, bt::TimeStamp send_time);
0025     ~UnackedPacket();
0026 
0027     PacketBuffer packet;
0028     bt::Uint16 seq_nr;
0029     bt::TimeStamp send_time;
0030     bool retransmitted;
0031 };
0032 
0033 /**
0034     The Retransmitter provides is an interface class to retransmit packets
0035 */
0036 class KTORRENT_EXPORT Retransmitter
0037 {
0038 public:
0039     virtual ~Retransmitter()
0040     {
0041     }
0042 
0043     /// Update the RTT time
0044     virtual void updateRTT(const Header *hdr, bt::Uint32 packet_rtt, bt::Uint32 packet_size) = 0;
0045 
0046     /// Retransmit a packet
0047     virtual void retransmit(PacketBuffer &packet, bt::Uint16 p_seq_nr) = 0;
0048 
0049     /// Get the current timeout
0050     virtual bt::Uint32 currentTimeout() const = 0;
0051 };
0052 
0053 /**
0054     Keeps track of the remote sides window including all packets inflight.
0055 */
0056 class KTORRENT_EXPORT RemoteWindow
0057 {
0058 public:
0059     RemoteWindow();
0060     virtual ~RemoteWindow();
0061 
0062     /// A packet was received (update window size and check for acks)
0063     void packetReceived(const Header *hdr, const SelectiveAck *sack, Retransmitter *conn);
0064 
0065     /// Add a packet to the remote window (should include headers)
0066     void addPacket(const PacketBuffer &packet, bt::Uint16 seq_nr, bt::TimeStamp send_time);
0067 
0068     /// Are we allowed to send
0069     bool allowedToSend(bt::Uint32 packet_size) const
0070     {
0071         return cur_window + packet_size <= qMin(wnd_size, max_window);
0072     }
0073 
0074     /// Calculates how much window space is availabe
0075     bt::Uint32 availableSpace() const
0076     {
0077         bt::Uint32 m = qMin(wnd_size, max_window);
0078         if (cur_window > m)
0079             return 0;
0080         else
0081             return m - cur_window;
0082     }
0083 
0084     /// See if all packets are acked
0085     bool allPacketsAcked() const
0086     {
0087         return unacked_packets.isEmpty();
0088     }
0089 
0090     /// Get the number of unacked packets
0091     bt::Uint32 numUnackedPackets() const
0092     {
0093         return unacked_packets.count();
0094     }
0095 
0096     /// A timeout occurred
0097     void timeout(Retransmitter *conn);
0098 
0099     /// Get the window usage factor
0100     double windowUsageFactor() const
0101     {
0102         return qMax((double)cur_window / max_window, 1.0);
0103     }
0104 
0105     /// Update the window size
0106     void updateWindowSize(double scaled_gain);
0107 
0108     bt::Uint32 currentWindow() const
0109     {
0110         return cur_window;
0111     }
0112     bt::Uint32 maxWindow() const
0113     {
0114         return max_window;
0115     }
0116     bt::Uint32 windowSize() const
0117     {
0118         return wnd_size;
0119     }
0120 
0121     /// Clear the window
0122     void clear();
0123 
0124 private:
0125     void checkLostPackets(const Header *hdr, const SelectiveAck *sack, Retransmitter *conn);
0126     bt::Uint16 lost(const SelectiveAck *sack);
0127 
0128 private:
0129     bt::Uint32 cur_window;
0130     bt::Uint32 max_window;
0131     bt::Uint32 wnd_size; // advertised window size from the other side
0132     QList<UnackedPacket> unacked_packets;
0133     bt::Uint16 last_ack_nr;
0134     bt::Uint32 last_ack_receive_count;
0135 };
0136 
0137 }
0138 
0139 #endif // UTP_REMOTEWINDOW_H