1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef TALK_P2P_BASE_PSEUDOTCP_H_ 29 #define TALK_P2P_BASE_PSEUDOTCP_H_ 30 31 #include <list> 32 33 #include "talk/base/basictypes.h" 34 #include "talk/base/stream.h" 35 36 namespace cricket { 37 38 ////////////////////////////////////////////////////////////////////// 39 // IPseudoTcpNotify 40 ////////////////////////////////////////////////////////////////////// 41 42 class PseudoTcp; 43 44 class IPseudoTcpNotify { 45 public: 46 // Notification of tcp events 47 virtual void OnTcpOpen(PseudoTcp* tcp) = 0; 48 virtual void OnTcpReadable(PseudoTcp* tcp) = 0; 49 virtual void OnTcpWriteable(PseudoTcp* tcp) = 0; 50 virtual void OnTcpClosed(PseudoTcp* tcp, uint32 error) = 0; 51 52 // Write the packet onto the network 53 enum WriteResult { WR_SUCCESS, WR_TOO_LARGE, WR_FAIL }; 54 virtual WriteResult TcpWritePacket(PseudoTcp* tcp, 55 const char* buffer, size_t len) = 0; 56 57 protected: 58 virtual ~IPseudoTcpNotify() {} 59 }; 60 61 ////////////////////////////////////////////////////////////////////// 62 // PseudoTcp 63 ////////////////////////////////////////////////////////////////////// 64 65 class PseudoTcp { 66 public: 67 static uint32 Now(); 68 69 PseudoTcp(IPseudoTcpNotify* notify, uint32 conv); 70 virtual ~PseudoTcp(); 71 72 int Connect(); 73 int Recv(char* buffer, size_t len); 74 int Send(const char* buffer, size_t len); 75 void Close(bool force); 76 int GetError(); 77 78 enum TcpState { 79 TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECEIVED, TCP_ESTABLISHED, TCP_CLOSED 80 }; 81 TcpState State() const { return m_state; } 82 83 // Call this when the PMTU changes. 84 void NotifyMTU(uint16 mtu); 85 86 // Call this based on timeout value returned from GetNextClock. 87 // It's ok to call this too frequently. 88 void NotifyClock(uint32 now); 89 90 // Call this whenever a packet arrives. 91 // Returns true if the packet was processed successfully. 92 bool NotifyPacket(const char * buffer, size_t len); 93 94 // Call this to determine the next time NotifyClock should be called. 95 // Returns false if the socket is ready to be destroyed. 96 bool GetNextClock(uint32 now, long& timeout); 97 98 // Call these to get/set option values to tailor this PseudoTcp 99 // instance's behaviour for the kind of data it will carry. 100 // If an unrecognized option is set or got, an assertion will fire. 101 // 102 // Setting options for OPT_RCVBUF or OPT_SNDBUF after Connect() is called 103 // will result in an assertion. 104 enum Option { 105 OPT_NODELAY, // Whether to enable Nagle's algorithm (0 == off) 106 OPT_ACKDELAY, // The Delayed ACK timeout (0 == off). 107 OPT_RCVBUF, // Set the receive buffer size, in bytes. 108 OPT_SNDBUF, // Set the send buffer size, in bytes. 109 }; 110 void GetOption(Option opt, int* value); 111 void SetOption(Option opt, int value); 112 113 // Returns current congestion window in bytes. 114 uint32 GetCongestionWindow() const; 115 116 // Returns amount of data in bytes that has been sent, but haven't 117 // been acknowledged. 118 uint32 GetBytesInFlight() const; 119 120 // Returns number of bytes that were written in buffer and haven't 121 // been sent. 122 uint32 GetBytesBufferedNotSent() const; 123 124 // Returns current round-trip time estimate in milliseconds. 125 uint32 GetRoundTripTimeEstimateMs() const; 126 127 protected: 128 enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck }; 129 130 struct Segment { 131 uint32 conv, seq, ack; 132 uint8 flags; 133 uint16 wnd; 134 const char * data; 135 uint32 len; 136 uint32 tsval, tsecr; 137 }; 138 139 struct SSegment { 140 SSegment(uint32 s, uint32 l, bool c) 141 : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) { 142 } 143 uint32 seq, len; 144 //uint32 tstamp; 145 uint8 xmit; 146 bool bCtrl; 147 }; 148 typedef std::list<SSegment> SList; 149 150 struct RSegment { 151 uint32 seq, len; 152 }; 153 154 uint32 queue(const char* data, uint32 len, bool bCtrl); 155 156 // Creates a packet and submits it to the network. This method can either 157 // send payload or just an ACK packet. 158 // 159 // |seq| is the sequence number of this packet. 160 // |flags| is the flags for sending this packet. 161 // |offset| is the offset to read from |m_sbuf|. 162 // |len| is the number of bytes to read from |m_sbuf| as payload. If this 163 // value is 0 then this is an ACK packet, otherwise this packet has payload. 164 IPseudoTcpNotify::WriteResult packet(uint32 seq, uint8 flags, 165 uint32 offset, uint32 len); 166 bool parse(const uint8* buffer, uint32 size); 167 168 void attemptSend(SendFlags sflags = sfNone); 169 170 void closedown(uint32 err = 0); 171 172 bool clock_check(uint32 now, long& nTimeout); 173 174 bool process(Segment& seg); 175 bool transmit(const SList::iterator& seg, uint32 now); 176 177 void adjustMTU(); 178 179 protected: 180 // This method is used in test only to query receive buffer state. 181 bool isReceiveBufferFull() const; 182 183 // This method is only used in tests, to disable window scaling 184 // support for testing backward compatibility. 185 void disableWindowScale(); 186 187 private: 188 // Queue the connect message with TCP options. 189 void queueConnectMessage(); 190 191 // Parse TCP options in the header. 192 void parseOptions(const char* data, uint32 len); 193 194 // Apply a TCP option that has been read from the header. 195 void applyOption(char kind, const char* data, uint32 len); 196 197 // Apply window scale option. 198 void applyWindowScaleOption(uint8 scale_factor); 199 200 // Resize the send buffer with |new_size| in bytes. 201 void resizeSendBuffer(uint32 new_size); 202 203 // Resize the receive buffer with |new_size| in bytes. This call adjusts 204 // window scale factor |m_swnd_scale| accordingly. 205 void resizeReceiveBuffer(uint32 new_size); 206 207 IPseudoTcpNotify* m_notify; 208 enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown; 209 int m_error; 210 211 // TCB data 212 TcpState m_state; 213 uint32 m_conv; 214 bool m_bReadEnable, m_bWriteEnable, m_bOutgoing; 215 uint32 m_lasttraffic; 216 217 // Incoming data 218 typedef std::list<RSegment> RList; 219 RList m_rlist; 220 uint32 m_rbuf_len, m_rcv_nxt, m_rcv_wnd, m_lastrecv; 221 uint8 m_rwnd_scale; // Window scale factor. 222 talk_base::FifoBuffer m_rbuf; 223 224 // Outgoing data 225 SList m_slist; 226 uint32 m_sbuf_len, m_snd_nxt, m_snd_wnd, m_lastsend, m_snd_una; 227 uint8 m_swnd_scale; // Window scale factor. 228 talk_base::FifoBuffer m_sbuf; 229 230 // Maximum segment size, estimated protocol level, largest segment sent 231 uint32 m_mss, m_msslevel, m_largest, m_mtu_advise; 232 // Retransmit timer 233 uint32 m_rto_base; 234 235 // Timestamp tracking 236 uint32 m_ts_recent, m_ts_lastack; 237 238 // Round-trip calculation 239 uint32 m_rx_rttvar, m_rx_srtt, m_rx_rto; 240 241 // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs 242 uint32 m_ssthresh, m_cwnd; 243 uint8 m_dup_acks; 244 uint32 m_recover; 245 uint32 m_t_ack; 246 247 // Configuration options 248 bool m_use_nagling; 249 uint32 m_ack_delay; 250 251 // This is used by unit tests to test backward compatibility of 252 // PseudoTcp implementations that don't support window scaling. 253 bool m_support_wnd_scale; 254 }; 255 256 } // namespace cricket 257 258 #endif // TALK_P2P_BASE_PSEUDOTCP_H_ 259