1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef P2P_BASE_PSEUDO_TCP_H_ 12 #define P2P_BASE_PSEUDO_TCP_H_ 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <list> 18 #include <memory> 19 20 #include "rtc_base/synchronization/mutex.h" 21 #include "rtc_base/system/rtc_export.h" 22 23 namespace cricket { 24 25 ////////////////////////////////////////////////////////////////////// 26 // IPseudoTcpNotify 27 ////////////////////////////////////////////////////////////////////// 28 29 class PseudoTcp; 30 31 class IPseudoTcpNotify { 32 public: 33 // Notification of tcp events 34 virtual void OnTcpOpen(PseudoTcp* tcp) = 0; 35 virtual void OnTcpReadable(PseudoTcp* tcp) = 0; 36 virtual void OnTcpWriteable(PseudoTcp* tcp) = 0; 37 virtual void OnTcpClosed(PseudoTcp* tcp, uint32_t error) = 0; 38 39 // Write the packet onto the network 40 enum WriteResult { WR_SUCCESS, WR_TOO_LARGE, WR_FAIL }; 41 virtual WriteResult TcpWritePacket(PseudoTcp* tcp, 42 const char* buffer, 43 size_t len) = 0; 44 45 protected: ~IPseudoTcpNotify()46 virtual ~IPseudoTcpNotify() {} 47 }; 48 49 ////////////////////////////////////////////////////////////////////// 50 // PseudoTcp 51 ////////////////////////////////////////////////////////////////////// 52 53 class RTC_EXPORT PseudoTcp { 54 public: 55 static uint32_t Now(); 56 57 PseudoTcp(IPseudoTcpNotify* notify, uint32_t conv); 58 virtual ~PseudoTcp(); 59 60 int Connect(); 61 int Recv(char* buffer, size_t len); 62 int Send(const char* buffer, size_t len); 63 void Close(bool force); 64 int GetError(); 65 66 enum TcpState { 67 TCP_LISTEN, 68 TCP_SYN_SENT, 69 TCP_SYN_RECEIVED, 70 TCP_ESTABLISHED, 71 TCP_CLOSED 72 }; State()73 TcpState State() const { return m_state; } 74 75 // Call this when the PMTU changes. 76 void NotifyMTU(uint16_t mtu); 77 78 // Call this based on timeout value returned from GetNextClock. 79 // It's ok to call this too frequently. 80 void NotifyClock(uint32_t now); 81 82 // Call this whenever a packet arrives. 83 // Returns true if the packet was processed successfully. 84 bool NotifyPacket(const char* buffer, size_t len); 85 86 // Call this to determine the next time NotifyClock should be called. 87 // Returns false if the socket is ready to be destroyed. 88 bool GetNextClock(uint32_t now, long& timeout); 89 90 // Call these to get/set option values to tailor this PseudoTcp 91 // instance's behaviour for the kind of data it will carry. 92 // If an unrecognized option is set or got, an assertion will fire. 93 // 94 // Setting options for OPT_RCVBUF or OPT_SNDBUF after Connect() is called 95 // will result in an assertion. 96 enum Option { 97 OPT_NODELAY, // Whether to enable Nagle's algorithm (0 == off) 98 OPT_ACKDELAY, // The Delayed ACK timeout (0 == off). 99 OPT_RCVBUF, // Set the receive buffer size, in bytes. 100 OPT_SNDBUF, // Set the send buffer size, in bytes. 101 }; 102 void GetOption(Option opt, int* value); 103 void SetOption(Option opt, int value); 104 105 // Returns current congestion window in bytes. 106 uint32_t GetCongestionWindow() const; 107 108 // Returns amount of data in bytes that has been sent, but haven't 109 // been acknowledged. 110 uint32_t GetBytesInFlight() const; 111 112 // Returns number of bytes that were written in buffer and haven't 113 // been sent. 114 uint32_t GetBytesBufferedNotSent() const; 115 116 // Returns current round-trip time estimate in milliseconds. 117 uint32_t GetRoundTripTimeEstimateMs() const; 118 119 protected: 120 enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck }; 121 122 struct Segment { 123 uint32_t conv, seq, ack; 124 uint8_t flags; 125 uint16_t wnd; 126 const char* data; 127 uint32_t len; 128 uint32_t tsval, tsecr; 129 }; 130 131 struct SSegment { SSegmentSSegment132 SSegment(uint32_t s, uint32_t l, bool c) 133 : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) {} 134 uint32_t seq, len; 135 // uint32_t tstamp; 136 uint8_t xmit; 137 bool bCtrl; 138 }; 139 typedef std::list<SSegment> SList; 140 141 struct RSegment { 142 uint32_t seq, len; 143 }; 144 145 uint32_t queue(const char* data, uint32_t len, bool bCtrl); 146 147 // Creates a packet and submits it to the network. This method can either 148 // send payload or just an ACK packet. 149 // 150 // `seq` is the sequence number of this packet. 151 // `flags` is the flags for sending this packet. 152 // `offset` is the offset to read from `m_sbuf`. 153 // `len` is the number of bytes to read from `m_sbuf` as payload. If this 154 // value is 0 then this is an ACK packet, otherwise this packet has payload. 155 IPseudoTcpNotify::WriteResult packet(uint32_t seq, 156 uint8_t flags, 157 uint32_t offset, 158 uint32_t len); 159 bool parse(const uint8_t* buffer, uint32_t size); 160 161 void attemptSend(SendFlags sflags = sfNone); 162 163 void closedown(uint32_t err = 0); 164 165 bool clock_check(uint32_t now, long& nTimeout); 166 167 bool process(Segment& seg); 168 bool transmit(const SList::iterator& seg, uint32_t now); 169 170 void adjustMTU(); 171 172 protected: 173 // This method is used in test only to query receive buffer state. 174 bool isReceiveBufferFull() const; 175 176 // This method is only used in tests, to disable window scaling 177 // support for testing backward compatibility. 178 void disableWindowScale(); 179 180 private: 181 // Queue the connect message with TCP options. 182 void queueConnectMessage(); 183 184 // Parse TCP options in the header. 185 void parseOptions(const char* data, uint32_t len); 186 187 // Apply a TCP option that has been read from the header. 188 void applyOption(char kind, const char* data, uint32_t len); 189 190 // Apply window scale option. 191 void applyWindowScaleOption(uint8_t scale_factor); 192 193 // Resize the send buffer with `new_size` in bytes. 194 void resizeSendBuffer(uint32_t new_size); 195 196 // Resize the receive buffer with `new_size` in bytes. This call adjusts 197 // window scale factor `m_swnd_scale` accordingly. 198 void resizeReceiveBuffer(uint32_t new_size); 199 200 class LockedFifoBuffer final { 201 public: 202 explicit LockedFifoBuffer(size_t size); 203 ~LockedFifoBuffer(); 204 205 size_t GetBuffered() const; 206 bool SetCapacity(size_t size); 207 bool ReadOffset(void* buffer, 208 size_t bytes, 209 size_t offset, 210 size_t* bytes_read); 211 bool WriteOffset(const void* buffer, 212 size_t bytes, 213 size_t offset, 214 size_t* bytes_written); 215 bool Read(void* buffer, size_t bytes, size_t* bytes_read); 216 bool Write(const void* buffer, size_t bytes, size_t* bytes_written); 217 void ConsumeReadData(size_t size); 218 void ConsumeWriteBuffer(size_t size); 219 bool GetWriteRemaining(size_t* size) const; 220 221 private: 222 bool ReadOffsetLocked(void* buffer, 223 size_t bytes, 224 size_t offset, 225 size_t* bytes_read) 226 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 227 bool WriteOffsetLocked(const void* buffer, 228 size_t bytes, 229 size_t offset, 230 size_t* bytes_written) 231 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 232 233 // the allocated buffer 234 std::unique_ptr<char[]> buffer_ RTC_GUARDED_BY(mutex_); 235 // size of the allocated buffer 236 size_t buffer_length_ RTC_GUARDED_BY(mutex_); 237 // amount of readable data in the buffer 238 size_t data_length_ RTC_GUARDED_BY(mutex_); 239 // offset to the readable data 240 size_t read_position_ RTC_GUARDED_BY(mutex_); 241 mutable webrtc::Mutex mutex_; 242 }; 243 244 IPseudoTcpNotify* m_notify; 245 enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown; 246 int m_error; 247 248 // TCB data 249 TcpState m_state; 250 uint32_t m_conv; 251 bool m_bReadEnable, m_bWriteEnable, m_bOutgoing; 252 uint32_t m_lasttraffic; 253 254 // Incoming data 255 typedef std::list<RSegment> RList; 256 RList m_rlist; 257 uint32_t m_rbuf_len, m_rcv_nxt, m_rcv_wnd, m_lastrecv; 258 uint8_t m_rwnd_scale; // Window scale factor. 259 LockedFifoBuffer m_rbuf; 260 261 // Outgoing data 262 SList m_slist; 263 uint32_t m_sbuf_len, m_snd_nxt, m_snd_wnd, m_lastsend, m_snd_una; 264 uint8_t m_swnd_scale; // Window scale factor. 265 LockedFifoBuffer m_sbuf; 266 267 // Maximum segment size, estimated protocol level, largest segment sent 268 uint32_t m_mss, m_msslevel, m_largest, m_mtu_advise; 269 // Retransmit timer 270 uint32_t m_rto_base; 271 272 // Timestamp tracking 273 uint32_t m_ts_recent, m_ts_lastack; 274 275 // Round-trip calculation 276 uint32_t m_rx_rttvar, m_rx_srtt, m_rx_rto; 277 278 // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs 279 uint32_t m_ssthresh, m_cwnd; 280 uint8_t m_dup_acks; 281 uint32_t m_recover; 282 uint32_t m_t_ack; 283 284 // Configuration options 285 bool m_use_nagling; 286 uint32_t m_ack_delay; 287 288 // This is used by unit tests to test backward compatibility of 289 // PseudoTcp implementations that don't support window scaling. 290 bool m_support_wnd_scale; 291 }; 292 293 } // namespace cricket 294 295 #endif // P2P_BASE_PSEUDO_TCP_H_ 296