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