xref: /aosp_15_r20/external/webrtc/p2p/base/pseudo_tcp.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/pseudo_tcp.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <errno.h>
14*d9f75844SAndroid Build Coastguard Worker #include <stdio.h>
15*d9f75844SAndroid Build Coastguard Worker #include <string.h>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
18*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
19*d9f75844SAndroid Build Coastguard Worker #include <memory>
20*d9f75844SAndroid Build Coastguard Worker #include <set>
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/byte_buffer.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/byte_order.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_minmax.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
29*d9f75844SAndroid Build Coastguard Worker 
30*d9f75844SAndroid Build Coastguard Worker // The following logging is for detailed (packet-level) analysis only.
31*d9f75844SAndroid Build Coastguard Worker #define _DBG_NONE 0
32*d9f75844SAndroid Build Coastguard Worker #define _DBG_NORMAL 1
33*d9f75844SAndroid Build Coastguard Worker #define _DBG_VERBOSE 2
34*d9f75844SAndroid Build Coastguard Worker #define _DEBUGMSG _DBG_NONE
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker namespace cricket {
37*d9f75844SAndroid Build Coastguard Worker 
38*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
39*d9f75844SAndroid Build Coastguard Worker // Network Constants
40*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
41*d9f75844SAndroid Build Coastguard Worker 
42*d9f75844SAndroid Build Coastguard Worker // Standard MTUs
43*d9f75844SAndroid Build Coastguard Worker const uint16_t PACKET_MAXIMUMS[] = {
44*d9f75844SAndroid Build Coastguard Worker     65535,  // Theoretical maximum, Hyperchannel
45*d9f75844SAndroid Build Coastguard Worker     32000,  // Nothing
46*d9f75844SAndroid Build Coastguard Worker     17914,  // 16Mb IBM Token Ring
47*d9f75844SAndroid Build Coastguard Worker     8166,   // IEEE 802.4
48*d9f75844SAndroid Build Coastguard Worker     // 4464,   // IEEE 802.5 (4Mb max)
49*d9f75844SAndroid Build Coastguard Worker     4352,  // FDDI
50*d9f75844SAndroid Build Coastguard Worker     // 2048,   // Wideband Network
51*d9f75844SAndroid Build Coastguard Worker     2002,  // IEEE 802.5 (4Mb recommended)
52*d9f75844SAndroid Build Coastguard Worker     // 1536,   // Expermental Ethernet Networks
53*d9f75844SAndroid Build Coastguard Worker     // 1500,   // Ethernet, Point-to-Point (default)
54*d9f75844SAndroid Build Coastguard Worker     1492,  // IEEE 802.3
55*d9f75844SAndroid Build Coastguard Worker     1006,  // SLIP, ARPANET
56*d9f75844SAndroid Build Coastguard Worker     // 576,    // X.25 Networks
57*d9f75844SAndroid Build Coastguard Worker     // 544,    // DEC IP Portal
58*d9f75844SAndroid Build Coastguard Worker     // 512,    // NETBIOS
59*d9f75844SAndroid Build Coastguard Worker     508,  // IEEE 802/Source-Rt Bridge, ARCNET
60*d9f75844SAndroid Build Coastguard Worker     296,  // Point-to-Point (low delay)
61*d9f75844SAndroid Build Coastguard Worker     // 68,     // Official minimum
62*d9f75844SAndroid Build Coastguard Worker     0,  // End of list marker
63*d9f75844SAndroid Build Coastguard Worker };
64*d9f75844SAndroid Build Coastguard Worker 
65*d9f75844SAndroid Build Coastguard Worker const uint32_t MAX_PACKET = 65535;
66*d9f75844SAndroid Build Coastguard Worker // Note: we removed lowest level because packet overhead was larger!
67*d9f75844SAndroid Build Coastguard Worker const uint32_t MIN_PACKET = 296;
68*d9f75844SAndroid Build Coastguard Worker 
69*d9f75844SAndroid Build Coastguard Worker const uint32_t IP_HEADER_SIZE = 20;  // (+ up to 40 bytes of options?)
70*d9f75844SAndroid Build Coastguard Worker const uint32_t UDP_HEADER_SIZE = 8;
71*d9f75844SAndroid Build Coastguard Worker // TODO(?): Make JINGLE_HEADER_SIZE transparent to this code?
72*d9f75844SAndroid Build Coastguard Worker const uint32_t JINGLE_HEADER_SIZE = 64;  // when relay framing is in use
73*d9f75844SAndroid Build Coastguard Worker 
74*d9f75844SAndroid Build Coastguard Worker // Default size for receive and send buffer.
75*d9f75844SAndroid Build Coastguard Worker const uint32_t DEFAULT_RCV_BUF_SIZE = 60 * 1024;
76*d9f75844SAndroid Build Coastguard Worker const uint32_t DEFAULT_SND_BUF_SIZE = 90 * 1024;
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
79*d9f75844SAndroid Build Coastguard Worker // Global Constants and Functions
80*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
81*d9f75844SAndroid Build Coastguard Worker //
82*d9f75844SAndroid Build Coastguard Worker //    0                   1                   2                   3
83*d9f75844SAndroid Build Coastguard Worker //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
84*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85*d9f75844SAndroid Build Coastguard Worker //  0 |                      Conversation Number                      |
86*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87*d9f75844SAndroid Build Coastguard Worker //  4 |                        Sequence Number                        |
88*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89*d9f75844SAndroid Build Coastguard Worker //  8 |                     Acknowledgment Number                     |
90*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91*d9f75844SAndroid Build Coastguard Worker //    |               |   |U|A|P|R|S|F|                               |
92*d9f75844SAndroid Build Coastguard Worker // 12 |    Control    |   |R|C|S|S|Y|I|            Window             |
93*d9f75844SAndroid Build Coastguard Worker //    |               |   |G|K|H|T|N|N|                               |
94*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95*d9f75844SAndroid Build Coastguard Worker // 16 |                       Timestamp sending                       |
96*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97*d9f75844SAndroid Build Coastguard Worker // 20 |                      Timestamp receiving                      |
98*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99*d9f75844SAndroid Build Coastguard Worker // 24 |                             data                              |
100*d9f75844SAndroid Build Coastguard Worker //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101*d9f75844SAndroid Build Coastguard Worker //
102*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
103*d9f75844SAndroid Build Coastguard Worker 
104*d9f75844SAndroid Build Coastguard Worker #define PSEUDO_KEEPALIVE 0
105*d9f75844SAndroid Build Coastguard Worker 
106*d9f75844SAndroid Build Coastguard Worker const uint32_t HEADER_SIZE = 24;
107*d9f75844SAndroid Build Coastguard Worker const uint32_t PACKET_OVERHEAD =
108*d9f75844SAndroid Build Coastguard Worker     HEADER_SIZE + UDP_HEADER_SIZE + IP_HEADER_SIZE + JINGLE_HEADER_SIZE;
109*d9f75844SAndroid Build Coastguard Worker 
110*d9f75844SAndroid Build Coastguard Worker const uint32_t MIN_RTO =
111*d9f75844SAndroid Build Coastguard Worker     250;  // 250 ms (RFC1122, Sec 4.2.3.1 "fractions of a second")
112*d9f75844SAndroid Build Coastguard Worker const uint32_t DEF_RTO = 3000;       // 3 seconds (RFC1122, Sec 4.2.3.1)
113*d9f75844SAndroid Build Coastguard Worker const uint32_t MAX_RTO = 60000;      // 60 seconds
114*d9f75844SAndroid Build Coastguard Worker const uint32_t DEF_ACK_DELAY = 100;  // 100 milliseconds
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker const uint8_t FLAG_CTL = 0x02;
117*d9f75844SAndroid Build Coastguard Worker const uint8_t FLAG_RST = 0x04;
118*d9f75844SAndroid Build Coastguard Worker 
119*d9f75844SAndroid Build Coastguard Worker const uint8_t CTL_CONNECT = 0;
120*d9f75844SAndroid Build Coastguard Worker 
121*d9f75844SAndroid Build Coastguard Worker // TCP options.
122*d9f75844SAndroid Build Coastguard Worker const uint8_t TCP_OPT_EOL = 0;        // End of list.
123*d9f75844SAndroid Build Coastguard Worker const uint8_t TCP_OPT_NOOP = 1;       // No-op.
124*d9f75844SAndroid Build Coastguard Worker const uint8_t TCP_OPT_MSS = 2;        // Maximum segment size.
125*d9f75844SAndroid Build Coastguard Worker const uint8_t TCP_OPT_WND_SCALE = 3;  // Window scale factor.
126*d9f75844SAndroid Build Coastguard Worker 
127*d9f75844SAndroid Build Coastguard Worker const long DEFAULT_TIMEOUT =
128*d9f75844SAndroid Build Coastguard Worker     4000;  // If there are no pending clocks, wake up every 4 seconds
129*d9f75844SAndroid Build Coastguard Worker const long CLOSED_TIMEOUT =
130*d9f75844SAndroid Build Coastguard Worker     60 * 1000;  // If the connection is closed, once per minute
131*d9f75844SAndroid Build Coastguard Worker 
132*d9f75844SAndroid Build Coastguard Worker #if PSEUDO_KEEPALIVE
133*d9f75844SAndroid Build Coastguard Worker // !?! Rethink these times
134*d9f75844SAndroid Build Coastguard Worker const uint32_t IDLE_PING =
135*d9f75844SAndroid Build Coastguard Worker     20 *
136*d9f75844SAndroid Build Coastguard Worker     1000;  // 20 seconds (note: WinXP SP2 firewall udp timeout is 90 seconds)
137*d9f75844SAndroid Build Coastguard Worker const uint32_t IDLE_TIMEOUT = 90 * 1000;  // 90 seconds;
138*d9f75844SAndroid Build Coastguard Worker #endif                                    // PSEUDO_KEEPALIVE
139*d9f75844SAndroid Build Coastguard Worker 
140*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
141*d9f75844SAndroid Build Coastguard Worker // Helper Functions
142*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
143*d9f75844SAndroid Build Coastguard Worker 
long_to_bytes(uint32_t val,void * buf)144*d9f75844SAndroid Build Coastguard Worker inline void long_to_bytes(uint32_t val, void* buf) {
145*d9f75844SAndroid Build Coastguard Worker   *static_cast<uint32_t*>(buf) = rtc::HostToNetwork32(val);
146*d9f75844SAndroid Build Coastguard Worker }
147*d9f75844SAndroid Build Coastguard Worker 
short_to_bytes(uint16_t val,void * buf)148*d9f75844SAndroid Build Coastguard Worker inline void short_to_bytes(uint16_t val, void* buf) {
149*d9f75844SAndroid Build Coastguard Worker   *static_cast<uint16_t*>(buf) = rtc::HostToNetwork16(val);
150*d9f75844SAndroid Build Coastguard Worker }
151*d9f75844SAndroid Build Coastguard Worker 
bytes_to_long(const void * buf)152*d9f75844SAndroid Build Coastguard Worker inline uint32_t bytes_to_long(const void* buf) {
153*d9f75844SAndroid Build Coastguard Worker   return rtc::NetworkToHost32(*static_cast<const uint32_t*>(buf));
154*d9f75844SAndroid Build Coastguard Worker }
155*d9f75844SAndroid Build Coastguard Worker 
bytes_to_short(const void * buf)156*d9f75844SAndroid Build Coastguard Worker inline uint16_t bytes_to_short(const void* buf) {
157*d9f75844SAndroid Build Coastguard Worker   return rtc::NetworkToHost16(*static_cast<const uint16_t*>(buf));
158*d9f75844SAndroid Build Coastguard Worker }
159*d9f75844SAndroid Build Coastguard Worker 
160*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
161*d9f75844SAndroid Build Coastguard Worker // Debugging Statistics
162*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
163*d9f75844SAndroid Build Coastguard Worker 
164*d9f75844SAndroid Build Coastguard Worker #if 0  // Not used yet
165*d9f75844SAndroid Build Coastguard Worker 
166*d9f75844SAndroid Build Coastguard Worker enum Stat {
167*d9f75844SAndroid Build Coastguard Worker   S_SENT_PACKET,    // All packet sends
168*d9f75844SAndroid Build Coastguard Worker   S_RESENT_PACKET,  // All packet sends that are retransmits
169*d9f75844SAndroid Build Coastguard Worker   S_RECV_PACKET,    // All packet receives
170*d9f75844SAndroid Build Coastguard Worker   S_RECV_NEW,       // All packet receives that are too new
171*d9f75844SAndroid Build Coastguard Worker   S_RECV_OLD,       // All packet receives that are too old
172*d9f75844SAndroid Build Coastguard Worker   S_NUM_STATS
173*d9f75844SAndroid Build Coastguard Worker };
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker const char* const STAT_NAMES[S_NUM_STATS] = {
176*d9f75844SAndroid Build Coastguard Worker   "snt",
177*d9f75844SAndroid Build Coastguard Worker   "snt-r",
178*d9f75844SAndroid Build Coastguard Worker   "rcv"
179*d9f75844SAndroid Build Coastguard Worker   "rcv-n",
180*d9f75844SAndroid Build Coastguard Worker   "rcv-o"
181*d9f75844SAndroid Build Coastguard Worker };
182*d9f75844SAndroid Build Coastguard Worker 
183*d9f75844SAndroid Build Coastguard Worker int g_stats[S_NUM_STATS];
184*d9f75844SAndroid Build Coastguard Worker inline void Incr(Stat s) { ++g_stats[s]; }
185*d9f75844SAndroid Build Coastguard Worker void ReportStats() {
186*d9f75844SAndroid Build Coastguard Worker   char buffer[256];
187*d9f75844SAndroid Build Coastguard Worker   size_t len = 0;
188*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < S_NUM_STATS; ++i) {
189*d9f75844SAndroid Build Coastguard Worker     len += snprintf(buffer, arraysize(buffer), "%s%s:%d",
190*d9f75844SAndroid Build Coastguard Worker                           (i == 0) ? "" : ",", STAT_NAMES[i], g_stats[i]);
191*d9f75844SAndroid Build Coastguard Worker     g_stats[i] = 0;
192*d9f75844SAndroid Build Coastguard Worker   }
193*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Stats[" << buffer << "]";
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker #endif
197*d9f75844SAndroid Build Coastguard Worker 
198*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
199*d9f75844SAndroid Build Coastguard Worker // PseudoTcp
200*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
201*d9f75844SAndroid Build Coastguard Worker 
Now()202*d9f75844SAndroid Build Coastguard Worker uint32_t PseudoTcp::Now() {
203*d9f75844SAndroid Build Coastguard Worker #if 0  // Use this to synchronize timers with logging timestamps (easier debug)
204*d9f75844SAndroid Build Coastguard Worker   return static_cast<uint32_t>(rtc::TimeSince(StartTime()));
205*d9f75844SAndroid Build Coastguard Worker #else
206*d9f75844SAndroid Build Coastguard Worker   return rtc::Time32();
207*d9f75844SAndroid Build Coastguard Worker #endif
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker 
PseudoTcp(IPseudoTcpNotify * notify,uint32_t conv)210*d9f75844SAndroid Build Coastguard Worker PseudoTcp::PseudoTcp(IPseudoTcpNotify* notify, uint32_t conv)
211*d9f75844SAndroid Build Coastguard Worker     : m_notify(notify),
212*d9f75844SAndroid Build Coastguard Worker       m_shutdown(SD_NONE),
213*d9f75844SAndroid Build Coastguard Worker       m_error(0),
214*d9f75844SAndroid Build Coastguard Worker       m_rbuf_len(DEFAULT_RCV_BUF_SIZE),
215*d9f75844SAndroid Build Coastguard Worker       m_rbuf(m_rbuf_len),
216*d9f75844SAndroid Build Coastguard Worker       m_sbuf_len(DEFAULT_SND_BUF_SIZE),
217*d9f75844SAndroid Build Coastguard Worker       m_sbuf(m_sbuf_len) {
218*d9f75844SAndroid Build Coastguard Worker   // Sanity check on buffer sizes (needed for OnTcpWriteable notification logic)
219*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(m_rbuf_len + MIN_PACKET < m_sbuf_len);
220*d9f75844SAndroid Build Coastguard Worker 
221*d9f75844SAndroid Build Coastguard Worker   uint32_t now = Now();
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker   m_state = TCP_LISTEN;
224*d9f75844SAndroid Build Coastguard Worker   m_conv = conv;
225*d9f75844SAndroid Build Coastguard Worker   m_rcv_wnd = m_rbuf_len;
226*d9f75844SAndroid Build Coastguard Worker   m_rwnd_scale = m_swnd_scale = 0;
227*d9f75844SAndroid Build Coastguard Worker   m_snd_nxt = 0;
228*d9f75844SAndroid Build Coastguard Worker   m_snd_wnd = 1;
229*d9f75844SAndroid Build Coastguard Worker   m_snd_una = m_rcv_nxt = 0;
230*d9f75844SAndroid Build Coastguard Worker   m_bReadEnable = true;
231*d9f75844SAndroid Build Coastguard Worker   m_bWriteEnable = false;
232*d9f75844SAndroid Build Coastguard Worker   m_t_ack = 0;
233*d9f75844SAndroid Build Coastguard Worker 
234*d9f75844SAndroid Build Coastguard Worker   m_msslevel = 0;
235*d9f75844SAndroid Build Coastguard Worker   m_largest = 0;
236*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(MIN_PACKET > PACKET_OVERHEAD);
237*d9f75844SAndroid Build Coastguard Worker   m_mss = MIN_PACKET - PACKET_OVERHEAD;
238*d9f75844SAndroid Build Coastguard Worker   m_mtu_advise = MAX_PACKET;
239*d9f75844SAndroid Build Coastguard Worker 
240*d9f75844SAndroid Build Coastguard Worker   m_rto_base = 0;
241*d9f75844SAndroid Build Coastguard Worker 
242*d9f75844SAndroid Build Coastguard Worker   m_cwnd = 2 * m_mss;
243*d9f75844SAndroid Build Coastguard Worker   m_ssthresh = m_rbuf_len;
244*d9f75844SAndroid Build Coastguard Worker   m_lastrecv = m_lastsend = m_lasttraffic = now;
245*d9f75844SAndroid Build Coastguard Worker   m_bOutgoing = false;
246*d9f75844SAndroid Build Coastguard Worker 
247*d9f75844SAndroid Build Coastguard Worker   m_dup_acks = 0;
248*d9f75844SAndroid Build Coastguard Worker   m_recover = 0;
249*d9f75844SAndroid Build Coastguard Worker 
250*d9f75844SAndroid Build Coastguard Worker   m_ts_recent = m_ts_lastack = 0;
251*d9f75844SAndroid Build Coastguard Worker 
252*d9f75844SAndroid Build Coastguard Worker   m_rx_rto = DEF_RTO;
253*d9f75844SAndroid Build Coastguard Worker   m_rx_srtt = m_rx_rttvar = 0;
254*d9f75844SAndroid Build Coastguard Worker 
255*d9f75844SAndroid Build Coastguard Worker   m_use_nagling = true;
256*d9f75844SAndroid Build Coastguard Worker   m_ack_delay = DEF_ACK_DELAY;
257*d9f75844SAndroid Build Coastguard Worker   m_support_wnd_scale = true;
258*d9f75844SAndroid Build Coastguard Worker }
259*d9f75844SAndroid Build Coastguard Worker 
~PseudoTcp()260*d9f75844SAndroid Build Coastguard Worker PseudoTcp::~PseudoTcp() {}
261*d9f75844SAndroid Build Coastguard Worker 
Connect()262*d9f75844SAndroid Build Coastguard Worker int PseudoTcp::Connect() {
263*d9f75844SAndroid Build Coastguard Worker   if (m_state != TCP_LISTEN) {
264*d9f75844SAndroid Build Coastguard Worker     m_error = EINVAL;
265*d9f75844SAndroid Build Coastguard Worker     return -1;
266*d9f75844SAndroid Build Coastguard Worker   }
267*d9f75844SAndroid Build Coastguard Worker 
268*d9f75844SAndroid Build Coastguard Worker   m_state = TCP_SYN_SENT;
269*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "State: TCP_SYN_SENT";
270*d9f75844SAndroid Build Coastguard Worker 
271*d9f75844SAndroid Build Coastguard Worker   queueConnectMessage();
272*d9f75844SAndroid Build Coastguard Worker   attemptSend();
273*d9f75844SAndroid Build Coastguard Worker 
274*d9f75844SAndroid Build Coastguard Worker   return 0;
275*d9f75844SAndroid Build Coastguard Worker }
276*d9f75844SAndroid Build Coastguard Worker 
NotifyMTU(uint16_t mtu)277*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::NotifyMTU(uint16_t mtu) {
278*d9f75844SAndroid Build Coastguard Worker   m_mtu_advise = mtu;
279*d9f75844SAndroid Build Coastguard Worker   if (m_state == TCP_ESTABLISHED) {
280*d9f75844SAndroid Build Coastguard Worker     adjustMTU();
281*d9f75844SAndroid Build Coastguard Worker   }
282*d9f75844SAndroid Build Coastguard Worker }
283*d9f75844SAndroid Build Coastguard Worker 
NotifyClock(uint32_t now)284*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::NotifyClock(uint32_t now) {
285*d9f75844SAndroid Build Coastguard Worker   if (m_state == TCP_CLOSED)
286*d9f75844SAndroid Build Coastguard Worker     return;
287*d9f75844SAndroid Build Coastguard Worker 
288*d9f75844SAndroid Build Coastguard Worker   // Check if it's time to retransmit a segment
289*d9f75844SAndroid Build Coastguard Worker   if (m_rto_base && (rtc::TimeDiff32(m_rto_base + m_rx_rto, now) <= 0)) {
290*d9f75844SAndroid Build Coastguard Worker     if (m_slist.empty()) {
291*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
292*d9f75844SAndroid Build Coastguard Worker     } else {
293*d9f75844SAndroid Build Coastguard Worker // Note: (m_slist.front().xmit == 0)) {
294*d9f75844SAndroid Build Coastguard Worker // retransmit segments
295*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
296*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << "timeout retransmit (rto: " << m_rx_rto
297*d9f75844SAndroid Build Coastguard Worker                        << ") (rto_base: " << m_rto_base << ") (now: " << now
298*d9f75844SAndroid Build Coastguard Worker                        << ") (dup_acks: " << static_cast<unsigned>(m_dup_acks)
299*d9f75844SAndroid Build Coastguard Worker                        << ")";
300*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
301*d9f75844SAndroid Build Coastguard Worker       if (!transmit(m_slist.begin(), now)) {
302*d9f75844SAndroid Build Coastguard Worker         closedown(ECONNABORTED);
303*d9f75844SAndroid Build Coastguard Worker         return;
304*d9f75844SAndroid Build Coastguard Worker       }
305*d9f75844SAndroid Build Coastguard Worker 
306*d9f75844SAndroid Build Coastguard Worker       uint32_t nInFlight = m_snd_nxt - m_snd_una;
307*d9f75844SAndroid Build Coastguard Worker       m_ssthresh = std::max(nInFlight / 2, 2 * m_mss);
308*d9f75844SAndroid Build Coastguard Worker       // RTC_LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << "  nInFlight: " <<
309*d9f75844SAndroid Build Coastguard Worker       // nInFlight << "  m_mss: " << m_mss;
310*d9f75844SAndroid Build Coastguard Worker       m_cwnd = m_mss;
311*d9f75844SAndroid Build Coastguard Worker 
312*d9f75844SAndroid Build Coastguard Worker       // Back off retransmit timer.  Note: the limit is lower when connecting.
313*d9f75844SAndroid Build Coastguard Worker       uint32_t rto_limit = (m_state < TCP_ESTABLISHED) ? DEF_RTO : MAX_RTO;
314*d9f75844SAndroid Build Coastguard Worker       m_rx_rto = std::min(rto_limit, m_rx_rto * 2);
315*d9f75844SAndroid Build Coastguard Worker       m_rto_base = now;
316*d9f75844SAndroid Build Coastguard Worker     }
317*d9f75844SAndroid Build Coastguard Worker   }
318*d9f75844SAndroid Build Coastguard Worker 
319*d9f75844SAndroid Build Coastguard Worker   // Check if it's time to probe closed windows
320*d9f75844SAndroid Build Coastguard Worker   if ((m_snd_wnd == 0) && (rtc::TimeDiff32(m_lastsend + m_rx_rto, now) <= 0)) {
321*d9f75844SAndroid Build Coastguard Worker     if (rtc::TimeDiff32(now, m_lastrecv) >= 15000) {
322*d9f75844SAndroid Build Coastguard Worker       closedown(ECONNABORTED);
323*d9f75844SAndroid Build Coastguard Worker       return;
324*d9f75844SAndroid Build Coastguard Worker     }
325*d9f75844SAndroid Build Coastguard Worker 
326*d9f75844SAndroid Build Coastguard Worker     // probe the window
327*d9f75844SAndroid Build Coastguard Worker     packet(m_snd_nxt - 1, 0, 0, 0);
328*d9f75844SAndroid Build Coastguard Worker     m_lastsend = now;
329*d9f75844SAndroid Build Coastguard Worker 
330*d9f75844SAndroid Build Coastguard Worker     // back off retransmit timer
331*d9f75844SAndroid Build Coastguard Worker     m_rx_rto = std::min(MAX_RTO, m_rx_rto * 2);
332*d9f75844SAndroid Build Coastguard Worker   }
333*d9f75844SAndroid Build Coastguard Worker 
334*d9f75844SAndroid Build Coastguard Worker   // Check if it's time to send delayed acks
335*d9f75844SAndroid Build Coastguard Worker   if (m_t_ack && (rtc::TimeDiff32(m_t_ack + m_ack_delay, now) <= 0)) {
336*d9f75844SAndroid Build Coastguard Worker     packet(m_snd_nxt, 0, 0, 0);
337*d9f75844SAndroid Build Coastguard Worker   }
338*d9f75844SAndroid Build Coastguard Worker 
339*d9f75844SAndroid Build Coastguard Worker #if PSEUDO_KEEPALIVE
340*d9f75844SAndroid Build Coastguard Worker   // Check for idle timeout
341*d9f75844SAndroid Build Coastguard Worker   if ((m_state == TCP_ESTABLISHED) &&
342*d9f75844SAndroid Build Coastguard Worker       (TimeDiff32(m_lastrecv + IDLE_TIMEOUT, now) <= 0)) {
343*d9f75844SAndroid Build Coastguard Worker     closedown(ECONNABORTED);
344*d9f75844SAndroid Build Coastguard Worker     return;
345*d9f75844SAndroid Build Coastguard Worker   }
346*d9f75844SAndroid Build Coastguard Worker 
347*d9f75844SAndroid Build Coastguard Worker   // Check for ping timeout (to keep udp mapping open)
348*d9f75844SAndroid Build Coastguard Worker   if ((m_state == TCP_ESTABLISHED) &&
349*d9f75844SAndroid Build Coastguard Worker       (TimeDiff32(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3 / 2 : IDLE_PING),
350*d9f75844SAndroid Build Coastguard Worker                   now) <= 0)) {
351*d9f75844SAndroid Build Coastguard Worker     packet(m_snd_nxt, 0, 0, 0);
352*d9f75844SAndroid Build Coastguard Worker   }
353*d9f75844SAndroid Build Coastguard Worker #endif  // PSEUDO_KEEPALIVE
354*d9f75844SAndroid Build Coastguard Worker }
355*d9f75844SAndroid Build Coastguard Worker 
NotifyPacket(const char * buffer,size_t len)356*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::NotifyPacket(const char* buffer, size_t len) {
357*d9f75844SAndroid Build Coastguard Worker   if (len > MAX_PACKET) {
358*d9f75844SAndroid Build Coastguard Worker     RTC_LOG_F(LS_WARNING) << "packet too large";
359*d9f75844SAndroid Build Coastguard Worker     return false;
360*d9f75844SAndroid Build Coastguard Worker   }
361*d9f75844SAndroid Build Coastguard Worker   return parse(reinterpret_cast<const uint8_t*>(buffer), uint32_t(len));
362*d9f75844SAndroid Build Coastguard Worker }
363*d9f75844SAndroid Build Coastguard Worker 
GetNextClock(uint32_t now,long & timeout)364*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::GetNextClock(uint32_t now, long& timeout) {
365*d9f75844SAndroid Build Coastguard Worker   return clock_check(now, timeout);
366*d9f75844SAndroid Build Coastguard Worker }
367*d9f75844SAndroid Build Coastguard Worker 
GetOption(Option opt,int * value)368*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::GetOption(Option opt, int* value) {
369*d9f75844SAndroid Build Coastguard Worker   if (opt == OPT_NODELAY) {
370*d9f75844SAndroid Build Coastguard Worker     *value = m_use_nagling ? 0 : 1;
371*d9f75844SAndroid Build Coastguard Worker   } else if (opt == OPT_ACKDELAY) {
372*d9f75844SAndroid Build Coastguard Worker     *value = m_ack_delay;
373*d9f75844SAndroid Build Coastguard Worker   } else if (opt == OPT_SNDBUF) {
374*d9f75844SAndroid Build Coastguard Worker     *value = m_sbuf_len;
375*d9f75844SAndroid Build Coastguard Worker   } else if (opt == OPT_RCVBUF) {
376*d9f75844SAndroid Build Coastguard Worker     *value = m_rbuf_len;
377*d9f75844SAndroid Build Coastguard Worker   } else {
378*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_NOTREACHED();
379*d9f75844SAndroid Build Coastguard Worker   }
380*d9f75844SAndroid Build Coastguard Worker }
SetOption(Option opt,int value)381*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::SetOption(Option opt, int value) {
382*d9f75844SAndroid Build Coastguard Worker   if (opt == OPT_NODELAY) {
383*d9f75844SAndroid Build Coastguard Worker     m_use_nagling = value == 0;
384*d9f75844SAndroid Build Coastguard Worker   } else if (opt == OPT_ACKDELAY) {
385*d9f75844SAndroid Build Coastguard Worker     m_ack_delay = value;
386*d9f75844SAndroid Build Coastguard Worker   } else if (opt == OPT_SNDBUF) {
387*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(m_state == TCP_LISTEN);
388*d9f75844SAndroid Build Coastguard Worker     resizeSendBuffer(value);
389*d9f75844SAndroid Build Coastguard Worker   } else if (opt == OPT_RCVBUF) {
390*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(m_state == TCP_LISTEN);
391*d9f75844SAndroid Build Coastguard Worker     resizeReceiveBuffer(value);
392*d9f75844SAndroid Build Coastguard Worker   } else {
393*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_NOTREACHED();
394*d9f75844SAndroid Build Coastguard Worker   }
395*d9f75844SAndroid Build Coastguard Worker }
396*d9f75844SAndroid Build Coastguard Worker 
GetCongestionWindow() const397*d9f75844SAndroid Build Coastguard Worker uint32_t PseudoTcp::GetCongestionWindow() const {
398*d9f75844SAndroid Build Coastguard Worker   return m_cwnd;
399*d9f75844SAndroid Build Coastguard Worker }
400*d9f75844SAndroid Build Coastguard Worker 
GetBytesInFlight() const401*d9f75844SAndroid Build Coastguard Worker uint32_t PseudoTcp::GetBytesInFlight() const {
402*d9f75844SAndroid Build Coastguard Worker   return m_snd_nxt - m_snd_una;
403*d9f75844SAndroid Build Coastguard Worker }
404*d9f75844SAndroid Build Coastguard Worker 
GetBytesBufferedNotSent() const405*d9f75844SAndroid Build Coastguard Worker uint32_t PseudoTcp::GetBytesBufferedNotSent() const {
406*d9f75844SAndroid Build Coastguard Worker   return static_cast<uint32_t>(m_snd_una + m_sbuf.GetBuffered() - m_snd_nxt);
407*d9f75844SAndroid Build Coastguard Worker }
408*d9f75844SAndroid Build Coastguard Worker 
GetRoundTripTimeEstimateMs() const409*d9f75844SAndroid Build Coastguard Worker uint32_t PseudoTcp::GetRoundTripTimeEstimateMs() const {
410*d9f75844SAndroid Build Coastguard Worker   return m_rx_srtt;
411*d9f75844SAndroid Build Coastguard Worker }
412*d9f75844SAndroid Build Coastguard Worker 
413*d9f75844SAndroid Build Coastguard Worker //
414*d9f75844SAndroid Build Coastguard Worker // IPStream Implementation
415*d9f75844SAndroid Build Coastguard Worker //
416*d9f75844SAndroid Build Coastguard Worker 
Recv(char * buffer,size_t len)417*d9f75844SAndroid Build Coastguard Worker int PseudoTcp::Recv(char* buffer, size_t len) {
418*d9f75844SAndroid Build Coastguard Worker   if (m_state != TCP_ESTABLISHED) {
419*d9f75844SAndroid Build Coastguard Worker     m_error = ENOTCONN;
420*d9f75844SAndroid Build Coastguard Worker     return SOCKET_ERROR;
421*d9f75844SAndroid Build Coastguard Worker   }
422*d9f75844SAndroid Build Coastguard Worker 
423*d9f75844SAndroid Build Coastguard Worker   size_t read = 0;
424*d9f75844SAndroid Build Coastguard Worker   if (!m_rbuf.Read(buffer, len, &read)) {
425*d9f75844SAndroid Build Coastguard Worker     m_bReadEnable = true;
426*d9f75844SAndroid Build Coastguard Worker     m_error = EWOULDBLOCK;
427*d9f75844SAndroid Build Coastguard Worker     return SOCKET_ERROR;
428*d9f75844SAndroid Build Coastguard Worker   }
429*d9f75844SAndroid Build Coastguard Worker 
430*d9f75844SAndroid Build Coastguard Worker   size_t available_space = 0;
431*d9f75844SAndroid Build Coastguard Worker   m_rbuf.GetWriteRemaining(&available_space);
432*d9f75844SAndroid Build Coastguard Worker 
433*d9f75844SAndroid Build Coastguard Worker   if (uint32_t(available_space) - m_rcv_wnd >=
434*d9f75844SAndroid Build Coastguard Worker       std::min<uint32_t>(m_rbuf_len / 2, m_mss)) {
435*d9f75844SAndroid Build Coastguard Worker     // TODO(jbeda): !?! Not sure about this was closed business
436*d9f75844SAndroid Build Coastguard Worker     bool bWasClosed = (m_rcv_wnd == 0);
437*d9f75844SAndroid Build Coastguard Worker     m_rcv_wnd = static_cast<uint32_t>(available_space);
438*d9f75844SAndroid Build Coastguard Worker 
439*d9f75844SAndroid Build Coastguard Worker     if (bWasClosed) {
440*d9f75844SAndroid Build Coastguard Worker       attemptSend(sfImmediateAck);
441*d9f75844SAndroid Build Coastguard Worker     }
442*d9f75844SAndroid Build Coastguard Worker   }
443*d9f75844SAndroid Build Coastguard Worker 
444*d9f75844SAndroid Build Coastguard Worker   return static_cast<int>(read);
445*d9f75844SAndroid Build Coastguard Worker }
446*d9f75844SAndroid Build Coastguard Worker 
Send(const char * buffer,size_t len)447*d9f75844SAndroid Build Coastguard Worker int PseudoTcp::Send(const char* buffer, size_t len) {
448*d9f75844SAndroid Build Coastguard Worker   if (m_state != TCP_ESTABLISHED) {
449*d9f75844SAndroid Build Coastguard Worker     m_error = ENOTCONN;
450*d9f75844SAndroid Build Coastguard Worker     return SOCKET_ERROR;
451*d9f75844SAndroid Build Coastguard Worker   }
452*d9f75844SAndroid Build Coastguard Worker 
453*d9f75844SAndroid Build Coastguard Worker   size_t available_space = 0;
454*d9f75844SAndroid Build Coastguard Worker   m_sbuf.GetWriteRemaining(&available_space);
455*d9f75844SAndroid Build Coastguard Worker 
456*d9f75844SAndroid Build Coastguard Worker   if (!available_space) {
457*d9f75844SAndroid Build Coastguard Worker     m_bWriteEnable = true;
458*d9f75844SAndroid Build Coastguard Worker     m_error = EWOULDBLOCK;
459*d9f75844SAndroid Build Coastguard Worker     return SOCKET_ERROR;
460*d9f75844SAndroid Build Coastguard Worker   }
461*d9f75844SAndroid Build Coastguard Worker 
462*d9f75844SAndroid Build Coastguard Worker   int written = queue(buffer, uint32_t(len), false);
463*d9f75844SAndroid Build Coastguard Worker   attemptSend();
464*d9f75844SAndroid Build Coastguard Worker   return written;
465*d9f75844SAndroid Build Coastguard Worker }
466*d9f75844SAndroid Build Coastguard Worker 
Close(bool force)467*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::Close(bool force) {
468*d9f75844SAndroid Build Coastguard Worker   RTC_LOG_F(LS_VERBOSE) << "(" << (force ? "true" : "false") << ")";
469*d9f75844SAndroid Build Coastguard Worker   m_shutdown = force ? SD_FORCEFUL : SD_GRACEFUL;
470*d9f75844SAndroid Build Coastguard Worker }
471*d9f75844SAndroid Build Coastguard Worker 
GetError()472*d9f75844SAndroid Build Coastguard Worker int PseudoTcp::GetError() {
473*d9f75844SAndroid Build Coastguard Worker   return m_error;
474*d9f75844SAndroid Build Coastguard Worker }
475*d9f75844SAndroid Build Coastguard Worker 
476*d9f75844SAndroid Build Coastguard Worker //
477*d9f75844SAndroid Build Coastguard Worker // Internal Implementation
478*d9f75844SAndroid Build Coastguard Worker //
479*d9f75844SAndroid Build Coastguard Worker 
queue(const char * data,uint32_t len,bool bCtrl)480*d9f75844SAndroid Build Coastguard Worker uint32_t PseudoTcp::queue(const char* data, uint32_t len, bool bCtrl) {
481*d9f75844SAndroid Build Coastguard Worker   size_t available_space = 0;
482*d9f75844SAndroid Build Coastguard Worker   m_sbuf.GetWriteRemaining(&available_space);
483*d9f75844SAndroid Build Coastguard Worker 
484*d9f75844SAndroid Build Coastguard Worker   if (len > static_cast<uint32_t>(available_space)) {
485*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!bCtrl);
486*d9f75844SAndroid Build Coastguard Worker     len = static_cast<uint32_t>(available_space);
487*d9f75844SAndroid Build Coastguard Worker   }
488*d9f75844SAndroid Build Coastguard Worker 
489*d9f75844SAndroid Build Coastguard Worker   // We can concatenate data if the last segment is the same type
490*d9f75844SAndroid Build Coastguard Worker   // (control v. regular data), and has not been transmitted yet
491*d9f75844SAndroid Build Coastguard Worker   if (!m_slist.empty() && (m_slist.back().bCtrl == bCtrl) &&
492*d9f75844SAndroid Build Coastguard Worker       (m_slist.back().xmit == 0)) {
493*d9f75844SAndroid Build Coastguard Worker     m_slist.back().len += len;
494*d9f75844SAndroid Build Coastguard Worker   } else {
495*d9f75844SAndroid Build Coastguard Worker     SSegment sseg(static_cast<uint32_t>(m_snd_una + m_sbuf.GetBuffered()), len,
496*d9f75844SAndroid Build Coastguard Worker                   bCtrl);
497*d9f75844SAndroid Build Coastguard Worker     m_slist.push_back(sseg);
498*d9f75844SAndroid Build Coastguard Worker   }
499*d9f75844SAndroid Build Coastguard Worker 
500*d9f75844SAndroid Build Coastguard Worker   size_t written = 0;
501*d9f75844SAndroid Build Coastguard Worker   m_sbuf.Write(data, len, &written);
502*d9f75844SAndroid Build Coastguard Worker   return static_cast<uint32_t>(written);
503*d9f75844SAndroid Build Coastguard Worker }
504*d9f75844SAndroid Build Coastguard Worker 
packet(uint32_t seq,uint8_t flags,uint32_t offset,uint32_t len)505*d9f75844SAndroid Build Coastguard Worker IPseudoTcpNotify::WriteResult PseudoTcp::packet(uint32_t seq,
506*d9f75844SAndroid Build Coastguard Worker                                                 uint8_t flags,
507*d9f75844SAndroid Build Coastguard Worker                                                 uint32_t offset,
508*d9f75844SAndroid Build Coastguard Worker                                                 uint32_t len) {
509*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(HEADER_SIZE + len <= MAX_PACKET);
510*d9f75844SAndroid Build Coastguard Worker 
511*d9f75844SAndroid Build Coastguard Worker   uint32_t now = Now();
512*d9f75844SAndroid Build Coastguard Worker 
513*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> buffer(new uint8_t[MAX_PACKET]);
514*d9f75844SAndroid Build Coastguard Worker   long_to_bytes(m_conv, buffer.get());
515*d9f75844SAndroid Build Coastguard Worker   long_to_bytes(seq, buffer.get() + 4);
516*d9f75844SAndroid Build Coastguard Worker   long_to_bytes(m_rcv_nxt, buffer.get() + 8);
517*d9f75844SAndroid Build Coastguard Worker   buffer[12] = 0;
518*d9f75844SAndroid Build Coastguard Worker   buffer[13] = flags;
519*d9f75844SAndroid Build Coastguard Worker   short_to_bytes(static_cast<uint16_t>(m_rcv_wnd >> m_rwnd_scale),
520*d9f75844SAndroid Build Coastguard Worker                  buffer.get() + 14);
521*d9f75844SAndroid Build Coastguard Worker 
522*d9f75844SAndroid Build Coastguard Worker   // Timestamp computations
523*d9f75844SAndroid Build Coastguard Worker   long_to_bytes(now, buffer.get() + 16);
524*d9f75844SAndroid Build Coastguard Worker   long_to_bytes(m_ts_recent, buffer.get() + 20);
525*d9f75844SAndroid Build Coastguard Worker   m_ts_lastack = m_rcv_nxt;
526*d9f75844SAndroid Build Coastguard Worker 
527*d9f75844SAndroid Build Coastguard Worker   if (len) {
528*d9f75844SAndroid Build Coastguard Worker     size_t bytes_read = 0;
529*d9f75844SAndroid Build Coastguard Worker     bool result =
530*d9f75844SAndroid Build Coastguard Worker         m_sbuf.ReadOffset(buffer.get() + HEADER_SIZE, len, offset, &bytes_read);
531*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(result);
532*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(static_cast<uint32_t>(bytes_read) == len);
533*d9f75844SAndroid Build Coastguard Worker   }
534*d9f75844SAndroid Build Coastguard Worker 
535*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_VERBOSE
536*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "<-- <CONV=" << m_conv
537*d9f75844SAndroid Build Coastguard Worker                    << "><FLG=" << static_cast<unsigned>(flags)
538*d9f75844SAndroid Build Coastguard Worker                    << "><SEQ=" << seq << ":" << seq + len
539*d9f75844SAndroid Build Coastguard Worker                    << "><ACK=" << m_rcv_nxt << "><WND=" << m_rcv_wnd
540*d9f75844SAndroid Build Coastguard Worker                    << "><TS=" << (now % 10000)
541*d9f75844SAndroid Build Coastguard Worker                    << "><TSR=" << (m_ts_recent % 10000) << "><LEN=" << len
542*d9f75844SAndroid Build Coastguard Worker                    << ">";
543*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
544*d9f75844SAndroid Build Coastguard Worker 
545*d9f75844SAndroid Build Coastguard Worker   IPseudoTcpNotify::WriteResult wres = m_notify->TcpWritePacket(
546*d9f75844SAndroid Build Coastguard Worker       this, reinterpret_cast<char*>(buffer.get()), len + HEADER_SIZE);
547*d9f75844SAndroid Build Coastguard Worker   // Note: When len is 0, this is an ACK packet.  We don't read the return value
548*d9f75844SAndroid Build Coastguard Worker   // for those, and thus we won't retry.  So go ahead and treat the packet as a
549*d9f75844SAndroid Build Coastguard Worker   // success (basically simulate as if it were dropped), which will prevent our
550*d9f75844SAndroid Build Coastguard Worker   // timers from being messed up.
551*d9f75844SAndroid Build Coastguard Worker   if ((wres != IPseudoTcpNotify::WR_SUCCESS) && (0 != len))
552*d9f75844SAndroid Build Coastguard Worker     return wres;
553*d9f75844SAndroid Build Coastguard Worker 
554*d9f75844SAndroid Build Coastguard Worker   m_t_ack = 0;
555*d9f75844SAndroid Build Coastguard Worker   if (len > 0) {
556*d9f75844SAndroid Build Coastguard Worker     m_lastsend = now;
557*d9f75844SAndroid Build Coastguard Worker   }
558*d9f75844SAndroid Build Coastguard Worker   m_lasttraffic = now;
559*d9f75844SAndroid Build Coastguard Worker   m_bOutgoing = true;
560*d9f75844SAndroid Build Coastguard Worker 
561*d9f75844SAndroid Build Coastguard Worker   return IPseudoTcpNotify::WR_SUCCESS;
562*d9f75844SAndroid Build Coastguard Worker }
563*d9f75844SAndroid Build Coastguard Worker 
parse(const uint8_t * buffer,uint32_t size)564*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::parse(const uint8_t* buffer, uint32_t size) {
565*d9f75844SAndroid Build Coastguard Worker   if (size < HEADER_SIZE)
566*d9f75844SAndroid Build Coastguard Worker     return false;
567*d9f75844SAndroid Build Coastguard Worker 
568*d9f75844SAndroid Build Coastguard Worker   Segment seg;
569*d9f75844SAndroid Build Coastguard Worker   seg.conv = bytes_to_long(buffer);
570*d9f75844SAndroid Build Coastguard Worker   seg.seq = bytes_to_long(buffer + 4);
571*d9f75844SAndroid Build Coastguard Worker   seg.ack = bytes_to_long(buffer + 8);
572*d9f75844SAndroid Build Coastguard Worker   seg.flags = buffer[13];
573*d9f75844SAndroid Build Coastguard Worker   seg.wnd = bytes_to_short(buffer + 14);
574*d9f75844SAndroid Build Coastguard Worker 
575*d9f75844SAndroid Build Coastguard Worker   seg.tsval = bytes_to_long(buffer + 16);
576*d9f75844SAndroid Build Coastguard Worker   seg.tsecr = bytes_to_long(buffer + 20);
577*d9f75844SAndroid Build Coastguard Worker 
578*d9f75844SAndroid Build Coastguard Worker   seg.data = reinterpret_cast<const char*>(buffer) + HEADER_SIZE;
579*d9f75844SAndroid Build Coastguard Worker   seg.len = size - HEADER_SIZE;
580*d9f75844SAndroid Build Coastguard Worker 
581*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_VERBOSE
582*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "--> <CONV=" << seg.conv
583*d9f75844SAndroid Build Coastguard Worker                    << "><FLG=" << static_cast<unsigned>(seg.flags)
584*d9f75844SAndroid Build Coastguard Worker                    << "><SEQ=" << seg.seq << ":" << seg.seq + seg.len
585*d9f75844SAndroid Build Coastguard Worker                    << "><ACK=" << seg.ack << "><WND=" << seg.wnd
586*d9f75844SAndroid Build Coastguard Worker                    << "><TS=" << (seg.tsval % 10000)
587*d9f75844SAndroid Build Coastguard Worker                    << "><TSR=" << (seg.tsecr % 10000) << "><LEN=" << seg.len
588*d9f75844SAndroid Build Coastguard Worker                    << ">";
589*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
590*d9f75844SAndroid Build Coastguard Worker 
591*d9f75844SAndroid Build Coastguard Worker   return process(seg);
592*d9f75844SAndroid Build Coastguard Worker }
593*d9f75844SAndroid Build Coastguard Worker 
clock_check(uint32_t now,long & nTimeout)594*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::clock_check(uint32_t now, long& nTimeout) {
595*d9f75844SAndroid Build Coastguard Worker   if (m_shutdown == SD_FORCEFUL)
596*d9f75844SAndroid Build Coastguard Worker     return false;
597*d9f75844SAndroid Build Coastguard Worker 
598*d9f75844SAndroid Build Coastguard Worker   if ((m_shutdown == SD_GRACEFUL) &&
599*d9f75844SAndroid Build Coastguard Worker       ((m_state != TCP_ESTABLISHED) ||
600*d9f75844SAndroid Build Coastguard Worker        ((m_sbuf.GetBuffered() == 0) && (m_t_ack == 0)))) {
601*d9f75844SAndroid Build Coastguard Worker     return false;
602*d9f75844SAndroid Build Coastguard Worker   }
603*d9f75844SAndroid Build Coastguard Worker 
604*d9f75844SAndroid Build Coastguard Worker   if (m_state == TCP_CLOSED) {
605*d9f75844SAndroid Build Coastguard Worker     nTimeout = CLOSED_TIMEOUT;
606*d9f75844SAndroid Build Coastguard Worker     return true;
607*d9f75844SAndroid Build Coastguard Worker   }
608*d9f75844SAndroid Build Coastguard Worker 
609*d9f75844SAndroid Build Coastguard Worker   nTimeout = DEFAULT_TIMEOUT;
610*d9f75844SAndroid Build Coastguard Worker 
611*d9f75844SAndroid Build Coastguard Worker   if (m_t_ack) {
612*d9f75844SAndroid Build Coastguard Worker     nTimeout = std::min<int32_t>(nTimeout,
613*d9f75844SAndroid Build Coastguard Worker                                  rtc::TimeDiff32(m_t_ack + m_ack_delay, now));
614*d9f75844SAndroid Build Coastguard Worker   }
615*d9f75844SAndroid Build Coastguard Worker   if (m_rto_base) {
616*d9f75844SAndroid Build Coastguard Worker     nTimeout = std::min<int32_t>(nTimeout,
617*d9f75844SAndroid Build Coastguard Worker                                  rtc::TimeDiff32(m_rto_base + m_rx_rto, now));
618*d9f75844SAndroid Build Coastguard Worker   }
619*d9f75844SAndroid Build Coastguard Worker   if (m_snd_wnd == 0) {
620*d9f75844SAndroid Build Coastguard Worker     nTimeout = std::min<int32_t>(nTimeout,
621*d9f75844SAndroid Build Coastguard Worker                                  rtc::TimeDiff32(m_lastsend + m_rx_rto, now));
622*d9f75844SAndroid Build Coastguard Worker   }
623*d9f75844SAndroid Build Coastguard Worker #if PSEUDO_KEEPALIVE
624*d9f75844SAndroid Build Coastguard Worker   if (m_state == TCP_ESTABLISHED) {
625*d9f75844SAndroid Build Coastguard Worker     nTimeout = std::min<int32_t>(
626*d9f75844SAndroid Build Coastguard Worker         nTimeout,
627*d9f75844SAndroid Build Coastguard Worker         rtc::TimeDiff32(
628*d9f75844SAndroid Build Coastguard Worker             m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3 / 2 : IDLE_PING),
629*d9f75844SAndroid Build Coastguard Worker             now));
630*d9f75844SAndroid Build Coastguard Worker   }
631*d9f75844SAndroid Build Coastguard Worker #endif  // PSEUDO_KEEPALIVE
632*d9f75844SAndroid Build Coastguard Worker   return true;
633*d9f75844SAndroid Build Coastguard Worker }
634*d9f75844SAndroid Build Coastguard Worker 
process(Segment & seg)635*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::process(Segment& seg) {
636*d9f75844SAndroid Build Coastguard Worker   // If this is the wrong conversation, send a reset!?! (with the correct
637*d9f75844SAndroid Build Coastguard Worker   // conversation?)
638*d9f75844SAndroid Build Coastguard Worker   if (seg.conv != m_conv) {
639*d9f75844SAndroid Build Coastguard Worker     // if ((seg.flags & FLAG_RST) == 0) {
640*d9f75844SAndroid Build Coastguard Worker     //  packet(tcb, seg.ack, 0, FLAG_RST, 0, 0);
641*d9f75844SAndroid Build Coastguard Worker     //}
642*d9f75844SAndroid Build Coastguard Worker     RTC_LOG_F(LS_ERROR) << "wrong conversation";
643*d9f75844SAndroid Build Coastguard Worker     return false;
644*d9f75844SAndroid Build Coastguard Worker   }
645*d9f75844SAndroid Build Coastguard Worker 
646*d9f75844SAndroid Build Coastguard Worker   uint32_t now = Now();
647*d9f75844SAndroid Build Coastguard Worker   m_lasttraffic = m_lastrecv = now;
648*d9f75844SAndroid Build Coastguard Worker   m_bOutgoing = false;
649*d9f75844SAndroid Build Coastguard Worker 
650*d9f75844SAndroid Build Coastguard Worker   if (m_state == TCP_CLOSED) {
651*d9f75844SAndroid Build Coastguard Worker     // !?! send reset?
652*d9f75844SAndroid Build Coastguard Worker     RTC_LOG_F(LS_ERROR) << "closed";
653*d9f75844SAndroid Build Coastguard Worker     return false;
654*d9f75844SAndroid Build Coastguard Worker   }
655*d9f75844SAndroid Build Coastguard Worker 
656*d9f75844SAndroid Build Coastguard Worker   // Check if this is a reset segment
657*d9f75844SAndroid Build Coastguard Worker   if (seg.flags & FLAG_RST) {
658*d9f75844SAndroid Build Coastguard Worker     closedown(ECONNRESET);
659*d9f75844SAndroid Build Coastguard Worker     return false;
660*d9f75844SAndroid Build Coastguard Worker   }
661*d9f75844SAndroid Build Coastguard Worker 
662*d9f75844SAndroid Build Coastguard Worker   // Check for control data
663*d9f75844SAndroid Build Coastguard Worker   bool bConnect = false;
664*d9f75844SAndroid Build Coastguard Worker   if (seg.flags & FLAG_CTL) {
665*d9f75844SAndroid Build Coastguard Worker     if (seg.len == 0) {
666*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_ERROR) << "Missing control code";
667*d9f75844SAndroid Build Coastguard Worker       return false;
668*d9f75844SAndroid Build Coastguard Worker     } else if (seg.data[0] == CTL_CONNECT) {
669*d9f75844SAndroid Build Coastguard Worker       bConnect = true;
670*d9f75844SAndroid Build Coastguard Worker 
671*d9f75844SAndroid Build Coastguard Worker       // TCP options are in the remainder of the payload after CTL_CONNECT.
672*d9f75844SAndroid Build Coastguard Worker       parseOptions(&seg.data[1], seg.len - 1);
673*d9f75844SAndroid Build Coastguard Worker 
674*d9f75844SAndroid Build Coastguard Worker       if (m_state == TCP_LISTEN) {
675*d9f75844SAndroid Build Coastguard Worker         m_state = TCP_SYN_RECEIVED;
676*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "State: TCP_SYN_RECEIVED";
677*d9f75844SAndroid Build Coastguard Worker         // m_notify->associate(addr);
678*d9f75844SAndroid Build Coastguard Worker         queueConnectMessage();
679*d9f75844SAndroid Build Coastguard Worker       } else if (m_state == TCP_SYN_SENT) {
680*d9f75844SAndroid Build Coastguard Worker         m_state = TCP_ESTABLISHED;
681*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "State: TCP_ESTABLISHED";
682*d9f75844SAndroid Build Coastguard Worker         adjustMTU();
683*d9f75844SAndroid Build Coastguard Worker         if (m_notify) {
684*d9f75844SAndroid Build Coastguard Worker           m_notify->OnTcpOpen(this);
685*d9f75844SAndroid Build Coastguard Worker         }
686*d9f75844SAndroid Build Coastguard Worker         // notify(evOpen);
687*d9f75844SAndroid Build Coastguard Worker       }
688*d9f75844SAndroid Build Coastguard Worker     } else {
689*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_WARNING) << "Unknown control code: " << seg.data[0];
690*d9f75844SAndroid Build Coastguard Worker       return false;
691*d9f75844SAndroid Build Coastguard Worker     }
692*d9f75844SAndroid Build Coastguard Worker   }
693*d9f75844SAndroid Build Coastguard Worker 
694*d9f75844SAndroid Build Coastguard Worker   // Update timestamp
695*d9f75844SAndroid Build Coastguard Worker   if ((seg.seq <= m_ts_lastack) && (m_ts_lastack < seg.seq + seg.len)) {
696*d9f75844SAndroid Build Coastguard Worker     m_ts_recent = seg.tsval;
697*d9f75844SAndroid Build Coastguard Worker   }
698*d9f75844SAndroid Build Coastguard Worker 
699*d9f75844SAndroid Build Coastguard Worker   // Check if this is a valuable ack
700*d9f75844SAndroid Build Coastguard Worker   if ((seg.ack > m_snd_una) && (seg.ack <= m_snd_nxt)) {
701*d9f75844SAndroid Build Coastguard Worker     // Calculate round-trip time
702*d9f75844SAndroid Build Coastguard Worker     if (seg.tsecr) {
703*d9f75844SAndroid Build Coastguard Worker       int32_t rtt = rtc::TimeDiff32(now, seg.tsecr);
704*d9f75844SAndroid Build Coastguard Worker       if (rtt >= 0) {
705*d9f75844SAndroid Build Coastguard Worker         if (m_rx_srtt == 0) {
706*d9f75844SAndroid Build Coastguard Worker           m_rx_srtt = rtt;
707*d9f75844SAndroid Build Coastguard Worker           m_rx_rttvar = rtt / 2;
708*d9f75844SAndroid Build Coastguard Worker         } else {
709*d9f75844SAndroid Build Coastguard Worker           uint32_t unsigned_rtt = static_cast<uint32_t>(rtt);
710*d9f75844SAndroid Build Coastguard Worker           uint32_t abs_err = unsigned_rtt > m_rx_srtt
711*d9f75844SAndroid Build Coastguard Worker                                  ? unsigned_rtt - m_rx_srtt
712*d9f75844SAndroid Build Coastguard Worker                                  : m_rx_srtt - unsigned_rtt;
713*d9f75844SAndroid Build Coastguard Worker           m_rx_rttvar = (3 * m_rx_rttvar + abs_err) / 4;
714*d9f75844SAndroid Build Coastguard Worker           m_rx_srtt = (7 * m_rx_srtt + rtt) / 8;
715*d9f75844SAndroid Build Coastguard Worker         }
716*d9f75844SAndroid Build Coastguard Worker         m_rx_rto = rtc::SafeClamp(m_rx_srtt + rtc::SafeMax(1, 4 * m_rx_rttvar),
717*d9f75844SAndroid Build Coastguard Worker                                   MIN_RTO, MAX_RTO);
718*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_VERBOSE
719*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "rtt: " << rtt << "  srtt: " << m_rx_srtt
720*d9f75844SAndroid Build Coastguard Worker                          << "  rto: " << m_rx_rto;
721*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
722*d9f75844SAndroid Build Coastguard Worker       } else {
723*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING) << "rtt < 0";
724*d9f75844SAndroid Build Coastguard Worker       }
725*d9f75844SAndroid Build Coastguard Worker     }
726*d9f75844SAndroid Build Coastguard Worker 
727*d9f75844SAndroid Build Coastguard Worker     m_snd_wnd = static_cast<uint32_t>(seg.wnd) << m_swnd_scale;
728*d9f75844SAndroid Build Coastguard Worker 
729*d9f75844SAndroid Build Coastguard Worker     uint32_t nAcked = seg.ack - m_snd_una;
730*d9f75844SAndroid Build Coastguard Worker     m_snd_una = seg.ack;
731*d9f75844SAndroid Build Coastguard Worker 
732*d9f75844SAndroid Build Coastguard Worker     m_rto_base = (m_snd_una == m_snd_nxt) ? 0 : now;
733*d9f75844SAndroid Build Coastguard Worker 
734*d9f75844SAndroid Build Coastguard Worker     m_sbuf.ConsumeReadData(nAcked);
735*d9f75844SAndroid Build Coastguard Worker 
736*d9f75844SAndroid Build Coastguard Worker     for (uint32_t nFree = nAcked; nFree > 0;) {
737*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(!m_slist.empty());
738*d9f75844SAndroid Build Coastguard Worker       if (nFree < m_slist.front().len) {
739*d9f75844SAndroid Build Coastguard Worker         m_slist.front().len -= nFree;
740*d9f75844SAndroid Build Coastguard Worker         nFree = 0;
741*d9f75844SAndroid Build Coastguard Worker       } else {
742*d9f75844SAndroid Build Coastguard Worker         if (m_slist.front().len > m_largest) {
743*d9f75844SAndroid Build Coastguard Worker           m_largest = m_slist.front().len;
744*d9f75844SAndroid Build Coastguard Worker         }
745*d9f75844SAndroid Build Coastguard Worker         nFree -= m_slist.front().len;
746*d9f75844SAndroid Build Coastguard Worker         m_slist.pop_front();
747*d9f75844SAndroid Build Coastguard Worker       }
748*d9f75844SAndroid Build Coastguard Worker     }
749*d9f75844SAndroid Build Coastguard Worker 
750*d9f75844SAndroid Build Coastguard Worker     if (m_dup_acks >= 3) {
751*d9f75844SAndroid Build Coastguard Worker       if (m_snd_una >= m_recover) {  // NewReno
752*d9f75844SAndroid Build Coastguard Worker         uint32_t nInFlight = m_snd_nxt - m_snd_una;
753*d9f75844SAndroid Build Coastguard Worker         m_cwnd = std::min(m_ssthresh, nInFlight + m_mss);  // (Fast Retransmit)
754*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
755*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "exit recovery";
756*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
757*d9f75844SAndroid Build Coastguard Worker         m_dup_acks = 0;
758*d9f75844SAndroid Build Coastguard Worker       } else {
759*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
760*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "recovery retransmit";
761*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
762*d9f75844SAndroid Build Coastguard Worker         if (!transmit(m_slist.begin(), now)) {
763*d9f75844SAndroid Build Coastguard Worker           closedown(ECONNABORTED);
764*d9f75844SAndroid Build Coastguard Worker           return false;
765*d9f75844SAndroid Build Coastguard Worker         }
766*d9f75844SAndroid Build Coastguard Worker         m_cwnd += m_mss - std::min(nAcked, m_cwnd);
767*d9f75844SAndroid Build Coastguard Worker       }
768*d9f75844SAndroid Build Coastguard Worker     } else {
769*d9f75844SAndroid Build Coastguard Worker       m_dup_acks = 0;
770*d9f75844SAndroid Build Coastguard Worker       // Slow start, congestion avoidance
771*d9f75844SAndroid Build Coastguard Worker       if (m_cwnd < m_ssthresh) {
772*d9f75844SAndroid Build Coastguard Worker         m_cwnd += m_mss;
773*d9f75844SAndroid Build Coastguard Worker       } else {
774*d9f75844SAndroid Build Coastguard Worker         m_cwnd += std::max<uint32_t>(1, m_mss * m_mss / m_cwnd);
775*d9f75844SAndroid Build Coastguard Worker       }
776*d9f75844SAndroid Build Coastguard Worker     }
777*d9f75844SAndroid Build Coastguard Worker   } else if (seg.ack == m_snd_una) {
778*d9f75844SAndroid Build Coastguard Worker     // !?! Note, tcp says don't do this... but otherwise how does a closed
779*d9f75844SAndroid Build Coastguard Worker     // window become open?
780*d9f75844SAndroid Build Coastguard Worker     m_snd_wnd = static_cast<uint32_t>(seg.wnd) << m_swnd_scale;
781*d9f75844SAndroid Build Coastguard Worker 
782*d9f75844SAndroid Build Coastguard Worker     // Check duplicate acks
783*d9f75844SAndroid Build Coastguard Worker     if (seg.len > 0) {
784*d9f75844SAndroid Build Coastguard Worker       // it's a dup ack, but with a data payload, so don't modify m_dup_acks
785*d9f75844SAndroid Build Coastguard Worker     } else if (m_snd_una != m_snd_nxt) {
786*d9f75844SAndroid Build Coastguard Worker       m_dup_acks += 1;
787*d9f75844SAndroid Build Coastguard Worker       if (m_dup_acks == 3) {  // (Fast Retransmit)
788*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
789*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "enter recovery";
790*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "recovery retransmit";
791*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
792*d9f75844SAndroid Build Coastguard Worker         if (!transmit(m_slist.begin(), now)) {
793*d9f75844SAndroid Build Coastguard Worker           closedown(ECONNABORTED);
794*d9f75844SAndroid Build Coastguard Worker           return false;
795*d9f75844SAndroid Build Coastguard Worker         }
796*d9f75844SAndroid Build Coastguard Worker         m_recover = m_snd_nxt;
797*d9f75844SAndroid Build Coastguard Worker         uint32_t nInFlight = m_snd_nxt - m_snd_una;
798*d9f75844SAndroid Build Coastguard Worker         m_ssthresh = std::max(nInFlight / 2, 2 * m_mss);
799*d9f75844SAndroid Build Coastguard Worker         // RTC_LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << "  nInFlight: "
800*d9f75844SAndroid Build Coastguard Worker         // << nInFlight << "  m_mss: " << m_mss;
801*d9f75844SAndroid Build Coastguard Worker         m_cwnd = m_ssthresh + 3 * m_mss;
802*d9f75844SAndroid Build Coastguard Worker       } else if (m_dup_acks > 3) {
803*d9f75844SAndroid Build Coastguard Worker         m_cwnd += m_mss;
804*d9f75844SAndroid Build Coastguard Worker       }
805*d9f75844SAndroid Build Coastguard Worker     } else {
806*d9f75844SAndroid Build Coastguard Worker       m_dup_acks = 0;
807*d9f75844SAndroid Build Coastguard Worker     }
808*d9f75844SAndroid Build Coastguard Worker   }
809*d9f75844SAndroid Build Coastguard Worker 
810*d9f75844SAndroid Build Coastguard Worker   // !?! A bit hacky
811*d9f75844SAndroid Build Coastguard Worker   if ((m_state == TCP_SYN_RECEIVED) && !bConnect) {
812*d9f75844SAndroid Build Coastguard Worker     m_state = TCP_ESTABLISHED;
813*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << "State: TCP_ESTABLISHED";
814*d9f75844SAndroid Build Coastguard Worker     adjustMTU();
815*d9f75844SAndroid Build Coastguard Worker     if (m_notify) {
816*d9f75844SAndroid Build Coastguard Worker       m_notify->OnTcpOpen(this);
817*d9f75844SAndroid Build Coastguard Worker     }
818*d9f75844SAndroid Build Coastguard Worker     // notify(evOpen);
819*d9f75844SAndroid Build Coastguard Worker   }
820*d9f75844SAndroid Build Coastguard Worker 
821*d9f75844SAndroid Build Coastguard Worker   // If we make room in the send queue, notify the user
822*d9f75844SAndroid Build Coastguard Worker   // The goal it to make sure we always have at least enough data to fill the
823*d9f75844SAndroid Build Coastguard Worker   // window.  We'd like to notify the app when we are halfway to that point.
824*d9f75844SAndroid Build Coastguard Worker   const uint32_t kIdealRefillSize = (m_sbuf_len + m_rbuf_len) / 2;
825*d9f75844SAndroid Build Coastguard Worker   if (m_bWriteEnable &&
826*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(m_sbuf.GetBuffered()) < kIdealRefillSize) {
827*d9f75844SAndroid Build Coastguard Worker     m_bWriteEnable = false;
828*d9f75844SAndroid Build Coastguard Worker     if (m_notify) {
829*d9f75844SAndroid Build Coastguard Worker       m_notify->OnTcpWriteable(this);
830*d9f75844SAndroid Build Coastguard Worker     }
831*d9f75844SAndroid Build Coastguard Worker     // notify(evWrite);
832*d9f75844SAndroid Build Coastguard Worker   }
833*d9f75844SAndroid Build Coastguard Worker 
834*d9f75844SAndroid Build Coastguard Worker   // Conditions were acks must be sent:
835*d9f75844SAndroid Build Coastguard Worker   // 1) Segment is too old (they missed an ACK) (immediately)
836*d9f75844SAndroid Build Coastguard Worker   // 2) Segment is too new (we missed a segment) (immediately)
837*d9f75844SAndroid Build Coastguard Worker   // 3) Segment has data (so we need to ACK!) (delayed)
838*d9f75844SAndroid Build Coastguard Worker   // ... so the only time we don't need to ACK, is an empty segment that points
839*d9f75844SAndroid Build Coastguard Worker   // to rcv_nxt!
840*d9f75844SAndroid Build Coastguard Worker 
841*d9f75844SAndroid Build Coastguard Worker   SendFlags sflags = sfNone;
842*d9f75844SAndroid Build Coastguard Worker   if (seg.seq != m_rcv_nxt) {
843*d9f75844SAndroid Build Coastguard Worker     sflags = sfImmediateAck;  // (Fast Recovery)
844*d9f75844SAndroid Build Coastguard Worker   } else if (seg.len != 0) {
845*d9f75844SAndroid Build Coastguard Worker     if (m_ack_delay == 0) {
846*d9f75844SAndroid Build Coastguard Worker       sflags = sfImmediateAck;
847*d9f75844SAndroid Build Coastguard Worker     } else {
848*d9f75844SAndroid Build Coastguard Worker       sflags = sfDelayedAck;
849*d9f75844SAndroid Build Coastguard Worker     }
850*d9f75844SAndroid Build Coastguard Worker   }
851*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
852*d9f75844SAndroid Build Coastguard Worker   if (sflags == sfImmediateAck) {
853*d9f75844SAndroid Build Coastguard Worker     if (seg.seq > m_rcv_nxt) {
854*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_INFO) << "too new";
855*d9f75844SAndroid Build Coastguard Worker     } else if (seg.seq + seg.len <= m_rcv_nxt) {
856*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_INFO) << "too old";
857*d9f75844SAndroid Build Coastguard Worker     }
858*d9f75844SAndroid Build Coastguard Worker   }
859*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
860*d9f75844SAndroid Build Coastguard Worker 
861*d9f75844SAndroid Build Coastguard Worker   // Adjust the incoming segment to fit our receive buffer
862*d9f75844SAndroid Build Coastguard Worker   if (seg.seq < m_rcv_nxt) {
863*d9f75844SAndroid Build Coastguard Worker     uint32_t nAdjust = m_rcv_nxt - seg.seq;
864*d9f75844SAndroid Build Coastguard Worker     if (nAdjust < seg.len) {
865*d9f75844SAndroid Build Coastguard Worker       seg.seq += nAdjust;
866*d9f75844SAndroid Build Coastguard Worker       seg.data += nAdjust;
867*d9f75844SAndroid Build Coastguard Worker       seg.len -= nAdjust;
868*d9f75844SAndroid Build Coastguard Worker     } else {
869*d9f75844SAndroid Build Coastguard Worker       seg.len = 0;
870*d9f75844SAndroid Build Coastguard Worker     }
871*d9f75844SAndroid Build Coastguard Worker   }
872*d9f75844SAndroid Build Coastguard Worker 
873*d9f75844SAndroid Build Coastguard Worker   size_t available_space = 0;
874*d9f75844SAndroid Build Coastguard Worker   m_rbuf.GetWriteRemaining(&available_space);
875*d9f75844SAndroid Build Coastguard Worker 
876*d9f75844SAndroid Build Coastguard Worker   if ((seg.seq + seg.len - m_rcv_nxt) >
877*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(available_space)) {
878*d9f75844SAndroid Build Coastguard Worker     uint32_t nAdjust =
879*d9f75844SAndroid Build Coastguard Worker         seg.seq + seg.len - m_rcv_nxt - static_cast<uint32_t>(available_space);
880*d9f75844SAndroid Build Coastguard Worker     if (nAdjust < seg.len) {
881*d9f75844SAndroid Build Coastguard Worker       seg.len -= nAdjust;
882*d9f75844SAndroid Build Coastguard Worker     } else {
883*d9f75844SAndroid Build Coastguard Worker       seg.len = 0;
884*d9f75844SAndroid Build Coastguard Worker     }
885*d9f75844SAndroid Build Coastguard Worker   }
886*d9f75844SAndroid Build Coastguard Worker 
887*d9f75844SAndroid Build Coastguard Worker   bool bIgnoreData = (seg.flags & FLAG_CTL) || (m_shutdown != SD_NONE);
888*d9f75844SAndroid Build Coastguard Worker   bool bNewData = false;
889*d9f75844SAndroid Build Coastguard Worker 
890*d9f75844SAndroid Build Coastguard Worker   if (seg.len > 0) {
891*d9f75844SAndroid Build Coastguard Worker     bool bRecover = false;
892*d9f75844SAndroid Build Coastguard Worker     if (bIgnoreData) {
893*d9f75844SAndroid Build Coastguard Worker       if (seg.seq == m_rcv_nxt) {
894*d9f75844SAndroid Build Coastguard Worker         m_rcv_nxt += seg.len;
895*d9f75844SAndroid Build Coastguard Worker         // If we received a data segment out of order relative to a control
896*d9f75844SAndroid Build Coastguard Worker         // segment, then we wrote it into the receive buffer at an offset (see
897*d9f75844SAndroid Build Coastguard Worker         // "WriteOffset") below. So we need to advance the position in the
898*d9f75844SAndroid Build Coastguard Worker         // buffer to avoid corrupting data. See bugs.webrtc.org/9208
899*d9f75844SAndroid Build Coastguard Worker         //
900*d9f75844SAndroid Build Coastguard Worker         // We advance the position in the buffer by N bytes by acting like we
901*d9f75844SAndroid Build Coastguard Worker         // wrote N bytes and then immediately read them. We can only do this if
902*d9f75844SAndroid Build Coastguard Worker         // there's not already data ready to read, but this should always be
903*d9f75844SAndroid Build Coastguard Worker         // true in the problematic scenario, since control frames are always
904*d9f75844SAndroid Build Coastguard Worker         // sent first in the stream.
905*d9f75844SAndroid Build Coastguard Worker         if (m_rbuf.GetBuffered() == 0) {
906*d9f75844SAndroid Build Coastguard Worker           m_rbuf.ConsumeWriteBuffer(seg.len);
907*d9f75844SAndroid Build Coastguard Worker           m_rbuf.ConsumeReadData(seg.len);
908*d9f75844SAndroid Build Coastguard Worker           // After shifting the position in the buffer, we may have
909*d9f75844SAndroid Build Coastguard Worker           // out-of-order packets ready to be recovered.
910*d9f75844SAndroid Build Coastguard Worker           bRecover = true;
911*d9f75844SAndroid Build Coastguard Worker         }
912*d9f75844SAndroid Build Coastguard Worker       }
913*d9f75844SAndroid Build Coastguard Worker     } else {
914*d9f75844SAndroid Build Coastguard Worker       uint32_t nOffset = seg.seq - m_rcv_nxt;
915*d9f75844SAndroid Build Coastguard Worker 
916*d9f75844SAndroid Build Coastguard Worker       if (!m_rbuf.WriteOffset(seg.data, seg.len, nOffset, NULL)) {
917*d9f75844SAndroid Build Coastguard Worker         // Ignore incoming packets outside of the receive window.
918*d9f75844SAndroid Build Coastguard Worker         return false;
919*d9f75844SAndroid Build Coastguard Worker       }
920*d9f75844SAndroid Build Coastguard Worker 
921*d9f75844SAndroid Build Coastguard Worker       if (seg.seq == m_rcv_nxt) {
922*d9f75844SAndroid Build Coastguard Worker         m_rbuf.ConsumeWriteBuffer(seg.len);
923*d9f75844SAndroid Build Coastguard Worker         m_rcv_nxt += seg.len;
924*d9f75844SAndroid Build Coastguard Worker         m_rcv_wnd -= seg.len;
925*d9f75844SAndroid Build Coastguard Worker         bNewData = true;
926*d9f75844SAndroid Build Coastguard Worker         // May be able to recover packets previously received out-of-order
927*d9f75844SAndroid Build Coastguard Worker         // now.
928*d9f75844SAndroid Build Coastguard Worker         bRecover = true;
929*d9f75844SAndroid Build Coastguard Worker       } else {
930*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
931*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "Saving " << seg.len << " bytes (" << seg.seq
932*d9f75844SAndroid Build Coastguard Worker                          << " -> " << seg.seq + seg.len << ")";
933*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
934*d9f75844SAndroid Build Coastguard Worker         RSegment rseg;
935*d9f75844SAndroid Build Coastguard Worker         rseg.seq = seg.seq;
936*d9f75844SAndroid Build Coastguard Worker         rseg.len = seg.len;
937*d9f75844SAndroid Build Coastguard Worker         RList::iterator it = m_rlist.begin();
938*d9f75844SAndroid Build Coastguard Worker         while ((it != m_rlist.end()) && (it->seq < rseg.seq)) {
939*d9f75844SAndroid Build Coastguard Worker           ++it;
940*d9f75844SAndroid Build Coastguard Worker         }
941*d9f75844SAndroid Build Coastguard Worker         m_rlist.insert(it, rseg);
942*d9f75844SAndroid Build Coastguard Worker       }
943*d9f75844SAndroid Build Coastguard Worker     }
944*d9f75844SAndroid Build Coastguard Worker     if (bRecover) {
945*d9f75844SAndroid Build Coastguard Worker       RList::iterator it = m_rlist.begin();
946*d9f75844SAndroid Build Coastguard Worker       while ((it != m_rlist.end()) && (it->seq <= m_rcv_nxt)) {
947*d9f75844SAndroid Build Coastguard Worker         if (it->seq + it->len > m_rcv_nxt) {
948*d9f75844SAndroid Build Coastguard Worker           sflags = sfImmediateAck;  // (Fast Recovery)
949*d9f75844SAndroid Build Coastguard Worker           uint32_t nAdjust = (it->seq + it->len) - m_rcv_nxt;
950*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
951*d9f75844SAndroid Build Coastguard Worker           RTC_LOG(LS_INFO) << "Recovered " << nAdjust << " bytes (" << m_rcv_nxt
952*d9f75844SAndroid Build Coastguard Worker                            << " -> " << m_rcv_nxt + nAdjust << ")";
953*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
954*d9f75844SAndroid Build Coastguard Worker           m_rbuf.ConsumeWriteBuffer(nAdjust);
955*d9f75844SAndroid Build Coastguard Worker           m_rcv_nxt += nAdjust;
956*d9f75844SAndroid Build Coastguard Worker           m_rcv_wnd -= nAdjust;
957*d9f75844SAndroid Build Coastguard Worker           bNewData = true;
958*d9f75844SAndroid Build Coastguard Worker         }
959*d9f75844SAndroid Build Coastguard Worker         it = m_rlist.erase(it);
960*d9f75844SAndroid Build Coastguard Worker       }
961*d9f75844SAndroid Build Coastguard Worker     }
962*d9f75844SAndroid Build Coastguard Worker   }
963*d9f75844SAndroid Build Coastguard Worker 
964*d9f75844SAndroid Build Coastguard Worker   attemptSend(sflags);
965*d9f75844SAndroid Build Coastguard Worker 
966*d9f75844SAndroid Build Coastguard Worker   // If we have new data, notify the user
967*d9f75844SAndroid Build Coastguard Worker   if (bNewData && m_bReadEnable) {
968*d9f75844SAndroid Build Coastguard Worker     m_bReadEnable = false;
969*d9f75844SAndroid Build Coastguard Worker     if (m_notify) {
970*d9f75844SAndroid Build Coastguard Worker       m_notify->OnTcpReadable(this);
971*d9f75844SAndroid Build Coastguard Worker     }
972*d9f75844SAndroid Build Coastguard Worker     // notify(evRead);
973*d9f75844SAndroid Build Coastguard Worker   }
974*d9f75844SAndroid Build Coastguard Worker 
975*d9f75844SAndroid Build Coastguard Worker   return true;
976*d9f75844SAndroid Build Coastguard Worker }
977*d9f75844SAndroid Build Coastguard Worker 
transmit(const SList::iterator & seg,uint32_t now)978*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::transmit(const SList::iterator& seg, uint32_t now) {
979*d9f75844SAndroid Build Coastguard Worker   if (seg->xmit >= ((m_state == TCP_ESTABLISHED) ? 15 : 30)) {
980*d9f75844SAndroid Build Coastguard Worker     RTC_LOG_F(LS_VERBOSE) << "too many retransmits";
981*d9f75844SAndroid Build Coastguard Worker     return false;
982*d9f75844SAndroid Build Coastguard Worker   }
983*d9f75844SAndroid Build Coastguard Worker 
984*d9f75844SAndroid Build Coastguard Worker   uint32_t nTransmit = std::min(seg->len, m_mss);
985*d9f75844SAndroid Build Coastguard Worker 
986*d9f75844SAndroid Build Coastguard Worker   while (true) {
987*d9f75844SAndroid Build Coastguard Worker     uint32_t seq = seg->seq;
988*d9f75844SAndroid Build Coastguard Worker     uint8_t flags = (seg->bCtrl ? FLAG_CTL : 0);
989*d9f75844SAndroid Build Coastguard Worker     IPseudoTcpNotify::WriteResult wres =
990*d9f75844SAndroid Build Coastguard Worker         packet(seq, flags, seg->seq - m_snd_una, nTransmit);
991*d9f75844SAndroid Build Coastguard Worker 
992*d9f75844SAndroid Build Coastguard Worker     if (wres == IPseudoTcpNotify::WR_SUCCESS)
993*d9f75844SAndroid Build Coastguard Worker       break;
994*d9f75844SAndroid Build Coastguard Worker 
995*d9f75844SAndroid Build Coastguard Worker     if (wres == IPseudoTcpNotify::WR_FAIL) {
996*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_VERBOSE) << "packet failed";
997*d9f75844SAndroid Build Coastguard Worker       return false;
998*d9f75844SAndroid Build Coastguard Worker     }
999*d9f75844SAndroid Build Coastguard Worker 
1000*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(wres == IPseudoTcpNotify::WR_TOO_LARGE);
1001*d9f75844SAndroid Build Coastguard Worker 
1002*d9f75844SAndroid Build Coastguard Worker     while (true) {
1003*d9f75844SAndroid Build Coastguard Worker       if (PACKET_MAXIMUMS[m_msslevel + 1] == 0) {
1004*d9f75844SAndroid Build Coastguard Worker         RTC_LOG_F(LS_VERBOSE) << "MTU too small";
1005*d9f75844SAndroid Build Coastguard Worker         return false;
1006*d9f75844SAndroid Build Coastguard Worker       }
1007*d9f75844SAndroid Build Coastguard Worker       // !?! We need to break up all outstanding and pending packets and then
1008*d9f75844SAndroid Build Coastguard Worker       // retransmit!?!
1009*d9f75844SAndroid Build Coastguard Worker 
1010*d9f75844SAndroid Build Coastguard Worker       m_mss = PACKET_MAXIMUMS[++m_msslevel] - PACKET_OVERHEAD;
1011*d9f75844SAndroid Build Coastguard Worker       m_cwnd = 2 * m_mss;  // I added this... haven't researched actual formula
1012*d9f75844SAndroid Build Coastguard Worker       if (m_mss < nTransmit) {
1013*d9f75844SAndroid Build Coastguard Worker         nTransmit = m_mss;
1014*d9f75844SAndroid Build Coastguard Worker         break;
1015*d9f75844SAndroid Build Coastguard Worker       }
1016*d9f75844SAndroid Build Coastguard Worker     }
1017*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
1018*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes";
1019*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
1020*d9f75844SAndroid Build Coastguard Worker   }
1021*d9f75844SAndroid Build Coastguard Worker 
1022*d9f75844SAndroid Build Coastguard Worker   if (nTransmit < seg->len) {
1023*d9f75844SAndroid Build Coastguard Worker     RTC_LOG_F(LS_VERBOSE) << "mss reduced to " << m_mss;
1024*d9f75844SAndroid Build Coastguard Worker 
1025*d9f75844SAndroid Build Coastguard Worker     SSegment subseg(seg->seq + nTransmit, seg->len - nTransmit, seg->bCtrl);
1026*d9f75844SAndroid Build Coastguard Worker     // subseg.tstamp = seg->tstamp;
1027*d9f75844SAndroid Build Coastguard Worker     subseg.xmit = seg->xmit;
1028*d9f75844SAndroid Build Coastguard Worker     seg->len = nTransmit;
1029*d9f75844SAndroid Build Coastguard Worker 
1030*d9f75844SAndroid Build Coastguard Worker     SList::iterator next = seg;
1031*d9f75844SAndroid Build Coastguard Worker     m_slist.insert(++next, subseg);
1032*d9f75844SAndroid Build Coastguard Worker   }
1033*d9f75844SAndroid Build Coastguard Worker 
1034*d9f75844SAndroid Build Coastguard Worker   if (seg->xmit == 0) {
1035*d9f75844SAndroid Build Coastguard Worker     m_snd_nxt += seg->len;
1036*d9f75844SAndroid Build Coastguard Worker   }
1037*d9f75844SAndroid Build Coastguard Worker   seg->xmit += 1;
1038*d9f75844SAndroid Build Coastguard Worker   // seg->tstamp = now;
1039*d9f75844SAndroid Build Coastguard Worker   if (m_rto_base == 0) {
1040*d9f75844SAndroid Build Coastguard Worker     m_rto_base = now;
1041*d9f75844SAndroid Build Coastguard Worker   }
1042*d9f75844SAndroid Build Coastguard Worker 
1043*d9f75844SAndroid Build Coastguard Worker   return true;
1044*d9f75844SAndroid Build Coastguard Worker }
1045*d9f75844SAndroid Build Coastguard Worker 
attemptSend(SendFlags sflags)1046*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::attemptSend(SendFlags sflags) {
1047*d9f75844SAndroid Build Coastguard Worker   uint32_t now = Now();
1048*d9f75844SAndroid Build Coastguard Worker 
1049*d9f75844SAndroid Build Coastguard Worker   if (rtc::TimeDiff32(now, m_lastsend) > static_cast<long>(m_rx_rto)) {
1050*d9f75844SAndroid Build Coastguard Worker     m_cwnd = m_mss;
1051*d9f75844SAndroid Build Coastguard Worker   }
1052*d9f75844SAndroid Build Coastguard Worker 
1053*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG
1054*d9f75844SAndroid Build Coastguard Worker   bool bFirst = true;
1055*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
1056*d9f75844SAndroid Build Coastguard Worker 
1057*d9f75844SAndroid Build Coastguard Worker   while (true) {
1058*d9f75844SAndroid Build Coastguard Worker     uint32_t cwnd = m_cwnd;
1059*d9f75844SAndroid Build Coastguard Worker     if ((m_dup_acks == 1) || (m_dup_acks == 2)) {  // Limited Transmit
1060*d9f75844SAndroid Build Coastguard Worker       cwnd += m_dup_acks * m_mss;
1061*d9f75844SAndroid Build Coastguard Worker     }
1062*d9f75844SAndroid Build Coastguard Worker     uint32_t nWindow = std::min(m_snd_wnd, cwnd);
1063*d9f75844SAndroid Build Coastguard Worker     uint32_t nInFlight = m_snd_nxt - m_snd_una;
1064*d9f75844SAndroid Build Coastguard Worker     uint32_t nUseable = (nInFlight < nWindow) ? (nWindow - nInFlight) : 0;
1065*d9f75844SAndroid Build Coastguard Worker 
1066*d9f75844SAndroid Build Coastguard Worker     size_t snd_buffered = m_sbuf.GetBuffered();
1067*d9f75844SAndroid Build Coastguard Worker     uint32_t nAvailable =
1068*d9f75844SAndroid Build Coastguard Worker         std::min(static_cast<uint32_t>(snd_buffered) - nInFlight, m_mss);
1069*d9f75844SAndroid Build Coastguard Worker 
1070*d9f75844SAndroid Build Coastguard Worker     if (nAvailable > nUseable) {
1071*d9f75844SAndroid Build Coastguard Worker       if (nUseable * 4 < nWindow) {
1072*d9f75844SAndroid Build Coastguard Worker         // RFC 813 - avoid SWS
1073*d9f75844SAndroid Build Coastguard Worker         nAvailable = 0;
1074*d9f75844SAndroid Build Coastguard Worker       } else {
1075*d9f75844SAndroid Build Coastguard Worker         nAvailable = nUseable;
1076*d9f75844SAndroid Build Coastguard Worker       }
1077*d9f75844SAndroid Build Coastguard Worker     }
1078*d9f75844SAndroid Build Coastguard Worker 
1079*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_VERBOSE
1080*d9f75844SAndroid Build Coastguard Worker     if (bFirst) {
1081*d9f75844SAndroid Build Coastguard Worker       size_t available_space = 0;
1082*d9f75844SAndroid Build Coastguard Worker       m_sbuf.GetWriteRemaining(&available_space);
1083*d9f75844SAndroid Build Coastguard Worker 
1084*d9f75844SAndroid Build Coastguard Worker       bFirst = false;
1085*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << "[cwnd: " << m_cwnd << "  nWindow: " << nWindow
1086*d9f75844SAndroid Build Coastguard Worker                        << "  nInFlight: " << nInFlight
1087*d9f75844SAndroid Build Coastguard Worker                        << "  nAvailable: " << nAvailable
1088*d9f75844SAndroid Build Coastguard Worker                        << "  nQueued: " << snd_buffered
1089*d9f75844SAndroid Build Coastguard Worker                        << "  nEmpty: " << available_space
1090*d9f75844SAndroid Build Coastguard Worker                        << "  ssthresh: " << m_ssthresh << "]";
1091*d9f75844SAndroid Build Coastguard Worker     }
1092*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
1093*d9f75844SAndroid Build Coastguard Worker 
1094*d9f75844SAndroid Build Coastguard Worker     if (nAvailable == 0) {
1095*d9f75844SAndroid Build Coastguard Worker       if (sflags == sfNone)
1096*d9f75844SAndroid Build Coastguard Worker         return;
1097*d9f75844SAndroid Build Coastguard Worker 
1098*d9f75844SAndroid Build Coastguard Worker       // If this is an immediate ack, or the second delayed ack
1099*d9f75844SAndroid Build Coastguard Worker       if ((sflags == sfImmediateAck) || m_t_ack) {
1100*d9f75844SAndroid Build Coastguard Worker         packet(m_snd_nxt, 0, 0, 0);
1101*d9f75844SAndroid Build Coastguard Worker       } else {
1102*d9f75844SAndroid Build Coastguard Worker         m_t_ack = Now();
1103*d9f75844SAndroid Build Coastguard Worker       }
1104*d9f75844SAndroid Build Coastguard Worker       return;
1105*d9f75844SAndroid Build Coastguard Worker     }
1106*d9f75844SAndroid Build Coastguard Worker 
1107*d9f75844SAndroid Build Coastguard Worker     // Nagle's algorithm.
1108*d9f75844SAndroid Build Coastguard Worker     // If there is data already in-flight, and we haven't a full segment of
1109*d9f75844SAndroid Build Coastguard Worker     // data ready to send then hold off until we get more to send, or the
1110*d9f75844SAndroid Build Coastguard Worker     // in-flight data is acknowledged.
1111*d9f75844SAndroid Build Coastguard Worker     if (m_use_nagling && (m_snd_nxt > m_snd_una) && (nAvailable < m_mss)) {
1112*d9f75844SAndroid Build Coastguard Worker       return;
1113*d9f75844SAndroid Build Coastguard Worker     }
1114*d9f75844SAndroid Build Coastguard Worker 
1115*d9f75844SAndroid Build Coastguard Worker     // Find the next segment to transmit
1116*d9f75844SAndroid Build Coastguard Worker     SList::iterator it = m_slist.begin();
1117*d9f75844SAndroid Build Coastguard Worker     while (it->xmit > 0) {
1118*d9f75844SAndroid Build Coastguard Worker       ++it;
1119*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(it != m_slist.end());
1120*d9f75844SAndroid Build Coastguard Worker     }
1121*d9f75844SAndroid Build Coastguard Worker     SList::iterator seg = it;
1122*d9f75844SAndroid Build Coastguard Worker 
1123*d9f75844SAndroid Build Coastguard Worker     // If the segment is too large, break it into two
1124*d9f75844SAndroid Build Coastguard Worker     if (seg->len > nAvailable) {
1125*d9f75844SAndroid Build Coastguard Worker       SSegment subseg(seg->seq + nAvailable, seg->len - nAvailable, seg->bCtrl);
1126*d9f75844SAndroid Build Coastguard Worker       seg->len = nAvailable;
1127*d9f75844SAndroid Build Coastguard Worker       m_slist.insert(++it, subseg);
1128*d9f75844SAndroid Build Coastguard Worker     }
1129*d9f75844SAndroid Build Coastguard Worker 
1130*d9f75844SAndroid Build Coastguard Worker     if (!transmit(seg, now)) {
1131*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_VERBOSE) << "transmit failed";
1132*d9f75844SAndroid Build Coastguard Worker       // TODO(?): consider closing socket
1133*d9f75844SAndroid Build Coastguard Worker       return;
1134*d9f75844SAndroid Build Coastguard Worker     }
1135*d9f75844SAndroid Build Coastguard Worker 
1136*d9f75844SAndroid Build Coastguard Worker     sflags = sfNone;
1137*d9f75844SAndroid Build Coastguard Worker   }
1138*d9f75844SAndroid Build Coastguard Worker }
1139*d9f75844SAndroid Build Coastguard Worker 
closedown(uint32_t err)1140*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::closedown(uint32_t err) {
1141*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "State: TCP_CLOSED";
1142*d9f75844SAndroid Build Coastguard Worker   m_state = TCP_CLOSED;
1143*d9f75844SAndroid Build Coastguard Worker   if (m_notify) {
1144*d9f75844SAndroid Build Coastguard Worker     m_notify->OnTcpClosed(this, err);
1145*d9f75844SAndroid Build Coastguard Worker   }
1146*d9f75844SAndroid Build Coastguard Worker   // notify(evClose, err);
1147*d9f75844SAndroid Build Coastguard Worker }
1148*d9f75844SAndroid Build Coastguard Worker 
adjustMTU()1149*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::adjustMTU() {
1150*d9f75844SAndroid Build Coastguard Worker   // Determine our current mss level, so that we can adjust appropriately later
1151*d9f75844SAndroid Build Coastguard Worker   for (m_msslevel = 0; PACKET_MAXIMUMS[m_msslevel + 1] > 0; ++m_msslevel) {
1152*d9f75844SAndroid Build Coastguard Worker     if (static_cast<uint16_t>(PACKET_MAXIMUMS[m_msslevel]) <= m_mtu_advise) {
1153*d9f75844SAndroid Build Coastguard Worker       break;
1154*d9f75844SAndroid Build Coastguard Worker     }
1155*d9f75844SAndroid Build Coastguard Worker   }
1156*d9f75844SAndroid Build Coastguard Worker   m_mss = m_mtu_advise - PACKET_OVERHEAD;
1157*d9f75844SAndroid Build Coastguard Worker // !?! Should we reset m_largest here?
1158*d9f75844SAndroid Build Coastguard Worker #if _DEBUGMSG >= _DBG_NORMAL
1159*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes";
1160*d9f75844SAndroid Build Coastguard Worker #endif  // _DEBUGMSG
1161*d9f75844SAndroid Build Coastguard Worker   // Enforce minimums on ssthresh and cwnd
1162*d9f75844SAndroid Build Coastguard Worker   m_ssthresh = std::max(m_ssthresh, 2 * m_mss);
1163*d9f75844SAndroid Build Coastguard Worker   m_cwnd = std::max(m_cwnd, m_mss);
1164*d9f75844SAndroid Build Coastguard Worker }
1165*d9f75844SAndroid Build Coastguard Worker 
isReceiveBufferFull() const1166*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::isReceiveBufferFull() const {
1167*d9f75844SAndroid Build Coastguard Worker   size_t available_space = 0;
1168*d9f75844SAndroid Build Coastguard Worker   m_rbuf.GetWriteRemaining(&available_space);
1169*d9f75844SAndroid Build Coastguard Worker   return !available_space;
1170*d9f75844SAndroid Build Coastguard Worker }
1171*d9f75844SAndroid Build Coastguard Worker 
disableWindowScale()1172*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::disableWindowScale() {
1173*d9f75844SAndroid Build Coastguard Worker   m_support_wnd_scale = false;
1174*d9f75844SAndroid Build Coastguard Worker }
1175*d9f75844SAndroid Build Coastguard Worker 
queueConnectMessage()1176*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::queueConnectMessage() {
1177*d9f75844SAndroid Build Coastguard Worker   rtc::ByteBufferWriter buf;
1178*d9f75844SAndroid Build Coastguard Worker 
1179*d9f75844SAndroid Build Coastguard Worker   buf.WriteUInt8(CTL_CONNECT);
1180*d9f75844SAndroid Build Coastguard Worker   if (m_support_wnd_scale) {
1181*d9f75844SAndroid Build Coastguard Worker     buf.WriteUInt8(TCP_OPT_WND_SCALE);
1182*d9f75844SAndroid Build Coastguard Worker     buf.WriteUInt8(1);
1183*d9f75844SAndroid Build Coastguard Worker     buf.WriteUInt8(m_rwnd_scale);
1184*d9f75844SAndroid Build Coastguard Worker   }
1185*d9f75844SAndroid Build Coastguard Worker   m_snd_wnd = static_cast<uint32_t>(buf.Length());
1186*d9f75844SAndroid Build Coastguard Worker   queue(buf.Data(), static_cast<uint32_t>(buf.Length()), true);
1187*d9f75844SAndroid Build Coastguard Worker }
1188*d9f75844SAndroid Build Coastguard Worker 
parseOptions(const char * data,uint32_t len)1189*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::parseOptions(const char* data, uint32_t len) {
1190*d9f75844SAndroid Build Coastguard Worker   std::set<uint8_t> options_specified;
1191*d9f75844SAndroid Build Coastguard Worker 
1192*d9f75844SAndroid Build Coastguard Worker   // See http://www.freesoft.org/CIE/Course/Section4/8.htm for
1193*d9f75844SAndroid Build Coastguard Worker   // parsing the options list.
1194*d9f75844SAndroid Build Coastguard Worker   rtc::ByteBufferReader buf(data, len);
1195*d9f75844SAndroid Build Coastguard Worker   while (buf.Length()) {
1196*d9f75844SAndroid Build Coastguard Worker     uint8_t kind = TCP_OPT_EOL;
1197*d9f75844SAndroid Build Coastguard Worker     buf.ReadUInt8(&kind);
1198*d9f75844SAndroid Build Coastguard Worker 
1199*d9f75844SAndroid Build Coastguard Worker     if (kind == TCP_OPT_EOL) {
1200*d9f75844SAndroid Build Coastguard Worker       // End of option list.
1201*d9f75844SAndroid Build Coastguard Worker       break;
1202*d9f75844SAndroid Build Coastguard Worker     } else if (kind == TCP_OPT_NOOP) {
1203*d9f75844SAndroid Build Coastguard Worker       // No op.
1204*d9f75844SAndroid Build Coastguard Worker       continue;
1205*d9f75844SAndroid Build Coastguard Worker     }
1206*d9f75844SAndroid Build Coastguard Worker 
1207*d9f75844SAndroid Build Coastguard Worker     // Length of this option.
1208*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(len != 0);
1209*d9f75844SAndroid Build Coastguard Worker     uint8_t opt_len = 0;
1210*d9f75844SAndroid Build Coastguard Worker     buf.ReadUInt8(&opt_len);
1211*d9f75844SAndroid Build Coastguard Worker 
1212*d9f75844SAndroid Build Coastguard Worker     // Content of this option.
1213*d9f75844SAndroid Build Coastguard Worker     if (opt_len <= buf.Length()) {
1214*d9f75844SAndroid Build Coastguard Worker       applyOption(kind, buf.Data(), opt_len);
1215*d9f75844SAndroid Build Coastguard Worker       buf.Consume(opt_len);
1216*d9f75844SAndroid Build Coastguard Worker     } else {
1217*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Invalid option length received.";
1218*d9f75844SAndroid Build Coastguard Worker       return;
1219*d9f75844SAndroid Build Coastguard Worker     }
1220*d9f75844SAndroid Build Coastguard Worker     options_specified.insert(kind);
1221*d9f75844SAndroid Build Coastguard Worker   }
1222*d9f75844SAndroid Build Coastguard Worker 
1223*d9f75844SAndroid Build Coastguard Worker   if (options_specified.find(TCP_OPT_WND_SCALE) == options_specified.end()) {
1224*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Peer doesn't support window scaling";
1225*d9f75844SAndroid Build Coastguard Worker 
1226*d9f75844SAndroid Build Coastguard Worker     if (m_rwnd_scale > 0) {
1227*d9f75844SAndroid Build Coastguard Worker       // Peer doesn't support TCP options and window scaling.
1228*d9f75844SAndroid Build Coastguard Worker       // Revert receive buffer size to default value.
1229*d9f75844SAndroid Build Coastguard Worker       resizeReceiveBuffer(DEFAULT_RCV_BUF_SIZE);
1230*d9f75844SAndroid Build Coastguard Worker       m_swnd_scale = 0;
1231*d9f75844SAndroid Build Coastguard Worker     }
1232*d9f75844SAndroid Build Coastguard Worker   }
1233*d9f75844SAndroid Build Coastguard Worker }
1234*d9f75844SAndroid Build Coastguard Worker 
applyOption(char kind,const char * data,uint32_t len)1235*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::applyOption(char kind, const char* data, uint32_t len) {
1236*d9f75844SAndroid Build Coastguard Worker   if (kind == TCP_OPT_MSS) {
1237*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Peer specified MSS option which is not supported.";
1238*d9f75844SAndroid Build Coastguard Worker     // TODO(?): Implement.
1239*d9f75844SAndroid Build Coastguard Worker   } else if (kind == TCP_OPT_WND_SCALE) {
1240*d9f75844SAndroid Build Coastguard Worker     // Window scale factor.
1241*d9f75844SAndroid Build Coastguard Worker     // http://www.ietf.org/rfc/rfc1323.txt
1242*d9f75844SAndroid Build Coastguard Worker     if (len != 1) {
1243*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_WARNING) << "Invalid window scale option received.";
1244*d9f75844SAndroid Build Coastguard Worker       return;
1245*d9f75844SAndroid Build Coastguard Worker     }
1246*d9f75844SAndroid Build Coastguard Worker     applyWindowScaleOption(data[0]);
1247*d9f75844SAndroid Build Coastguard Worker   }
1248*d9f75844SAndroid Build Coastguard Worker }
1249*d9f75844SAndroid Build Coastguard Worker 
applyWindowScaleOption(uint8_t scale_factor)1250*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::applyWindowScaleOption(uint8_t scale_factor) {
1251*d9f75844SAndroid Build Coastguard Worker   m_swnd_scale = scale_factor;
1252*d9f75844SAndroid Build Coastguard Worker }
1253*d9f75844SAndroid Build Coastguard Worker 
resizeSendBuffer(uint32_t new_size)1254*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::resizeSendBuffer(uint32_t new_size) {
1255*d9f75844SAndroid Build Coastguard Worker   m_sbuf_len = new_size;
1256*d9f75844SAndroid Build Coastguard Worker   m_sbuf.SetCapacity(new_size);
1257*d9f75844SAndroid Build Coastguard Worker }
1258*d9f75844SAndroid Build Coastguard Worker 
resizeReceiveBuffer(uint32_t new_size)1259*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::resizeReceiveBuffer(uint32_t new_size) {
1260*d9f75844SAndroid Build Coastguard Worker   uint8_t scale_factor = 0;
1261*d9f75844SAndroid Build Coastguard Worker 
1262*d9f75844SAndroid Build Coastguard Worker   // Determine the scale factor such that the scaled window size can fit
1263*d9f75844SAndroid Build Coastguard Worker   // in a 16-bit unsigned integer.
1264*d9f75844SAndroid Build Coastguard Worker   while (new_size > 0xFFFF) {
1265*d9f75844SAndroid Build Coastguard Worker     ++scale_factor;
1266*d9f75844SAndroid Build Coastguard Worker     new_size >>= 1;
1267*d9f75844SAndroid Build Coastguard Worker   }
1268*d9f75844SAndroid Build Coastguard Worker 
1269*d9f75844SAndroid Build Coastguard Worker   // Determine the proper size of the buffer.
1270*d9f75844SAndroid Build Coastguard Worker   new_size <<= scale_factor;
1271*d9f75844SAndroid Build Coastguard Worker   bool result = m_rbuf.SetCapacity(new_size);
1272*d9f75844SAndroid Build Coastguard Worker 
1273*d9f75844SAndroid Build Coastguard Worker   // Make sure the new buffer is large enough to contain data in the old
1274*d9f75844SAndroid Build Coastguard Worker   // buffer. This should always be true because this method is called either
1275*d9f75844SAndroid Build Coastguard Worker   // before connection is established or when peers are exchanging connect
1276*d9f75844SAndroid Build Coastguard Worker   // messages.
1277*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(result);
1278*d9f75844SAndroid Build Coastguard Worker   m_rbuf_len = new_size;
1279*d9f75844SAndroid Build Coastguard Worker   m_rwnd_scale = scale_factor;
1280*d9f75844SAndroid Build Coastguard Worker   m_ssthresh = new_size;
1281*d9f75844SAndroid Build Coastguard Worker 
1282*d9f75844SAndroid Build Coastguard Worker   size_t available_space = 0;
1283*d9f75844SAndroid Build Coastguard Worker   m_rbuf.GetWriteRemaining(&available_space);
1284*d9f75844SAndroid Build Coastguard Worker   m_rcv_wnd = static_cast<uint32_t>(available_space);
1285*d9f75844SAndroid Build Coastguard Worker }
1286*d9f75844SAndroid Build Coastguard Worker 
LockedFifoBuffer(size_t size)1287*d9f75844SAndroid Build Coastguard Worker PseudoTcp::LockedFifoBuffer::LockedFifoBuffer(size_t size)
1288*d9f75844SAndroid Build Coastguard Worker     : buffer_(new char[size]),
1289*d9f75844SAndroid Build Coastguard Worker       buffer_length_(size),
1290*d9f75844SAndroid Build Coastguard Worker       data_length_(0),
1291*d9f75844SAndroid Build Coastguard Worker       read_position_(0) {}
1292*d9f75844SAndroid Build Coastguard Worker 
~LockedFifoBuffer()1293*d9f75844SAndroid Build Coastguard Worker PseudoTcp::LockedFifoBuffer::~LockedFifoBuffer() {}
1294*d9f75844SAndroid Build Coastguard Worker 
GetBuffered() const1295*d9f75844SAndroid Build Coastguard Worker size_t PseudoTcp::LockedFifoBuffer::GetBuffered() const {
1296*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1297*d9f75844SAndroid Build Coastguard Worker   return data_length_;
1298*d9f75844SAndroid Build Coastguard Worker }
1299*d9f75844SAndroid Build Coastguard Worker 
SetCapacity(size_t size)1300*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::SetCapacity(size_t size) {
1301*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1302*d9f75844SAndroid Build Coastguard Worker   if (data_length_ > size)
1303*d9f75844SAndroid Build Coastguard Worker     return false;
1304*d9f75844SAndroid Build Coastguard Worker 
1305*d9f75844SAndroid Build Coastguard Worker   if (size != buffer_length_) {
1306*d9f75844SAndroid Build Coastguard Worker     char* buffer = new char[size];
1307*d9f75844SAndroid Build Coastguard Worker     const size_t copy = data_length_;
1308*d9f75844SAndroid Build Coastguard Worker     const size_t tail_copy = std::min(copy, buffer_length_ - read_position_);
1309*d9f75844SAndroid Build Coastguard Worker     memcpy(buffer, &buffer_[read_position_], tail_copy);
1310*d9f75844SAndroid Build Coastguard Worker     memcpy(buffer + tail_copy, &buffer_[0], copy - tail_copy);
1311*d9f75844SAndroid Build Coastguard Worker     buffer_.reset(buffer);
1312*d9f75844SAndroid Build Coastguard Worker     read_position_ = 0;
1313*d9f75844SAndroid Build Coastguard Worker     buffer_length_ = size;
1314*d9f75844SAndroid Build Coastguard Worker   }
1315*d9f75844SAndroid Build Coastguard Worker 
1316*d9f75844SAndroid Build Coastguard Worker   return true;
1317*d9f75844SAndroid Build Coastguard Worker }
1318*d9f75844SAndroid Build Coastguard Worker 
ReadOffset(void * buffer,size_t bytes,size_t offset,size_t * bytes_read)1319*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::ReadOffset(void* buffer,
1320*d9f75844SAndroid Build Coastguard Worker                                              size_t bytes,
1321*d9f75844SAndroid Build Coastguard Worker                                              size_t offset,
1322*d9f75844SAndroid Build Coastguard Worker                                              size_t* bytes_read) {
1323*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1324*d9f75844SAndroid Build Coastguard Worker   return ReadOffsetLocked(buffer, bytes, offset, bytes_read);
1325*d9f75844SAndroid Build Coastguard Worker }
1326*d9f75844SAndroid Build Coastguard Worker 
WriteOffset(const void * buffer,size_t bytes,size_t offset,size_t * bytes_written)1327*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::WriteOffset(const void* buffer,
1328*d9f75844SAndroid Build Coastguard Worker                                               size_t bytes,
1329*d9f75844SAndroid Build Coastguard Worker                                               size_t offset,
1330*d9f75844SAndroid Build Coastguard Worker                                               size_t* bytes_written) {
1331*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1332*d9f75844SAndroid Build Coastguard Worker   return WriteOffsetLocked(buffer, bytes, offset, bytes_written);
1333*d9f75844SAndroid Build Coastguard Worker }
1334*d9f75844SAndroid Build Coastguard Worker 
Read(void * buffer,size_t bytes,size_t * bytes_read)1335*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::Read(void* buffer,
1336*d9f75844SAndroid Build Coastguard Worker                                        size_t bytes,
1337*d9f75844SAndroid Build Coastguard Worker                                        size_t* bytes_read) {
1338*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1339*d9f75844SAndroid Build Coastguard Worker   size_t copy = 0;
1340*d9f75844SAndroid Build Coastguard Worker   if (!ReadOffsetLocked(buffer, bytes, 0, &copy))
1341*d9f75844SAndroid Build Coastguard Worker     return false;
1342*d9f75844SAndroid Build Coastguard Worker 
1343*d9f75844SAndroid Build Coastguard Worker   // If read was successful then adjust the read position and number of
1344*d9f75844SAndroid Build Coastguard Worker   // bytes buffered.
1345*d9f75844SAndroid Build Coastguard Worker   read_position_ = (read_position_ + copy) % buffer_length_;
1346*d9f75844SAndroid Build Coastguard Worker   data_length_ -= copy;
1347*d9f75844SAndroid Build Coastguard Worker   if (bytes_read)
1348*d9f75844SAndroid Build Coastguard Worker     *bytes_read = copy;
1349*d9f75844SAndroid Build Coastguard Worker 
1350*d9f75844SAndroid Build Coastguard Worker   return true;
1351*d9f75844SAndroid Build Coastguard Worker }
1352*d9f75844SAndroid Build Coastguard Worker 
Write(const void * buffer,size_t bytes,size_t * bytes_written)1353*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::Write(const void* buffer,
1354*d9f75844SAndroid Build Coastguard Worker                                         size_t bytes,
1355*d9f75844SAndroid Build Coastguard Worker                                         size_t* bytes_written) {
1356*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1357*d9f75844SAndroid Build Coastguard Worker   size_t copy = 0;
1358*d9f75844SAndroid Build Coastguard Worker   if (!WriteOffsetLocked(buffer, bytes, 0, &copy))
1359*d9f75844SAndroid Build Coastguard Worker     return false;
1360*d9f75844SAndroid Build Coastguard Worker 
1361*d9f75844SAndroid Build Coastguard Worker   // If write was successful then adjust the number of readable bytes.
1362*d9f75844SAndroid Build Coastguard Worker   data_length_ += copy;
1363*d9f75844SAndroid Build Coastguard Worker   if (bytes_written) {
1364*d9f75844SAndroid Build Coastguard Worker     *bytes_written = copy;
1365*d9f75844SAndroid Build Coastguard Worker   }
1366*d9f75844SAndroid Build Coastguard Worker 
1367*d9f75844SAndroid Build Coastguard Worker   return true;
1368*d9f75844SAndroid Build Coastguard Worker }
1369*d9f75844SAndroid Build Coastguard Worker 
ConsumeReadData(size_t size)1370*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::LockedFifoBuffer::ConsumeReadData(size_t size) {
1371*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1372*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(size <= data_length_);
1373*d9f75844SAndroid Build Coastguard Worker   read_position_ = (read_position_ + size) % buffer_length_;
1374*d9f75844SAndroid Build Coastguard Worker   data_length_ -= size;
1375*d9f75844SAndroid Build Coastguard Worker }
1376*d9f75844SAndroid Build Coastguard Worker 
ConsumeWriteBuffer(size_t size)1377*d9f75844SAndroid Build Coastguard Worker void PseudoTcp::LockedFifoBuffer::ConsumeWriteBuffer(size_t size) {
1378*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1379*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(size <= buffer_length_ - data_length_);
1380*d9f75844SAndroid Build Coastguard Worker   data_length_ += size;
1381*d9f75844SAndroid Build Coastguard Worker }
1382*d9f75844SAndroid Build Coastguard Worker 
GetWriteRemaining(size_t * size) const1383*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::GetWriteRemaining(size_t* size) const {
1384*d9f75844SAndroid Build Coastguard Worker   webrtc::MutexLock lock(&mutex_);
1385*d9f75844SAndroid Build Coastguard Worker   *size = buffer_length_ - data_length_;
1386*d9f75844SAndroid Build Coastguard Worker   return true;
1387*d9f75844SAndroid Build Coastguard Worker }
1388*d9f75844SAndroid Build Coastguard Worker 
ReadOffsetLocked(void * buffer,size_t bytes,size_t offset,size_t * bytes_read)1389*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::ReadOffsetLocked(void* buffer,
1390*d9f75844SAndroid Build Coastguard Worker                                                    size_t bytes,
1391*d9f75844SAndroid Build Coastguard Worker                                                    size_t offset,
1392*d9f75844SAndroid Build Coastguard Worker                                                    size_t* bytes_read) {
1393*d9f75844SAndroid Build Coastguard Worker   if (offset >= data_length_)
1394*d9f75844SAndroid Build Coastguard Worker     return false;
1395*d9f75844SAndroid Build Coastguard Worker 
1396*d9f75844SAndroid Build Coastguard Worker   const size_t available = data_length_ - offset;
1397*d9f75844SAndroid Build Coastguard Worker   const size_t read_position = (read_position_ + offset) % buffer_length_;
1398*d9f75844SAndroid Build Coastguard Worker   const size_t copy = std::min(bytes, available);
1399*d9f75844SAndroid Build Coastguard Worker   const size_t tail_copy = std::min(copy, buffer_length_ - read_position);
1400*d9f75844SAndroid Build Coastguard Worker   char* const p = static_cast<char*>(buffer);
1401*d9f75844SAndroid Build Coastguard Worker   memcpy(p, &buffer_[read_position], tail_copy);
1402*d9f75844SAndroid Build Coastguard Worker   memcpy(p + tail_copy, &buffer_[0], copy - tail_copy);
1403*d9f75844SAndroid Build Coastguard Worker 
1404*d9f75844SAndroid Build Coastguard Worker   if (bytes_read)
1405*d9f75844SAndroid Build Coastguard Worker     *bytes_read = copy;
1406*d9f75844SAndroid Build Coastguard Worker 
1407*d9f75844SAndroid Build Coastguard Worker   return true;
1408*d9f75844SAndroid Build Coastguard Worker }
1409*d9f75844SAndroid Build Coastguard Worker 
WriteOffsetLocked(const void * buffer,size_t bytes,size_t offset,size_t * bytes_written)1410*d9f75844SAndroid Build Coastguard Worker bool PseudoTcp::LockedFifoBuffer::WriteOffsetLocked(const void* buffer,
1411*d9f75844SAndroid Build Coastguard Worker                                                     size_t bytes,
1412*d9f75844SAndroid Build Coastguard Worker                                                     size_t offset,
1413*d9f75844SAndroid Build Coastguard Worker                                                     size_t* bytes_written) {
1414*d9f75844SAndroid Build Coastguard Worker   if (data_length_ + offset >= buffer_length_)
1415*d9f75844SAndroid Build Coastguard Worker     return false;
1416*d9f75844SAndroid Build Coastguard Worker 
1417*d9f75844SAndroid Build Coastguard Worker   const size_t available = buffer_length_ - data_length_ - offset;
1418*d9f75844SAndroid Build Coastguard Worker   const size_t write_position =
1419*d9f75844SAndroid Build Coastguard Worker       (read_position_ + data_length_ + offset) % buffer_length_;
1420*d9f75844SAndroid Build Coastguard Worker   const size_t copy = std::min(bytes, available);
1421*d9f75844SAndroid Build Coastguard Worker   const size_t tail_copy = std::min(copy, buffer_length_ - write_position);
1422*d9f75844SAndroid Build Coastguard Worker   const char* const p = static_cast<const char*>(buffer);
1423*d9f75844SAndroid Build Coastguard Worker   memcpy(&buffer_[write_position], p, tail_copy);
1424*d9f75844SAndroid Build Coastguard Worker   memcpy(&buffer_[0], p + tail_copy, copy - tail_copy);
1425*d9f75844SAndroid Build Coastguard Worker 
1426*d9f75844SAndroid Build Coastguard Worker   if (bytes_written)
1427*d9f75844SAndroid Build Coastguard Worker     *bytes_written = copy;
1428*d9f75844SAndroid Build Coastguard Worker 
1429*d9f75844SAndroid Build Coastguard Worker   return true;
1430*d9f75844SAndroid Build Coastguard Worker }
1431*d9f75844SAndroid Build Coastguard Worker 
1432*d9f75844SAndroid Build Coastguard Worker }  // namespace cricket
1433