blob: 65b54ba125aa97456f5c82c476a7ba9847490be0 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
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
Steve Anton10542f22019-01-11 09:11:00 -080011#ifndef P2P_BASE_PSEUDO_TCP_H_
12#define P2P_BASE_PSEUDO_TCP_H_
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000013
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <stddef.h>
15#include <stdint.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020016
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000017#include <list>
Tomas Gunnarsson8e4cda72020-10-05 13:44:39 +020018#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000019
Tomas Gunnarsson8e4cda72020-10-05 13:44:39 +020020#include "rtc_base/synchronization/mutex.h"
Mirko Bonadeiac194142018-10-22 17:08:37 +020021#include "rtc_base/system/rtc_export.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000022
23namespace cricket {
24
25//////////////////////////////////////////////////////////////////////
26// IPseudoTcpNotify
27//////////////////////////////////////////////////////////////////////
28
29class PseudoTcp;
30
31class 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;
Peter Boström0c4e06b2015-10-07 12:23:21 +020037 virtual void OnTcpClosed(PseudoTcp* tcp, uint32_t error) = 0;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000038
39 // Write the packet onto the network
40 enum WriteResult { WR_SUCCESS, WR_TOO_LARGE, WR_FAIL };
41 virtual WriteResult TcpWritePacket(PseudoTcp* tcp,
Yves Gerey665174f2018-06-19 15:03:05 +020042 const char* buffer,
43 size_t len) = 0;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000044
45 protected:
46 virtual ~IPseudoTcpNotify() {}
47};
48
49//////////////////////////////////////////////////////////////////////
50// PseudoTcp
51//////////////////////////////////////////////////////////////////////
52
Mirko Bonadeiac194142018-10-22 17:08:37 +020053class RTC_EXPORT PseudoTcp {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000054 public:
Peter Boström0c4e06b2015-10-07 12:23:21 +020055 static uint32_t Now();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000056
Peter Boström0c4e06b2015-10-07 12:23:21 +020057 PseudoTcp(IPseudoTcpNotify* notify, uint32_t conv);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000058 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 {
Yves Gerey665174f2018-06-19 15:03:05 +020067 TCP_LISTEN,
68 TCP_SYN_SENT,
69 TCP_SYN_RECEIVED,
70 TCP_ESTABLISHED,
71 TCP_CLOSED
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000072 };
73 TcpState State() const { return m_state; }
74
75 // Call this when the PMTU changes.
Peter Boström0c4e06b2015-10-07 12:23:21 +020076 void NotifyMTU(uint16_t mtu);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000077
78 // Call this based on timeout value returned from GetNextClock.
79 // It's ok to call this too frequently.
Peter Boström0c4e06b2015-10-07 12:23:21 +020080 void NotifyClock(uint32_t now);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000081
82 // Call this whenever a packet arrives.
83 // Returns true if the packet was processed successfully.
Yves Gerey665174f2018-06-19 15:03:05 +020084 bool NotifyPacket(const char* buffer, size_t len);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000085
86 // Call this to determine the next time NotifyClock should be called.
87 // Returns false if the socket is ready to be destroyed.
Peter Boström0c4e06b2015-10-07 12:23:21 +020088 bool GetNextClock(uint32_t now, long& timeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000089
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 {
Yves Gerey665174f2018-06-19 15:03:05 +020097 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.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000101 };
102 void GetOption(Option opt, int* value);
103 void SetOption(Option opt, int value);
104
105 // Returns current congestion window in bytes.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200106 uint32_t GetCongestionWindow() const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000107
108 // Returns amount of data in bytes that has been sent, but haven't
109 // been acknowledged.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200110 uint32_t GetBytesInFlight() const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000111
112 // Returns number of bytes that were written in buffer and haven't
113 // been sent.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200114 uint32_t GetBytesBufferedNotSent() const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000115
116 // Returns current round-trip time estimate in milliseconds.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200117 uint32_t GetRoundTripTimeEstimateMs() const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000118
119 protected:
120 enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck };
121
122 struct Segment {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200123 uint32_t conv, seq, ack;
124 uint8_t flags;
125 uint16_t wnd;
Yves Gerey665174f2018-06-19 15:03:05 +0200126 const char* data;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200127 uint32_t len;
128 uint32_t tsval, tsecr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000129 };
130
131 struct SSegment {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200132 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;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000137 bool bCtrl;
138 };
139 typedef std::list<SSegment> SList;
140
141 struct RSegment {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200142 uint32_t seq, len;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000143 };
144
Peter Boström0c4e06b2015-10-07 12:23:21 +0200145 uint32_t queue(const char* data, uint32_t len, bool bCtrl);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000146
147 // Creates a packet and submits it to the network. This method can either
148 // send payload or just an ACK packet.
149 //
Artem Titov2dbb4c92021-07-26 15:12:41 +0200150 // `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
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000154 // value is 0 then this is an ACK packet, otherwise this packet has payload.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200155 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);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000160
161 void attemptSend(SendFlags sflags = sfNone);
162
Peter Boström0c4e06b2015-10-07 12:23:21 +0200163 void closedown(uint32_t err = 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000164
Peter Boström0c4e06b2015-10-07 12:23:21 +0200165 bool clock_check(uint32_t now, long& nTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000166
167 bool process(Segment& seg);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200168 bool transmit(const SList::iterator& seg, uint32_t now);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000169
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.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200185 void parseOptions(const char* data, uint32_t len);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000186
187 // Apply a TCP option that has been read from the header.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200188 void applyOption(char kind, const char* data, uint32_t len);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000189
190 // Apply window scale option.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200191 void applyWindowScaleOption(uint8_t scale_factor);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000192
Artem Titov2dbb4c92021-07-26 15:12:41 +0200193 // Resize the send buffer with `new_size` in bytes.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200194 void resizeSendBuffer(uint32_t new_size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000195
Artem Titov2dbb4c92021-07-26 15:12:41 +0200196 // Resize the receive buffer with `new_size` in bytes. This call adjusts
197 // window scale factor `m_swnd_scale` accordingly.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200198 void resizeReceiveBuffer(uint32_t new_size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000199
Tomas Gunnarsson8e4cda72020-10-05 13:44:39 +0200200 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
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000244 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;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200250 uint32_t m_conv;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000251 bool m_bReadEnable, m_bWriteEnable, m_bOutgoing;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200252 uint32_t m_lasttraffic;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000253
254 // Incoming data
255 typedef std::list<RSegment> RList;
256 RList m_rlist;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200257 uint32_t m_rbuf_len, m_rcv_nxt, m_rcv_wnd, m_lastrecv;
258 uint8_t m_rwnd_scale; // Window scale factor.
Tomas Gunnarsson8e4cda72020-10-05 13:44:39 +0200259 LockedFifoBuffer m_rbuf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000260
261 // Outgoing data
262 SList m_slist;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200263 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.
Tomas Gunnarsson8e4cda72020-10-05 13:44:39 +0200265 LockedFifoBuffer m_sbuf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000266
267 // Maximum segment size, estimated protocol level, largest segment sent
Peter Boström0c4e06b2015-10-07 12:23:21 +0200268 uint32_t m_mss, m_msslevel, m_largest, m_mtu_advise;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000269 // Retransmit timer
Peter Boström0c4e06b2015-10-07 12:23:21 +0200270 uint32_t m_rto_base;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000271
272 // Timestamp tracking
Peter Boström0c4e06b2015-10-07 12:23:21 +0200273 uint32_t m_ts_recent, m_ts_lastack;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000274
275 // Round-trip calculation
Peter Boström0c4e06b2015-10-07 12:23:21 +0200276 uint32_t m_rx_rttvar, m_rx_srtt, m_rx_rto;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000277
278 // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs
Peter Boström0c4e06b2015-10-07 12:23:21 +0200279 uint32_t m_ssthresh, m_cwnd;
280 uint8_t m_dup_acks;
281 uint32_t m_recover;
282 uint32_t m_t_ack;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000283
284 // Configuration options
285 bool m_use_nagling;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200286 uint32_t m_ack_delay;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000287
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
Steve Anton10542f22019-01-11 09:11:00 -0800295#endif // P2P_BASE_PSEUDO_TCP_H_