• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
35  namespace cricket {
36  
37  //////////////////////////////////////////////////////////////////////
38  // IPseudoTcpNotify
39  //////////////////////////////////////////////////////////////////////
40  
41  class PseudoTcp;
42  
43  class IPseudoTcpNotify {
44   public:
~IPseudoTcpNotify()45    virtual ~IPseudoTcpNotify() {}
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  
58  //////////////////////////////////////////////////////////////////////
59  // PseudoTcp
60  //////////////////////////////////////////////////////////////////////
61  
62  class PseudoTcp {
63   public:
64    static uint32 Now();
65  
66    PseudoTcp(IPseudoTcpNotify* notify, uint32 conv);
67    virtual ~PseudoTcp();
68  
69    int Connect();
70    int Recv(char* buffer, size_t len);
71    int Send(const char* buffer, size_t len);
72    void Close(bool force);
73    int GetError();
74  
75    enum TcpState {
76      TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECEIVED, TCP_ESTABLISHED, TCP_CLOSED
77    };
State()78    TcpState State() const { return m_state; }
79  
80    // Call this when the PMTU changes.
81    void NotifyMTU(uint16 mtu);
82  
83    // Call this based on timeout value returned from GetNextClock.
84    // It's ok to call this too frequently.
85    void NotifyClock(uint32 now);
86  
87    // Call this whenever a packet arrives.
88    // Returns true if the packet was processed successfully.
89    bool NotifyPacket(const char * buffer, size_t len);
90  
91    // Call this to determine the next time NotifyClock should be called.
92    // Returns false if the socket is ready to be destroyed.
93    bool GetNextClock(uint32 now, long& timeout);
94  
95    // Call these to get/set option values to tailor this PseudoTcp
96    // instance's behaviour for the kind of data it will carry.
97    // If an unrecognized option is set or got, an assertion will fire.
98    enum Option {
99      OPT_NODELAY,      // Whether to enable Nagle's algorithm (0 == off)
100      OPT_ACKDELAY,     // The Delayed ACK timeout (0 == off).
101      //kOptRcvBuf,     // Set the receive buffer size, in bytes.
102      //kOptSndBuf,     // Set the send buffer size, in bytes.
103    };
104    void GetOption(Option opt, int* value);
105    void SetOption(Option opt, int value);
106  
107   protected:
108    enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck };
109    enum {
110      // Note: can't go as high as 1024 * 64, because of uint16 precision
111      kRcvBufSize = 1024 * 60,
112      // Note: send buffer should be larger to make sure we can always fill the
113      // receiver window
114      kSndBufSize = 1024 * 90
115    };
116  
117    struct Segment {
118      uint32 conv, seq, ack;
119      uint8 flags;
120      uint16 wnd;
121      const char * data;
122      uint32 len;
123      uint32 tsval, tsecr;
124    };
125  
126    struct SSegment {
SSegmentSSegment127      SSegment(uint32 s, uint32 l, bool c)
128          : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) {
129      }
130      uint32 seq, len;
131      //uint32 tstamp;
132      uint8 xmit;
133      bool bCtrl;
134    };
135    typedef std::list<SSegment> SList;
136  
137    struct RSegment {
138      uint32 seq, len;
139    };
140  
141    uint32 queue(const char* data, uint32 len, bool bCtrl);
142  
143    IPseudoTcpNotify::WriteResult packet(uint32 seq, uint8 flags,
144                                         const char* data, uint32 len);
145    bool parse(const uint8* buffer, uint32 size);
146  
147    void attemptSend(SendFlags sflags = sfNone);
148  
149    void closedown(uint32 err = 0);
150  
151    bool clock_check(uint32 now, long& nTimeout);
152  
153    bool process(Segment& seg);
154    bool transmit(const SList::iterator& seg, uint32 now);
155  
156    void adjustMTU();
157  
158   private:
159    IPseudoTcpNotify* m_notify;
160    enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown;
161    int m_error;
162  
163    // TCB data
164    TcpState m_state;
165    uint32 m_conv;
166    bool m_bReadEnable, m_bWriteEnable, m_bOutgoing;
167    uint32 m_lasttraffic;
168  
169    // Incoming data
170    typedef std::list<RSegment> RList;
171    RList m_rlist;
172    char m_rbuf[kRcvBufSize];
173    uint32 m_rcv_nxt, m_rcv_wnd, m_rlen, m_lastrecv;
174  
175    // Outgoing data
176    SList m_slist;
177    char m_sbuf[kSndBufSize];
178    uint32 m_snd_nxt, m_snd_wnd, m_slen, m_lastsend, m_snd_una;
179    // Maximum segment size, estimated protocol level, largest segment sent
180    uint32 m_mss, m_msslevel, m_largest, m_mtu_advise;
181    // Retransmit timer
182    uint32 m_rto_base;
183  
184    // Timestamp tracking
185    uint32 m_ts_recent, m_ts_lastack;
186  
187    // Round-trip calculation
188    uint32 m_rx_rttvar, m_rx_srtt, m_rx_rto;
189  
190    // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs
191    uint32 m_ssthresh, m_cwnd;
192    uint8 m_dup_acks;
193    uint32 m_recover;
194    uint32 m_t_ack;
195  
196    // Configuration options
197    bool m_use_nagling;
198    uint32 m_ack_delay;
199  };
200  
201  }  // namespace cricket
202  
203  #endif  // TALK_P2P_BASE_PSEUDOTCP_H_
204