⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pseudotcp.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
📖 第 1 页 / 共 3 页
字号:
/* * libjingle * Copyright 2004--2005, Google Inc. * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions are met: * *  1. Redistributions of source code must retain the above copyright notice,  *     this list of conditions and the following disclaimer. *  2. Redistributions in binary form must reproduce the above copyright notice, *     this list of conditions and the following disclaimer in the documentation *     and/or other materials provided with the distribution. *  3. The name of the author may not be used to endorse or promote products  *     derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "talk/base/basicdefs.h"#include "talk/base/basictypes.h"#include "talk/base/byteorder.h"#include "talk/base/common.h"#include "talk/base/logging.h"#include "talk/base/socket.h"#include "talk/base/stringutils.h"#include "talk/base/time.h"#include "talk/p2p/base/pseudotcp.h"#ifdef POSIXextern "C" {#include <errno.h>}#endif // POSIX// The following logging is for detailed (packet-level) pseudotcp analysis only.#define _DBG_NONE     0#define _DBG_NORMAL   1#define _DBG_VERBOSE  2#define _DEBUGMSG _DBG_NONEnamespace cricket {//////////////////////////////////////////////////////////////////////// Network Constants//////////////////////////////////////////////////////////////////////// Standard MTUsconst uint16 PACKET_MAXIMUMS[] = {  65535,    // Theoretical maximum, Hyperchannel  32000,    // Nothing  17914,    // 16Mb IBM Token Ring  8166,   // IEEE 802.4  //4464,   // IEEE 802.5 (4Mb max)  4352,   // FDDI  //2048,   // Wideband Network  2002,   // IEEE 802.5 (4Mb recommended)  //1536,   // Expermental Ethernet Networks  //1500,   // Ethernet, Point-to-Point (default)  1492,   // IEEE 802.3  1006,   // SLIP, ARPANET  //576,    // X.25 Networks  //544,    // DEC IP Portal  //512,    // NETBIOS  508,    // IEEE 802/Source-Rt Bridge, ARCNET  296,    // Point-to-Point (low delay)  //68,     // Official minimum  0,      // End of list marker};const uint32 MAX_PACKET = 65535;// Note: we removed lowest level because packet overhead was larger!const uint32 MIN_PACKET = 296;const uint32 IP_HEADER_SIZE = 20; // (+ up to 40 bytes of options?)const uint32 ICMP_HEADER_SIZE = 8;const uint32 UDP_HEADER_SIZE = 8;// TODO: Make JINGLE_HEADER_SIZE transparent to this code?const uint32 JINGLE_HEADER_SIZE = 64; // when relay framing is in use//////////////////////////////////////////////////////////////////////// Global Constants and Functions//////////////////////////////////////////////////////////////////////////    0                   1                   2                   3   //    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 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//  0 |                      Conversation Number                      |//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//  4 |                        Sequence Number                        |//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//  8 |                     Acknowledgment Number                     |//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//    |               |   |U|A|P|R|S|F|                               |// 12 |    Control    |   |R|C|S|S|Y|I|            Window             |//    |               |   |G|K|H|T|N|N|                               |//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+// 16 |                       Timestamp sending                       |//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+// 20 |                      Timestamp receiving                      |//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+// 24 |                             data                              |//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+////////////////////////////////////////////////////////////////////////#define PSEUDO_KEEPALIVE 0const uint32 MAX_SEQ = 0xFFFFFFFF;const uint32 HEADER_SIZE = 24;const uint32 PACKET_OVERHEAD = HEADER_SIZE + UDP_HEADER_SIZE + IP_HEADER_SIZE + JINGLE_HEADER_SIZE;const uint32 MIN_RTO   =   250; // 250 ms (RFC1122, Sec 4.2.3.1 "fractions of a second")const uint32 DEF_RTO   =  3000; // 3 seconds (RFC1122, Sec 4.2.3.1)const uint32 MAX_RTO   = 60000; // 60 secondsconst uint32 ACK_DELAY =   100; // 100 millisecondsconst uint8 FLAG_CTL = 0x02;const uint8 FLAG_RST = 0x04;const uint8 CTL_CONNECT = 0;//const uint8 CTL_REDIRECT = 1;const uint8 CTL_EXTRA = 255;/*const uint8 FLAG_FIN = 0x01;const uint8 FLAG_SYN = 0x02;const uint8 FLAG_ACK = 0x10;*/const uint32 CTRL_BOUND = 0x80000000;const long DEFAULT_TIMEOUT = 4000; // If there are no pending clocks, wake up every 4 secondsconst long CLOSED_TIMEOUT = 60 * 1000; // If the connection is closed, once per minute#if PSEUDO_KEEPALIVE// !?! Rethink these timesconst uint32 IDLE_PING = 20 * 1000; // 20 seconds (note: WinXP SP2 firewall udp timeout is 90 seconds)const uint32 IDLE_TIMEOUT = 90 * 1000; // 90 seconds;#endif // PSEUDO_KEEPALIVE//////////////////////////////////////////////////////////////////////// Helper Functions//////////////////////////////////////////////////////////////////////inline void long_to_bytes(uint32 val, void* buf) {  *static_cast<uint32*>(buf) = talk_base::HostToNetwork32(val);}inline void short_to_bytes(uint16 val, void* buf) {  *static_cast<uint16*>(buf) = talk_base::HostToNetwork16(val);}inline uint32 bytes_to_long(const void* buf) {  return talk_base::NetworkToHost32(*static_cast<const uint32*>(buf));}inline uint16 bytes_to_short(const void* buf) {  return talk_base::NetworkToHost16(*static_cast<const uint16*>(buf));}uint32 bound(uint32 lower, uint32 middle, uint32 upper) {  return talk_base::_min(talk_base::_max(lower, middle), upper);}//////////////////////////////////////////////////////////////////////// Debugging Statistics//////////////////////////////////////////////////////////////////////#if 0  // Not used yetenum Stat {  S_SENT_PACKET,   // All packet sends  S_RESENT_PACKET, // All packet sends that are retransmits  S_RECV_PACKET,   // All packet receives  S_RECV_NEW,      // All packet receives that are too new  S_RECV_OLD,      // All packet receives that are too old  S_NUM_STATS};const char* const STAT_NAMES[S_NUM_STATS] = {  "snt",  "snt-r",  "rcv"  "rcv-n",  "rcv-o"};int g_stats[S_NUM_STATS];inline void Incr(Stat s) { ++g_stats[s]; }void ReportStats() {  char buffer[256];  size_t len = 0;  for (int i=0; i<S_NUM_STATS; ++i) {    len += talk_base::sprintfn(buffer, ARRAY_SIZE(buffer), "%s%s:%d",                               (i == 0) ? "" : ",", STAT_NAMES[i], g_stats[i]);    g_stats[i] = 0;  }  LOG(LS_INFO) << "Stats[" << buffer << "]";}#endif//////////////////////////////////////////////////////////////////////// PseudoTcp//////////////////////////////////////////////////////////////////////uint32 PseudoTcp::Now() {#if 0  // Use this to synchronize timers with logging timestamps (easier debug)  return talk_base::ElapsedTime();#else  return talk_base::Time();#endif}PseudoTcp::PseudoTcp(IPseudoTcpNotify * notify, uint32 conv)    : m_notify(notify), m_shutdown(SD_NONE), m_error(0) {  // Sanity check on buffer sizes (needed for OnTcpWriteable notification logic)  ASSERT(sizeof(m_rbuf) + MIN_PACKET < sizeof(m_sbuf));  uint32 now = Now();  m_state = TCP_LISTEN;  m_conv = conv;  m_rcv_wnd = sizeof(m_rbuf);  m_snd_nxt = m_slen = 0;  m_snd_wnd = 1;  m_snd_una = m_rcv_nxt = m_rlen = 0;  m_bReadEnable = true;  m_bWriteEnable = false;  m_t_ack = 0;  m_msslevel = 0;  m_largest = 0;  ASSERT(MIN_PACKET > PACKET_OVERHEAD);  m_mss = MIN_PACKET - PACKET_OVERHEAD;  m_mtu_advise = MAX_PACKET;  m_rto_base = 0;  m_cwnd = 2 * m_mss;  m_ssthresh = sizeof(m_rbuf);  m_lastrecv = m_lastsend = m_lasttraffic = now;  m_bOutgoing = false;  m_dup_acks = 0;  m_recover = 0;  m_ts_recent = m_ts_lastack = 0;  m_rx_rto = DEF_RTO;  m_rx_srtt = m_rx_rttvar = 0;}PseudoTcp::~PseudoTcp() {}intPseudoTcp::Connect() {  if (m_state != TCP_LISTEN) {    m_error = EINVAL;    return -1;  }  m_state = TCP_SYN_SENT;  LOG(LS_INFO) << "State: TCP_SYN_SENT";  char buffer[1];  buffer[0] = CTL_CONNECT;  queue(buffer, 1, true);  attemptSend();  return 0;}voidPseudoTcp::NotifyMTU(uint16 mtu) {  m_mtu_advise = mtu;  if (m_state == TCP_ESTABLISHED) {    adjustMTU();  }}voidPseudoTcp::NotifyClock(uint32 now) {  if (m_state == TCP_CLOSED)    return;    // Check if it's time to retransmit a segment  if (m_rto_base && (talk_base::TimeDiff(m_rto_base + m_rx_rto, now) <= 0)) {    if (m_slist.empty()) {      ASSERT(false);    } else {      // Note: (m_slist.front().xmit == 0)) {      // retransmit segments#if _DEBUGMSG >= _DBG_NORMAL      LOG(LS_INFO) << "timeout retransmit (rto: " << m_rx_rto                   << ") (rto_base: " << m_rto_base                   << ") (now: " << now                   << ") (dup_acks: " << static_cast<unsigned>(m_dup_acks)                   << ")";#endif // _DEBUGMSG      if (!transmit(m_slist.begin(), now)) {        closedown(ECONNABORTED);        return;      }      uint32 nInFlight = m_snd_nxt - m_snd_una;      m_ssthresh = talk_base::_max(nInFlight / 2, 2 * m_mss);      //LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << "  nInFlight: " << nInFlight << "  m_mss: " << m_mss;      m_cwnd = m_mss;      // Back off retransmit timer.  Note: the limit is lower when connecting.      uint32 rto_limit = (m_state < TCP_ESTABLISHED) ? DEF_RTO : MAX_RTO;      m_rx_rto = talk_base::_min(rto_limit, m_rx_rto * 2);      m_rto_base = now;    }  }    // Check if it's time to probe closed windows  if ((m_snd_wnd == 0)         && (talk_base::TimeDiff(m_lastsend + m_rx_rto, now) <= 0)) {    if (talk_base::TimeDiff(now, m_lastrecv) >= 15000) {      closedown(ECONNABORTED);      return;    }    // probe the window    packet(m_snd_nxt - 1, 0, 0, 0);    m_lastsend = now;    // back off retransmit timer    m_rx_rto = talk_base::_min(MAX_RTO, m_rx_rto * 2);  }  // Check if it's time to send delayed acks  if (m_t_ack && (talk_base::TimeDiff(m_t_ack + ACK_DELAY, now) <= 0)) {    packet(m_snd_nxt, 0, 0, 0);  }#if PSEUDO_KEEPALIVE  // Check for idle timeout  if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lastrecv + IDLE_TIMEOUT, now) <= 0)) {    closedown(ECONNABORTED);    return;  }  // Check for ping timeout (to keep udp mapping open)  if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3/2 : IDLE_PING), now) <= 0)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -