• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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