10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2005, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/pseudotcp.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org#include <stdio.h>
31b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org#include <stdlib.h>
32b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <set>
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/basictypes.h"
362a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/bytebuffer.h"
372a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/byteorder.h"
382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/common.h"
392a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h"
402a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/scoped_ptr.h"
412a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/socket.h"
422a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/stringutils.h"
432a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/timeutils.h"
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The following logging is for detailed (packet-level) analysis only.
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define _DBG_NONE     0
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define _DBG_NORMAL   1
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define _DBG_VERBOSE  2
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define _DEBUGMSG _DBG_NONE
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Network Constants
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Standard MTUs
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint16 PACKET_MAXIMUMS[] = {
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  65535,    // Theoretical maximum, Hyperchannel
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  32000,    // Nothing
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  17914,    // 16Mb IBM Token Ring
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  8166,   // IEEE 802.4
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //4464,   // IEEE 802.5 (4Mb max)
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  4352,   // FDDI
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //2048,   // Wideband Network
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  2002,   // IEEE 802.5 (4Mb recommended)
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //1536,   // Expermental Ethernet Networks
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //1500,   // Ethernet, Point-to-Point (default)
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  1492,   // IEEE 802.3
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  1006,   // SLIP, ARPANET
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //576,    // X.25 Networks
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //544,    // DEC IP Portal
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //512,    // NETBIOS
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  508,    // IEEE 802/Source-Rt Bridge, ARCNET
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  296,    // Point-to-Point (low delay)
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //68,     // Official minimum
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  0,      // End of list marker
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MAX_PACKET = 65535;
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Note: we removed lowest level because packet overhead was larger!
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MIN_PACKET = 296;
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 IP_HEADER_SIZE = 20; // (+ up to 40 bytes of options?)
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 UDP_HEADER_SIZE = 8;
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO: Make JINGLE_HEADER_SIZE transparent to this code?
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 JINGLE_HEADER_SIZE = 64; // when relay framing is in use
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Default size for receive and send buffer.
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 DEFAULT_RCV_BUF_SIZE = 60 * 1024;
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 DEFAULT_SND_BUF_SIZE = 90 * 1024;
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Global Constants and Functions
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    0                   1                   2                   3
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    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
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  0 |                      Conversation Number                      |
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  4 |                        Sequence Number                        |
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//  8 |                     Acknowledgment Number                     |
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    |               |   |U|A|P|R|S|F|                               |
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 12 |    Control    |   |R|C|S|S|Y|I|            Window             |
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    |               |   |G|K|H|T|N|N|                               |
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 16 |                       Timestamp sending                       |
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 20 |                      Timestamp receiving                      |
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 24 |                             data                              |
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define PSEUDO_KEEPALIVE 0
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 HEADER_SIZE = 24;
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 PACKET_OVERHEAD = HEADER_SIZE + UDP_HEADER_SIZE + IP_HEADER_SIZE + JINGLE_HEADER_SIZE;
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MIN_RTO   =   250; // 250 ms (RFC1122, Sec 4.2.3.1 "fractions of a second")
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 DEF_RTO   =  3000; // 3 seconds (RFC1122, Sec 4.2.3.1)
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MAX_RTO   = 60000; // 60 seconds
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 DEF_ACK_DELAY = 100; // 100 milliseconds
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint8 FLAG_CTL = 0x02;
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint8 FLAG_RST = 0x04;
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint8 CTL_CONNECT = 0;
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TCP options.
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint8 TCP_OPT_EOL = 0;  // End of list.
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint8 TCP_OPT_NOOP = 1;  // No-op.
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint8 TCP_OPT_MSS = 2;  // Maximum segment size.
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint8 TCP_OPT_WND_SCALE = 3;  // Window scale factor.
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst long DEFAULT_TIMEOUT = 4000; // If there are no pending clocks, wake up every 4 seconds
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst long CLOSED_TIMEOUT = 60 * 1000; // If the connection is closed, once per minute
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if PSEUDO_KEEPALIVE
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// !?! Rethink these times
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 IDLE_PING = 20 * 1000; // 20 seconds (note: WinXP SP2 firewall udp timeout is 90 seconds)
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 IDLE_TIMEOUT = 90 * 1000; // 90 seconds;
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // PSEUDO_KEEPALIVE
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Helper Functions
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline void long_to_bytes(uint32 val, void* buf) {
1542a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  *static_cast<uint32*>(buf) = rtc::HostToNetwork32(val);
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline void short_to_bytes(uint16 val, void* buf) {
1582a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  *static_cast<uint16*>(buf) = rtc::HostToNetwork16(val);
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline uint32 bytes_to_long(const void* buf) {
1622a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  return rtc::NetworkToHost32(*static_cast<const uint32*>(buf));
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline uint16 bytes_to_short(const void* buf) {
1662a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  return rtc::NetworkToHost16(*static_cast<const uint16*>(buf));
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 bound(uint32 lower, uint32 middle, uint32 upper) {
1702a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  return rtc::_min(rtc::_max(lower, middle), upper);
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Debugging Statistics
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if 0  // Not used yet
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum Stat {
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  S_SENT_PACKET,   // All packet sends
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  S_RESENT_PACKET, // All packet sends that are retransmits
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  S_RECV_PACKET,   // All packet receives
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  S_RECV_NEW,      // All packet receives that are too new
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  S_RECV_OLD,      // All packet receives that are too old
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  S_NUM_STATS
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* const STAT_NAMES[S_NUM_STATS] = {
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  "snt",
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  "snt-r",
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  "rcv"
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  "rcv-n",
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  "rcv-o"
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint g_stats[S_NUM_STATS];
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orginline void Incr(Stat s) { ++g_stats[s]; }
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ReportStats() {
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  char buffer[256];
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t len = 0;
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (int i = 0; i < S_NUM_STATS; ++i) {
2022a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    len += rtc::sprintfn(buffer, ARRAY_SIZE(buffer), "%s%s:%d",
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               (i == 0) ? "" : ",", STAT_NAMES[i], g_stats[i]);
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    g_stats[i] = 0;
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Stats[" << buffer << "]";
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PseudoTcp
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//////////////////////////////////////////////////////////////////////
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 PseudoTcp::Now() {
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if 0  // Use this to synchronize timers with logging timestamps (easier debug)
2172a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  return rtc::TimeSince(StartTime());
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
2192a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  return rtc::Time();
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::PseudoTcp(IPseudoTcpNotify* notify, uint32 conv)
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : m_notify(notify),
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_shutdown(SD_NONE),
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_error(0),
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_rbuf_len(DEFAULT_RCV_BUF_SIZE),
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_rbuf(m_rbuf_len),
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_sbuf_len(DEFAULT_SND_BUF_SIZE),
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_sbuf(m_sbuf_len) {
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sanity check on buffer sizes (needed for OnTcpWriteable notification logic)
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(m_rbuf_len + MIN_PACKET < m_sbuf_len);
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 now = Now();
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_state = TCP_LISTEN;
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_conv = conv;
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rcv_wnd = m_rbuf_len;
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rwnd_scale = m_swnd_scale = 0;
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_snd_nxt = 0;
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_snd_wnd = 1;
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_snd_una = m_rcv_nxt = 0;
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_bReadEnable = true;
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_bWriteEnable = false;
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_t_ack = 0;
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_msslevel = 0;
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_largest = 0;
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(MIN_PACKET > PACKET_OVERHEAD);
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_mss = MIN_PACKET - PACKET_OVERHEAD;
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_mtu_advise = MAX_PACKET;
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rto_base = 0;
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_cwnd = 2 * m_mss;
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_ssthresh = m_rbuf_len;
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_lastrecv = m_lastsend = m_lasttraffic = now;
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_bOutgoing = false;
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_dup_acks = 0;
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_recover = 0;
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_ts_recent = m_ts_lastack = 0;
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rx_rto = DEF_RTO;
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rx_srtt = m_rx_rttvar = 0;
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_use_nagling = true;
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_ack_delay = DEF_ACK_DELAY;
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_support_wnd_scale = true;
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::~PseudoTcp() {
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint PseudoTcp::Connect() {
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state != TCP_LISTEN) {
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_error = EINVAL;
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return -1;
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_state = TCP_SYN_SENT;
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "State: TCP_SYN_SENT";
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  queueConnectMessage();
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  attemptSend();
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return 0;
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcp::NotifyMTU(uint16 mtu) {
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_mtu_advise = mtu;
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state == TCP_ESTABLISHED) {
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adjustMTU();
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcp::NotifyClock(uint32 now) {
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state == TCP_CLOSED)
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Check if it's time to retransmit a segment
3042a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (m_rto_base && (rtc::TimeDiff(m_rto_base + m_rx_rto, now) <= 0)) {
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_slist.empty()) {
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(false);
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Note: (m_slist.front().xmit == 0)) {
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // retransmit segments
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "timeout retransmit (rto: " << m_rx_rto
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << ") (rto_base: " << m_rto_base
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << ") (now: " << now
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << ") (dup_acks: " << static_cast<unsigned>(m_dup_acks)
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << ")";
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!transmit(m_slist.begin(), now)) {
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        closedown(ECONNABORTED);
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return;
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      uint32 nInFlight = m_snd_nxt - m_snd_una;
3232a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      m_ssthresh = rtc::_max(nInFlight / 2, 2 * m_mss);
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      //LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << "  nInFlight: " << nInFlight << "  m_mss: " << m_mss;
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_cwnd = m_mss;
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Back off retransmit timer.  Note: the limit is lower when connecting.
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      uint32 rto_limit = (m_state < TCP_ESTABLISHED) ? DEF_RTO : MAX_RTO;
3292a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      m_rx_rto = rtc::_min(rto_limit, m_rx_rto * 2);
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_rto_base = now;
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check if it's time to probe closed windows
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((m_snd_wnd == 0)
3362a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        && (rtc::TimeDiff(m_lastsend + m_rx_rto, now) <= 0)) {
3372a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (rtc::TimeDiff(now, m_lastrecv) >= 15000) {
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      closedown(ECONNABORTED);
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // probe the window
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    packet(m_snd_nxt - 1, 0, 0, 0);
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_lastsend = now;
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // back off retransmit timer
3472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    m_rx_rto = rtc::_min(MAX_RTO, m_rx_rto * 2);
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check if it's time to send delayed acks
3512a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (m_t_ack && (rtc::TimeDiff(m_t_ack + m_ack_delay, now) <= 0)) {
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    packet(m_snd_nxt, 0, 0, 0);
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if PSEUDO_KEEPALIVE
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check for idle timeout
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lastrecv + IDLE_TIMEOUT, now) <= 0)) {
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    closedown(ECONNABORTED);
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check for ping timeout (to keep udp mapping open)
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3/2 : IDLE_PING), now) <= 0)) {
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    packet(m_snd_nxt, 0, 0, 0);
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // PSEUDO_KEEPALIVE
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PseudoTcp::NotifyPacket(const char* buffer, size_t len) {
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (len > MAX_PACKET) {
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(WARNING) << "packet too large";
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return parse(reinterpret_cast<const uint8 *>(buffer), uint32(len));
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PseudoTcp::GetNextClock(uint32 now, long& timeout) {
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return clock_check(now, timeout);
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcp::GetOption(Option opt, int* value) {
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (opt == OPT_NODELAY) {
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *value = m_use_nagling ? 0 : 1;
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (opt == OPT_ACKDELAY) {
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *value = m_ack_delay;
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (opt == OPT_SNDBUF) {
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *value = m_sbuf_len;
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (opt == OPT_RCVBUF) {
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *value = m_rbuf_len;
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcp::SetOption(Option opt, int value) {
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (opt == OPT_NODELAY) {
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_use_nagling = value == 0;
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (opt == OPT_ACKDELAY) {
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_ack_delay = value;
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (opt == OPT_SNDBUF) {
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(m_state == TCP_LISTEN);
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    resizeSendBuffer(value);
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (opt == OPT_RCVBUF) {
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(m_state == TCP_LISTEN);
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    resizeReceiveBuffer(value);
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 PseudoTcp::GetCongestionWindow() const {
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return m_cwnd;
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 PseudoTcp::GetBytesInFlight() const {
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return m_snd_nxt - m_snd_una;
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 PseudoTcp::GetBytesBufferedNotSent() const {
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t buffered_bytes = 0;
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf.GetBuffered(&buffered_bytes);
4211a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  return static_cast<uint32>(m_snd_una + buffered_bytes - m_snd_nxt);
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 PseudoTcp::GetRoundTripTimeEstimateMs() const {
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return m_rx_srtt;
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// IPStream Implementation
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint PseudoTcp::Recv(char* buffer, size_t len) {
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state != TCP_ESTABLISHED) {
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_error = ENOTCONN;
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SOCKET_ERROR;
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t read = 0;
4392a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::StreamResult result = m_rbuf.Read(buffer, len, &read, NULL);
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If there's no data in |m_rbuf|.
4422a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (result == rtc::SR_BLOCK) {
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_bReadEnable = true;
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_error = EWOULDBLOCK;
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SOCKET_ERROR;
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  ASSERT(result == rtc::SR_SUCCESS);
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t available_space = 0;
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rbuf.GetWriteRemaining(&available_space);
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (uint32(available_space) - m_rcv_wnd >=
4532a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::_min<uint32>(m_rbuf_len / 2, m_mss)) {
4541a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org    // TODO(jbeda): !?! Not sure about this was closed business
4551a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org    bool bWasClosed = (m_rcv_wnd == 0);
4561a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org    m_rcv_wnd = static_cast<uint32>(available_space);
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (bWasClosed) {
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      attemptSend(sfImmediateAck);
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4631a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  return static_cast<int>(read);
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint PseudoTcp::Send(const char* buffer, size_t len) {
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state != TCP_ESTABLISHED) {
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_error = ENOTCONN;
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SOCKET_ERROR;
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t available_space = 0;
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf.GetWriteRemaining(&available_space);
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!available_space) {
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_bWriteEnable = true;
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_error = EWOULDBLOCK;
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SOCKET_ERROR;
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int written = queue(buffer, uint32(len), false);
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  attemptSend();
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return written;
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcp::Close(bool force) {
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_F(LS_VERBOSE) << "(" << (force ? "true" : "false") << ")";
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_shutdown = force ? SD_FORCEFUL : SD_GRACEFUL;
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint PseudoTcp::GetError() {
4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return m_error;
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Internal Implementation
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 PseudoTcp::queue(const char* data, uint32 len, bool bCtrl) {
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t available_space = 0;
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf.GetWriteRemaining(&available_space);
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (len > static_cast<uint32>(available_space)) {
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(!bCtrl);
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    len = static_cast<uint32>(available_space);
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We can concatenate data if the last segment is the same type
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // (control v. regular data), and has not been transmitted yet
5101a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  if (!m_slist.empty() && (m_slist.back().bCtrl == bCtrl) &&
5111a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org      (m_slist.back().xmit == 0)) {
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_slist.back().len += len;
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    size_t snd_buffered = 0;
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_sbuf.GetBuffered(&snd_buffered);
5161a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org    SSegment sseg(static_cast<uint32>(m_snd_una + snd_buffered), len, bCtrl);
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_slist.push_back(sseg);
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t written = 0;
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf.Write(data, len, &written, NULL);
5221a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  return static_cast<uint32>(written);
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgIPseudoTcpNotify::WriteResult PseudoTcp::packet(uint32 seq, uint8 flags,
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                uint32 offset, uint32 len) {
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(HEADER_SIZE + len <= MAX_PACKET);
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 now = Now();
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5312a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::scoped_ptr<uint8[]> buffer(new uint8[MAX_PACKET]);
532a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  long_to_bytes(m_conv, buffer.get());
533a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  long_to_bytes(seq, buffer.get() + 4);
534a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  long_to_bytes(m_rcv_nxt, buffer.get() + 8);
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buffer[12] = 0;
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buffer[13] = flags;
537a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  short_to_bytes(
538a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      static_cast<uint16>(m_rcv_wnd >> m_rwnd_scale), buffer.get() + 14);
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Timestamp computations
541a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  long_to_bytes(now, buffer.get() + 16);
542a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  long_to_bytes(m_ts_recent, buffer.get() + 20);
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_ts_lastack = m_rcv_nxt;
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (len) {
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    size_t bytes_read = 0;
5472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::StreamResult result = m_sbuf.ReadOffset(
548a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        buffer.get() + HEADER_SIZE, len, offset, &bytes_read);
5492a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    RTC_UNUSED(result);
5502a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    ASSERT(result == rtc::SR_SUCCESS);
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(static_cast<uint32>(bytes_read) == len);
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_VERBOSE
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "<-- <CONV=" << m_conv
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><FLG=" << static_cast<unsigned>(flags)
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><SEQ=" << seq << ":" << seq + len
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><ACK=" << m_rcv_nxt
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><WND=" << m_rcv_wnd
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><TS="  << (now % 10000)
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><TSR=" << (m_ts_recent % 10000)
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><LEN=" << len << ">";
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
565a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  IPseudoTcpNotify::WriteResult wres = m_notify->TcpWritePacket(
566a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      this, reinterpret_cast<char *>(buffer.get()), len + HEADER_SIZE);
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Note: When len is 0, this is an ACK packet.  We don't read the return value for those,
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // and thus we won't retry.  So go ahead and treat the packet as a success (basically simulate
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // as if it were dropped), which will prevent our timers from being messed up.
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((wres != IPseudoTcpNotify::WR_SUCCESS) && (0 != len))
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return wres;
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_t_ack = 0;
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (len > 0) {
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_lastsend = now;
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_lasttraffic = now;
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_bOutgoing = true;
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return IPseudoTcpNotify::WR_SUCCESS;
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PseudoTcp::parse(const uint8* buffer, uint32 size) {
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (size < 12)
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Segment seg;
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.conv = bytes_to_long(buffer);
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.seq = bytes_to_long(buffer + 4);
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.ack = bytes_to_long(buffer + 8);
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.flags = buffer[13];
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.wnd = bytes_to_short(buffer + 14);
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.tsval = bytes_to_long(buffer + 16);
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.tsecr = bytes_to_long(buffer + 20);
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.data = reinterpret_cast<const char *>(buffer) + HEADER_SIZE;
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg.len = size - HEADER_SIZE;
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_VERBOSE
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "--> <CONV=" << seg.conv
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><FLG=" << static_cast<unsigned>(seg.flags)
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><SEQ=" << seg.seq << ":" << seg.seq + seg.len
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><ACK=" << seg.ack
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><WND=" << seg.wnd
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><TS="  << (seg.tsval % 10000)
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><TSR=" << (seg.tsecr % 10000)
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << "><LEN=" << seg.len << ">";
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return process(seg);
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PseudoTcp::clock_check(uint32 now, long& nTimeout) {
6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_shutdown == SD_FORCEFUL)
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t snd_buffered = 0;
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf.GetBuffered(&snd_buffered);
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((m_shutdown == SD_GRACEFUL)
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      && ((m_state != TCP_ESTABLISHED)
6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          || ((snd_buffered == 0) && (m_t_ack == 0)))) {
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state == TCP_CLOSED) {
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    nTimeout = CLOSED_TIMEOUT;
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  nTimeout = DEFAULT_TIMEOUT;
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_t_ack) {
6342a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    nTimeout = rtc::_min<int32>(nTimeout,
6352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::TimeDiff(m_t_ack + m_ack_delay, now));
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_rto_base) {
6382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    nTimeout = rtc::_min<int32>(nTimeout,
6392a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::TimeDiff(m_rto_base + m_rx_rto, now));
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_snd_wnd == 0) {
6422a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    nTimeout = rtc::_min<int32>(nTimeout, rtc::TimeDiff(m_lastsend + m_rx_rto, now));
6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if PSEUDO_KEEPALIVE
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state == TCP_ESTABLISHED) {
6462a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    nTimeout = rtc::_min<int32>(nTimeout,
6472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::TimeDiff(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3/2 : IDLE_PING), now));
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // PSEUDO_KEEPALIVE
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PseudoTcp::process(Segment& seg) {
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If this is the wrong conversation, send a reset!?! (with the correct conversation?)
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg.conv != m_conv) {
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //if ((seg.flags & FLAG_RST) == 0) {
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //  packet(tcb, seg.ack, 0, FLAG_RST, 0, 0);
6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //}
6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_ERROR) << "wrong conversation";
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 now = Now();
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_lasttraffic = m_lastrecv = now;
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_bOutgoing = false;
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_state == TCP_CLOSED) {
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // !?! send reset?
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_ERROR) << "closed";
6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check if this is a reset segment
6740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg.flags & FLAG_RST) {
6750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    closedown(ECONNRESET);
6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check for control data
6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool bConnect = false;
6810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg.flags & FLAG_CTL) {
6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (seg.len == 0) {
6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(LS_ERROR) << "Missing control code";
6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (seg.data[0] == CTL_CONNECT) {
6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      bConnect = true;
6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // TCP options are in the remainder of the payload after CTL_CONNECT.
6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      parseOptions(&seg.data[1], seg.len - 1);
6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (m_state == TCP_LISTEN) {
6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_state = TCP_SYN_RECEIVED;
6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "State: TCP_SYN_RECEIVED";
6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        //m_notify->associate(addr);
6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        queueConnectMessage();
6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else if (m_state == TCP_SYN_SENT) {
6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_state = TCP_ESTABLISHED;
6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "State: TCP_ESTABLISHED";
6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        adjustMTU();
7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (m_notify) {
7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          m_notify->OnTcpOpen(this);
7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        //notify(evOpen);
7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(LS_WARNING) << "Unknown control code: " << seg.data[0];
7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Update timestamp
7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((seg.seq <= m_ts_lastack) && (m_ts_lastack < seg.seq + seg.len)) {
7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_ts_recent = seg.tsval;
7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check if this is a valuable ack
7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((seg.ack > m_snd_una) && (seg.ack <= m_snd_nxt)) {
7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Calculate round-trip time
7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (seg.tsecr) {
7202a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      int32 rtt = rtc::TimeDiff(now, seg.tsecr);
7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (rtt >= 0) {
7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (m_rx_srtt == 0) {
7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          m_rx_srtt = rtt;
7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          m_rx_rttvar = rtt / 2;
7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        } else {
7265336226082b83b0a8c0c6f2783555a51842b42b8pbos@webrtc.org          uint32 unsigned_rtt = static_cast<uint32>(rtt);
7275336226082b83b0a8c0c6f2783555a51842b42b8pbos@webrtc.org          uint32 abs_err = unsigned_rtt > m_rx_srtt ? unsigned_rtt - m_rx_srtt
7285336226082b83b0a8c0c6f2783555a51842b42b8pbos@webrtc.org                                                    : m_rx_srtt - unsigned_rtt;
7295336226082b83b0a8c0c6f2783555a51842b42b8pbos@webrtc.org          m_rx_rttvar = (3 * m_rx_rttvar + abs_err) / 4;
7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          m_rx_srtt = (7 * m_rx_srtt + rtt) / 8;
7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_rx_rto = bound(MIN_RTO, m_rx_srtt +
7332a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org            rtc::_max<uint32>(1, 4 * m_rx_rttvar), MAX_RTO);
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_VERBOSE
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "rtt: " << rtt
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     << "  srtt: " << m_rx_srtt
7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     << "  rto: " << m_rx_rto;
7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ASSERT(false);
7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_snd_wnd = static_cast<uint32>(seg.wnd) << m_swnd_scale;
7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 nAcked = seg.ack - m_snd_una;
7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_snd_una = seg.ack;
7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_rto_base = (m_snd_una == m_snd_nxt) ? 0 : now;
7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_sbuf.ConsumeReadData(nAcked);
7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (uint32 nFree = nAcked; nFree > 0; ) {
7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(!m_slist.empty());
7550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (nFree < m_slist.front().len) {
7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_slist.front().len -= nFree;
7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        nFree = 0;
7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (m_slist.front().len > m_largest) {
7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          m_largest = m_slist.front().len;
7610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        nFree -= m_slist.front().len;
7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_slist.pop_front();
7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_dup_acks >= 3) {
7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (m_snd_una >= m_recover) { // NewReno
7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        uint32 nInFlight = m_snd_nxt - m_snd_una;
7702a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        m_cwnd = rtc::_min(m_ssthresh, nInFlight + m_mss); // (Fast Retransmit)
7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "exit recovery";
7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_dup_acks = 0;
7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "recovery retransmit";
7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!transmit(m_slist.begin(), now)) {
7800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          closedown(ECONNABORTED);
7810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          return false;
7820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
7832a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        m_cwnd += m_mss - rtc::_min(nAcked, m_cwnd);
7840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
7850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_dup_acks = 0;
7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Slow start, congestion avoidance
7880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (m_cwnd < m_ssthresh) {
7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_cwnd += m_mss;
7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
7912a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        m_cwnd += rtc::_max<uint32>(1, m_mss * m_mss / m_cwnd);
7920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
7930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (seg.ack == m_snd_una) {
7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // !?! Note, tcp says don't do this... but otherwise how does a closed window become open?
7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_snd_wnd = static_cast<uint32>(seg.wnd) << m_swnd_scale;
7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Check duplicate acks
7990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (seg.len > 0) {
8000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // it's a dup ack, but with a data payload, so don't modify m_dup_acks
8010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (m_snd_una != m_snd_nxt) {
8020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_dup_acks += 1;
8030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (m_dup_acks == 3) { // (Fast Retransmit)
8040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
8050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "enter recovery";
8060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "recovery retransmit";
8070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
8080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!transmit(m_slist.begin(), now)) {
8090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          closedown(ECONNABORTED);
8100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          return false;
8110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
8120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_recover = m_snd_nxt;
8130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        uint32 nInFlight = m_snd_nxt - m_snd_una;
8142a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        m_ssthresh = rtc::_max(nInFlight / 2, 2 * m_mss);
8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        //LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << "  nInFlight: " << nInFlight << "  m_mss: " << m_mss;
8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_cwnd = m_ssthresh + 3 * m_mss;
8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else if (m_dup_acks > 3) {
8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_cwnd += m_mss;
8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
8200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
8210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_dup_acks = 0;
8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // !?! A bit hacky
8260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((m_state == TCP_SYN_RECEIVED) && !bConnect) {
8270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_state = TCP_ESTABLISHED;
8280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "State: TCP_ESTABLISHED";
8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adjustMTU();
8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_notify) {
8310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_notify->OnTcpOpen(this);
8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //notify(evOpen);
8340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we make room in the send queue, notify the user
8370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The goal it to make sure we always have at least enough data to fill the
8380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // window.  We'd like to notify the app when we are halfway to that point.
8390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint32 kIdealRefillSize = (m_sbuf_len + m_rbuf_len) / 2;
8400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t snd_buffered = 0;
8410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf.GetBuffered(&snd_buffered);
8420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_bWriteEnable && static_cast<uint32>(snd_buffered) < kIdealRefillSize) {
8430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_bWriteEnable = false;
8440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_notify) {
8450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_notify->OnTcpWriteable(this);
8460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //notify(evWrite);
8480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Conditions were acks must be sent:
8510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 1) Segment is too old (they missed an ACK) (immediately)
8520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 2) Segment is too new (we missed a segment) (immediately)
8530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 3) Segment has data (so we need to ACK!) (delayed)
8540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // ... so the only time we don't need to ACK, is an empty segment that points to rcv_nxt!
8550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SendFlags sflags = sfNone;
8570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg.seq != m_rcv_nxt) {
8580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    sflags = sfImmediateAck; // (Fast Recovery)
8590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (seg.len != 0) {
8600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_ack_delay == 0) {
8610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      sflags = sfImmediateAck;
8620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
8630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      sflags = sfDelayedAck;
8640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
8670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (sflags == sfImmediateAck) {
8680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (seg.seq > m_rcv_nxt) {
8690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(LS_INFO) << "too new";
8700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (seg.seq + seg.len <= m_rcv_nxt) {
8710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(LS_INFO) << "too old";
8720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
8750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Adjust the incoming segment to fit our receive buffer
8770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg.seq < m_rcv_nxt) {
8780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 nAdjust = m_rcv_nxt - seg.seq;
8790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (nAdjust < seg.len) {
8800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      seg.seq += nAdjust;
8810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      seg.data += nAdjust;
8820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      seg.len -= nAdjust;
8830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
8840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      seg.len = 0;
8850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t available_space = 0;
8890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rbuf.GetWriteRemaining(&available_space);
8900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((seg.seq + seg.len - m_rcv_nxt) > static_cast<uint32>(available_space)) {
8920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 nAdjust = seg.seq + seg.len - m_rcv_nxt - static_cast<uint32>(available_space);
8930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (nAdjust < seg.len) {
8940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      seg.len -= nAdjust;
8950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
8960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      seg.len = 0;
8970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool bIgnoreData = (seg.flags & FLAG_CTL) || (m_shutdown != SD_NONE);
9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool bNewData = false;
9020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg.len > 0) {
9040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (bIgnoreData) {
9050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (seg.seq == m_rcv_nxt) {
9060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_rcv_nxt += seg.len;
9070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
9080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
9090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      uint32 nOffset = seg.seq - m_rcv_nxt;
9100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9112a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::StreamResult result = m_rbuf.WriteOffset(seg.data, seg.len,
9120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                          nOffset, NULL);
9132a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      ASSERT(result == rtc::SR_SUCCESS);
9142a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      RTC_UNUSED(result);
9150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (seg.seq == m_rcv_nxt) {
9170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_rbuf.ConsumeWriteBuffer(seg.len);
9180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_rcv_nxt += seg.len;
9190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_rcv_wnd -= seg.len;
9200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        bNewData = true;
9210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        RList::iterator it = m_rlist.begin();
9230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        while ((it != m_rlist.end()) && (it->seq <= m_rcv_nxt)) {
9240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          if (it->seq + it->len > m_rcv_nxt) {
9250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            sflags = sfImmediateAck; // (Fast Recovery)
9260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            uint32 nAdjust = (it->seq + it->len) - m_rcv_nxt;
9270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
9280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            LOG(LS_INFO) << "Recovered " << nAdjust << " bytes (" << m_rcv_nxt << " -> " << m_rcv_nxt + nAdjust << ")";
9290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
9300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            m_rbuf.ConsumeWriteBuffer(nAdjust);
9310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            m_rcv_nxt += nAdjust;
9320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            m_rcv_wnd -= nAdjust;
9330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          }
9340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          it = m_rlist.erase(it);
9350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
9360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
9370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
9380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "Saving " << seg.len << " bytes (" << seg.seq << " -> " << seg.seq + seg.len << ")";
9390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
9400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        RSegment rseg;
9410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        rseg.seq = seg.seq;
9420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        rseg.len = seg.len;
9430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        RList::iterator it = m_rlist.begin();
9440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        while ((it != m_rlist.end()) && (it->seq < rseg.seq)) {
9450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          ++it;
9460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
9470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_rlist.insert(it, rseg);
9480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
9490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
9500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  attemptSend(sflags);
9530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we have new data, notify the user
9550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (bNewData && m_bReadEnable) {
9560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_bReadEnable = false;
9570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_notify) {
9580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_notify->OnTcpReadable(this);
9590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
9600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //notify(evRead);
9610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
9640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PseudoTcp::transmit(const SList::iterator& seg, uint32 now) {
9670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg->xmit >= ((m_state == TCP_ESTABLISHED) ? 15 : 30)) {
9680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_VERBOSE) << "too many retransmits";
9690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
9700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9722a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  uint32 nTransmit = rtc::_min(seg->len, m_mss);
9730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  while (true) {
9750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 seq = seg->seq;
9760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8 flags = (seg->bCtrl ? FLAG_CTL : 0);
9770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    IPseudoTcpNotify::WriteResult wres = packet(seq,
9780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                flags,
9790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                seg->seq - m_snd_una,
9800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                nTransmit);
9810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (wres == IPseudoTcpNotify::WR_SUCCESS)
9830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (wres == IPseudoTcpNotify::WR_FAIL) {
9860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(LS_VERBOSE) << "packet failed";
9870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
9890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(wres == IPseudoTcpNotify::WR_TOO_LARGE);
9910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    while (true) {
9930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (PACKET_MAXIMUMS[m_msslevel + 1] == 0) {
9940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG_F(LS_VERBOSE) << "MTU too small";
9950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return false;
9960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
9970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // !?! We need to break up all outstanding and pending packets and then retransmit!?!
9980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_mss = PACKET_MAXIMUMS[++m_msslevel] - PACKET_OVERHEAD;
10000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_cwnd = 2 * m_mss; // I added this... haven't researched actual formula
10010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (m_mss < nTransmit) {
10020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        nTransmit = m_mss;
10030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        break;
10040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
10050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
10070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes";
10080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
10090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (nTransmit < seg->len) {
10120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_F(LS_VERBOSE) << "mss reduced to " << m_mss;
10130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SSegment subseg(seg->seq + nTransmit, seg->len - nTransmit, seg->bCtrl);
10150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //subseg.tstamp = seg->tstamp;
10160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    subseg.xmit = seg->xmit;
10170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    seg->len = nTransmit;
10180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SList::iterator next = seg;
10200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_slist.insert(++next, subseg);
10210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (seg->xmit == 0) {
10240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_snd_nxt += seg->len;
10250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  seg->xmit += 1;
10270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //seg->tstamp = now;
10280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_rto_base == 0) {
10290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_rto_base = now;
10300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
10330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PseudoTcp::attemptSend(SendFlags sflags) {
10360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 now = Now();
10370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (rtc::TimeDiff(now, m_lastsend) > static_cast<long>(m_rx_rto)) {
10390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_cwnd = m_mss;
10400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG
10430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool bFirst = true;
10442a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  RTC_UNUSED(bFirst);
10450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
10460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  while (true) {
10480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 cwnd = m_cwnd;
10490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((m_dup_acks == 1) || (m_dup_acks == 2)) { // Limited Transmit
10500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cwnd += m_dup_acks * m_mss;
10510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    uint32 nWindow = rtc::_min(m_snd_wnd, cwnd);
10530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 nInFlight = m_snd_nxt - m_snd_una;
10540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 nUseable = (nInFlight < nWindow) ? (nWindow - nInFlight) : 0;
10550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    size_t snd_buffered = 0;
10570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_sbuf.GetBuffered(&snd_buffered);
10580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 nAvailable =
10592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        rtc::_min(static_cast<uint32>(snd_buffered) - nInFlight, m_mss);
10600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (nAvailable > nUseable) {
10620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (nUseable * 4 < nWindow) {
10630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // RFC 813 - avoid SWS
10640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        nAvailable = 0;
10650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
10660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        nAvailable = nUseable;
10670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
10680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_VERBOSE
10710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (bFirst) {
10720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      size_t available_space = 0;
10730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_sbuf.GetWriteRemaining(&available_space);
10740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      bFirst = false;
10760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "[cwnd: " << m_cwnd
10770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << "  nWindow: " << nWindow
10780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << "  nInFlight: " << nInFlight
10790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << "  nAvailable: " << nAvailable
10800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << "  nQueued: " << snd_buffered
10810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << "  nEmpty: " << available_space
10820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << "  ssthresh: " << m_ssthresh << "]";
10830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
10850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (nAvailable == 0) {
10870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (sflags == sfNone)
10880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return;
10890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // If this is an immediate ack, or the second delayed ack
10910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if ((sflags == sfImmediateAck) || m_t_ack) {
10920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        packet(m_snd_nxt, 0, 0, 0);
10930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
10940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        m_t_ack = Now();
10950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
10960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
10970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Nagle's algorithm.
11000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If there is data already in-flight, and we haven't a full segment of
11010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // data ready to send then hold off until we get more to send, or the
11020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // in-flight data is acknowledged.
11030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_use_nagling && (m_snd_nxt > m_snd_una) && (nAvailable < m_mss))  {
11040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
11050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Find the next segment to transmit
11080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SList::iterator it = m_slist.begin();
11090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    while (it->xmit > 0) {
11100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ++it;
11110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(it != m_slist.end());
11120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SList::iterator seg = it;
11140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If the segment is too large, break it into two
11160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (seg->len > nAvailable) {
11170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SSegment subseg(seg->seq + nAvailable, seg->len - nAvailable, seg->bCtrl);
11180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      seg->len = nAvailable;
11190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_slist.insert(++it, subseg);
11200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!transmit(seg, now)) {
11230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(LS_VERBOSE) << "transmit failed";
11240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // TODO: consider closing socket
11250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
11260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    sflags = sfNone;
11290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
11330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::closedown(uint32 err) {
11340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "State: TCP_CLOSED";
11350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_state = TCP_CLOSED;
11360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_notify) {
11370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    m_notify->OnTcpClosed(this, err);
11380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //notify(evClose, err);
11400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
11430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::adjustMTU() {
11440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Determine our current mss level, so that we can adjust appropriately later
11450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (m_msslevel = 0; PACKET_MAXIMUMS[m_msslevel + 1] > 0; ++m_msslevel) {
11460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (static_cast<uint16>(PACKET_MAXIMUMS[m_msslevel]) <= m_mtu_advise) {
11470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
11480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_mss = m_mtu_advise - PACKET_OVERHEAD;
11510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // !?! Should we reset m_largest here?
11520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUGMSG >= _DBG_NORMAL
11530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes";
11540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // _DEBUGMSG
11550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Enforce minimums on ssthresh and cwnd
11562a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  m_ssthresh = rtc::_max(m_ssthresh, 2 * m_mss);
11572a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  m_cwnd = rtc::_max(m_cwnd, m_mss);
11580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool
11610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::isReceiveBufferFull() const {
11620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t available_space = 0;
11630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rbuf.GetWriteRemaining(&available_space);
11640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return !available_space;
11650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
11680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::disableWindowScale() {
11690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_support_wnd_scale = false;
11700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
11730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::queueConnectMessage() {
11742a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::ByteBuffer buf(rtc::ByteBuffer::ORDER_NETWORK);
11750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buf.WriteUInt8(CTL_CONNECT);
11770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (m_support_wnd_scale) {
11780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buf.WriteUInt8(TCP_OPT_WND_SCALE);
11790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buf.WriteUInt8(1);
11800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buf.WriteUInt8(m_rwnd_scale);
11810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11821a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  m_snd_wnd = static_cast<uint32>(buf.Length());
11831a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  queue(buf.Data(), static_cast<uint32>(buf.Length()), true);
11840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
11870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::parseOptions(const char* data, uint32 len) {
11880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::set<uint8> options_specified;
11890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // See http://www.freesoft.org/CIE/Course/Section4/8.htm for
11910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // parsing the options list.
11922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::ByteBuffer buf(data, len);
11930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  while (buf.Length()) {
11940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8 kind = TCP_OPT_EOL;
11950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buf.ReadUInt8(&kind);
11960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (kind == TCP_OPT_EOL) {
11980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // End of option list.
11990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
12000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (kind == TCP_OPT_NOOP) {
12010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // No op.
12020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      continue;
12030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
12040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Length of this option.
12060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(len != 0);
12072a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    RTC_UNUSED(len);
12080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8 opt_len = 0;
12090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buf.ReadUInt8(&opt_len);
12100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Content of this option.
12120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (opt_len <= buf.Length()) {
12130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      applyOption(kind, buf.Data(), opt_len);
12140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      buf.Consume(opt_len);
12150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
12160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_ERROR) << "Invalid option length received.";
12170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
12180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
12190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    options_specified.insert(kind);
12200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (options_specified.find(TCP_OPT_WND_SCALE) == options_specified.end()) {
12230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Peer doesn't support window scaling";
12240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (m_rwnd_scale > 0) {
12260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Peer doesn't support TCP options and window scaling.
12270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Revert receive buffer size to default value.
12280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      resizeReceiveBuffer(DEFAULT_RCV_BUF_SIZE);
12290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      m_swnd_scale = 0;
12300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
12310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
12350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::applyOption(char kind, const char* data, uint32 len) {
12360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (kind == TCP_OPT_MSS) {
12370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Peer specified MSS option which is not supported.";
12380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // TODO: Implement.
12390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (kind == TCP_OPT_WND_SCALE) {
12400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Window scale factor.
12410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // http://www.ietf.org/rfc/rfc1323.txt
12420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (len != 1) {
12430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_F(WARNING) << "Invalid window scale option received.";
12440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
12450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
12460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    applyWindowScaleOption(data[0]);
12470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
12510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::applyWindowScaleOption(uint8 scale_factor) {
12520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_swnd_scale = scale_factor;
12530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
12560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::resizeSendBuffer(uint32 new_size) {
12570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf_len = new_size;
12580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_sbuf.SetCapacity(new_size);
12590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid
12620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPseudoTcp::resizeReceiveBuffer(uint32 new_size) {
12630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint8 scale_factor = 0;
12640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Determine the scale factor such that the scaled window size can fit
12660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // in a 16-bit unsigned integer.
12670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  while (new_size > 0xFFFF) {
12680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ++scale_factor;
12690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    new_size >>= 1;
12700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Determine the proper size of the buffer.
12730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  new_size <<= scale_factor;
12740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool result = m_rbuf.SetCapacity(new_size);
12750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Make sure the new buffer is large enough to contain data in the old
12770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // buffer. This should always be true because this method is called either
12780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // before connection is established or when peers are exchanging connect
12790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // messages.
12800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(result);
12812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  RTC_UNUSED(result);
12820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rbuf_len = new_size;
12830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rwnd_scale = scale_factor;
12840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_ssthresh = new_size;
12850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t available_space = 0;
12870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  m_rbuf.GetWriteRemaining(&available_space);
12881a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  m_rcv_wnd = static_cast<uint32>(available_space);
12890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
1292