Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #ifndef WEBRTC_P2P_BASE_PSEUDOTCP_H_
     12 #define WEBRTC_P2P_BASE_PSEUDOTCP_H_
     13 
     14 #include <list>
     15 
     16 #include "webrtc/base/basictypes.h"
     17 #include "webrtc/base/stream.h"
     18 
     19 namespace cricket {
     20 
     21 //////////////////////////////////////////////////////////////////////
     22 // IPseudoTcpNotify
     23 //////////////////////////////////////////////////////////////////////
     24 
     25 class PseudoTcp;
     26 
     27 class IPseudoTcpNotify {
     28  public:
     29   // Notification of tcp events
     30   virtual void OnTcpOpen(PseudoTcp* tcp) = 0;
     31   virtual void OnTcpReadable(PseudoTcp* tcp) = 0;
     32   virtual void OnTcpWriteable(PseudoTcp* tcp) = 0;
     33   virtual void OnTcpClosed(PseudoTcp* tcp, uint32_t error) = 0;
     34 
     35   // Write the packet onto the network
     36   enum WriteResult { WR_SUCCESS, WR_TOO_LARGE, WR_FAIL };
     37   virtual WriteResult TcpWritePacket(PseudoTcp* tcp,
     38                                      const char* buffer, size_t len) = 0;
     39 
     40  protected:
     41   virtual ~IPseudoTcpNotify() {}
     42 };
     43 
     44 //////////////////////////////////////////////////////////////////////
     45 // PseudoTcp
     46 //////////////////////////////////////////////////////////////////////
     47 
     48 class PseudoTcp {
     49  public:
     50   static uint32_t Now();
     51 
     52   PseudoTcp(IPseudoTcpNotify* notify, uint32_t conv);
     53   virtual ~PseudoTcp();
     54 
     55   int Connect();
     56   int Recv(char* buffer, size_t len);
     57   int Send(const char* buffer, size_t len);
     58   void Close(bool force);
     59   int GetError();
     60 
     61   enum TcpState {
     62     TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECEIVED, TCP_ESTABLISHED, TCP_CLOSED
     63   };
     64   TcpState State() const { return m_state; }
     65 
     66   // Call this when the PMTU changes.
     67   void NotifyMTU(uint16_t mtu);
     68 
     69   // Call this based on timeout value returned from GetNextClock.
     70   // It's ok to call this too frequently.
     71   void NotifyClock(uint32_t now);
     72 
     73   // Call this whenever a packet arrives.
     74   // Returns true if the packet was processed successfully.
     75   bool NotifyPacket(const char * buffer, size_t len);
     76 
     77   // Call this to determine the next time NotifyClock should be called.
     78   // Returns false if the socket is ready to be destroyed.
     79   bool GetNextClock(uint32_t now, long& timeout);
     80 
     81   // Call these to get/set option values to tailor this PseudoTcp
     82   // instance's behaviour for the kind of data it will carry.
     83   // If an unrecognized option is set or got, an assertion will fire.
     84   //
     85   // Setting options for OPT_RCVBUF or OPT_SNDBUF after Connect() is called
     86   // will result in an assertion.
     87   enum Option {
     88     OPT_NODELAY,      // Whether to enable Nagle's algorithm (0 == off)
     89     OPT_ACKDELAY,     // The Delayed ACK timeout (0 == off).
     90     OPT_RCVBUF,       // Set the receive buffer size, in bytes.
     91     OPT_SNDBUF,       // Set the send buffer size, in bytes.
     92   };
     93   void GetOption(Option opt, int* value);
     94   void SetOption(Option opt, int value);
     95 
     96   // Returns current congestion window in bytes.
     97   uint32_t GetCongestionWindow() const;
     98 
     99   // Returns amount of data in bytes that has been sent, but haven't
    100   // been acknowledged.
    101   uint32_t GetBytesInFlight() const;
    102 
    103   // Returns number of bytes that were written in buffer and haven't
    104   // been sent.
    105   uint32_t GetBytesBufferedNotSent() const;
    106 
    107   // Returns current round-trip time estimate in milliseconds.
    108   uint32_t GetRoundTripTimeEstimateMs() const;
    109 
    110  protected:
    111   enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck };
    112 
    113   struct Segment {
    114     uint32_t conv, seq, ack;
    115     uint8_t flags;
    116     uint16_t wnd;
    117     const char * data;
    118     uint32_t len;
    119     uint32_t tsval, tsecr;
    120   };
    121 
    122   struct SSegment {
    123     SSegment(uint32_t s, uint32_t l, bool c)
    124         : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) {}
    125     uint32_t seq, len;
    126     // uint32_t tstamp;
    127     uint8_t xmit;
    128     bool bCtrl;
    129   };
    130   typedef std::list<SSegment> SList;
    131 
    132   struct RSegment {
    133     uint32_t seq, len;
    134   };
    135 
    136   uint32_t queue(const char* data, uint32_t len, bool bCtrl);
    137 
    138   // Creates a packet and submits it to the network. This method can either
    139   // send payload or just an ACK packet.
    140   //
    141   // |seq| is the sequence number of this packet.
    142   // |flags| is the flags for sending this packet.
    143   // |offset| is the offset to read from |m_sbuf|.
    144   // |len| is the number of bytes to read from |m_sbuf| as payload. If this
    145   // value is 0 then this is an ACK packet, otherwise this packet has payload.
    146   IPseudoTcpNotify::WriteResult packet(uint32_t seq,
    147                                        uint8_t flags,
    148                                        uint32_t offset,
    149                                        uint32_t len);
    150   bool parse(const uint8_t* buffer, uint32_t size);
    151 
    152   void attemptSend(SendFlags sflags = sfNone);
    153 
    154   void closedown(uint32_t err = 0);
    155 
    156   bool clock_check(uint32_t now, long& nTimeout);
    157 
    158   bool process(Segment& seg);
    159   bool transmit(const SList::iterator& seg, uint32_t now);
    160 
    161   void adjustMTU();
    162 
    163  protected:
    164   // This method is used in test only to query receive buffer state.
    165   bool isReceiveBufferFull() const;
    166 
    167   // This method is only used in tests, to disable window scaling
    168   // support for testing backward compatibility.
    169   void disableWindowScale();
    170 
    171  private:
    172   // Queue the connect message with TCP options.
    173   void queueConnectMessage();
    174 
    175   // Parse TCP options in the header.
    176   void parseOptions(const char* data, uint32_t len);
    177 
    178   // Apply a TCP option that has been read from the header.
    179   void applyOption(char kind, const char* data, uint32_t len);
    180 
    181   // Apply window scale option.
    182   void applyWindowScaleOption(uint8_t scale_factor);
    183 
    184   // Resize the send buffer with |new_size| in bytes.
    185   void resizeSendBuffer(uint32_t new_size);
    186 
    187   // Resize the receive buffer with |new_size| in bytes. This call adjusts
    188   // window scale factor |m_swnd_scale| accordingly.
    189   void resizeReceiveBuffer(uint32_t new_size);
    190 
    191   IPseudoTcpNotify* m_notify;
    192   enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown;
    193   int m_error;
    194 
    195   // TCB data
    196   TcpState m_state;
    197   uint32_t m_conv;
    198   bool m_bReadEnable, m_bWriteEnable, m_bOutgoing;
    199   uint32_t m_lasttraffic;
    200 
    201   // Incoming data
    202   typedef std::list<RSegment> RList;
    203   RList m_rlist;
    204   uint32_t m_rbuf_len, m_rcv_nxt, m_rcv_wnd, m_lastrecv;
    205   uint8_t m_rwnd_scale;  // Window scale factor.
    206   rtc::FifoBuffer m_rbuf;
    207 
    208   // Outgoing data
    209   SList m_slist;
    210   uint32_t m_sbuf_len, m_snd_nxt, m_snd_wnd, m_lastsend, m_snd_una;
    211   uint8_t m_swnd_scale;  // Window scale factor.
    212   rtc::FifoBuffer m_sbuf;
    213 
    214   // Maximum segment size, estimated protocol level, largest segment sent
    215   uint32_t m_mss, m_msslevel, m_largest, m_mtu_advise;
    216   // Retransmit timer
    217   uint32_t m_rto_base;
    218 
    219   // Timestamp tracking
    220   uint32_t m_ts_recent, m_ts_lastack;
    221 
    222   // Round-trip calculation
    223   uint32_t m_rx_rttvar, m_rx_srtt, m_rx_rto;
    224 
    225   // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs
    226   uint32_t m_ssthresh, m_cwnd;
    227   uint8_t m_dup_acks;
    228   uint32_t m_recover;
    229   uint32_t m_t_ack;
    230 
    231   // Configuration options
    232   bool m_use_nagling;
    233   uint32_t m_ack_delay;
    234 
    235   // This is used by unit tests to test backward compatibility of
    236   // PseudoTcp implementations that don't support window scaling.
    237   bool m_support_wnd_scale;
    238 };
    239 
    240 }  // namespace cricket
    241 
    242 #endif  // WEBRTC_P2P_BASE_PSEUDOTCP_H_
    243