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