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

📄 tcpstate.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************//*                                                                     *//*   Module:  tcp_ip/tcp/tcpstate.c                                    *//*   Release: 2001.3                                                   *//*   Version: 2001.0                                                   *//*   Purpose: TCP Input State Machine Implementation                   *//*                                                                     *//*---------------------------------------------------------------------*//*                                                                     *//*               Copyright 2001, Blunk Microsystems                    *//*                      ALL RIGHTS RESERVED                            *//*                                                                     *//*   Licensees have the non-exclusive right to use, modify, or extract *//*   this computer program for software development at a single site.  *//*   This program may be resold or disseminated in executable format   *//*   only. The source code may not be redistributed or resold.         *//*                                                                     *//***********************************************************************/#include "../tcp_ipp.h"#include "tcp.h"#include "../ip/ip.h"/***********************************************************************//* Configuration                                                       *//***********************************************************************/#define FAST_RXMIT_THRES    3   /* fast retransmit threshold *//***********************************************************************//* Function Prototypes                                                 *//***********************************************************************/static void closed(void);static void listens(void);static void syn_sent(void);static void syn_rcvd(void);static void established(void);static void closing(void);static void fin_wait1(void);static void fin_wait2(void);static void close_wait(void);static void last_ack(void);static void time_wait(void);static void set_time_wait(void);static int  ack_and_win(void);/***********************************************************************//* Global Variable Definitions                                         *//***********************************************************************/void (*TcpSwitch[])(void) ={  NULL,         /* SS_FREE */  closed,       /* SS_CLOSED */  listens,      /* SS_LISTEN */  syn_sent,     /* SS_SYNSENT */  syn_rcvd,     /* SS_SYNRCVD */  established,  /* SS_ESTABLISHED */  fin_wait1,    /* SS_FINWAIT1 */  fin_wait2,    /* SS_FINWAIT2 */  close_wait,   /* SS_CLOSEWAIT */  last_ack,     /* SS_LASTACK */  closing,      /* SS_CLOSING */  time_wait,    /* SS_TIMEWAIT */};/***********************************************************************//* Local TCP State Function Definitions                                *//***********************************************************************//***********************************************************************//*      closed: Do CLOSED state processing                             *//*                                                                     *//***********************************************************************/static void closed(void){  /*-------------------------------------------------------------------*/  /* Any incoming segment generates a TCP reset.                       */  /*-------------------------------------------------------------------*/  TcpReset();}/***********************************************************************//*     listens: Do LISTEN state processing                             *//*                                                                     *//***********************************************************************/static void listens(void){  SOCKET newsock;  Route *route;  uint mss;  /*-------------------------------------------------------------------*/  /* Ignore resets because no connection exists.                       */  /*-------------------------------------------------------------------*/  if (Net.Tcp->flags & TCPF_RST)    return;  /*-------------------------------------------------------------------*/  /* Send RESET unless incoming packet contains SYN and no ACK.        */  /*-------------------------------------------------------------------*/  if ((Net.Tcp->flags & TCPF_ACK) || !(Net.Tcp->flags & TCPF_SYN))  {    TcpReset();    return;  }  /*-------------------------------------------------------------------*/  /* Get new TCP socket and begin initializing it.                     */  /*-------------------------------------------------------------------*/  newsock = TcpNewSock(WITH_BUFS);  if (newsock == NULL)    return;  ++Stats.TcpPassiveOpens;  newsock->flags = (Sock->flags & SF_INHERITED) | TCPF_SYN | TCPF_ACK;  newsock->state = SS_SYNRCVD;  newsock->connect_timeo = Sock->connect_timeo;  /*-------------------------------------------------------------------*/  /* Reserve parent until child is deleted or becomes established.     */  /*-------------------------------------------------------------------*/  ++Sock->reserve_cnt;  newsock->psock = Sock;  /*-------------------------------------------------------------------*/  /* Copy IP addresses and port numbers to the new socket.             */  /*-------------------------------------------------------------------*/  newsock->remote.sin_addr.s_addr = Net.Ip->src_ip;  newsock->remote.sin_port = Net.Tcp->src_port;  newsock->local.sin_addr.s_addr = Net.Ip->dst_ip;  newsock->local.sin_port = Net.Tcp->dst_port;  /*-------------------------------------------------------------------*/  /* Determine maximum receive segment size.                           */  /*-------------------------------------------------------------------*/  route = RtSearch(Net.Ip->src_ip);  if (route == NULL)    mss = 536; /* RFC 1122 */  else  {    mss = route->ni->mtu - (IPMHLEN + TCPMHLEN);    if (mss > (newsock->rb_size >> 1))      mss = newsock->rb_size >> 1;  }  newsock->rcv_mss = mss;  /*-------------------------------------------------------------------*/  /* Send MSS should have come to parent. If not, use receive MSS.     */  /*-------------------------------------------------------------------*/  if (Sock->snd_mss)  {    newsock->snd_mss = min(Sock->snd_mss, mss);    Sock->snd_mss = 0; /* reset server smss */  }  else    newsock->snd_mss = mss;  /*-------------------------------------------------------------------*/  /* Initialize other socket data.                                     */  /*-------------------------------------------------------------------*/  newsock->snd_cwnd = newsock->snd_mss;  newsock->rd_nxt = newsock->rcv_nxt = Net.Tcp->seq_num + 1;  newsock->snd_window = Net.Tcp->window;  newsock->lw_seq = Net.Tcp->seq_num;  /*-------------------------------------------------------------------*/  /* Initiate new socket's SYN response and acknowledgment.            */  /*-------------------------------------------------------------------*/  TcpTryOut(newsock);  /*-------------------------------------------------------------------*/  /* Start SYN_RCVD timer to expire after timeout.                     */  /*-------------------------------------------------------------------*/  NetTimerStart(&newsock->state_tmr, newsock->connect_timeo);  /*-------------------------------------------------------------------*/  /* Ignore FINs in LISTEN.                                            */  /*-------------------------------------------------------------------*/  Net.Tcp->flags &= ~TCPF_FIN;  /*-------------------------------------------------------------------*/  /* Advance sequence number due to SYN and process accompanying data. */  /*-------------------------------------------------------------------*/  ++Net.Tcp->seq_num;  TcpData(newsock);}/***********************************************************************//*    syn_sent: Do SYN_SENT state processing                           *//*                                                                     *//***********************************************************************/static void syn_sent(void){  /*-------------------------------------------------------------------*/  /* Send RESET if incoming ACK specifies wrong sequence number.       */  /*-------------------------------------------------------------------*/  if ((Net.Tcp->flags & TCPF_ACK) && (Net.Tcp->ack_num != Sock->snd_nxt))  {    TcpReset();    return;  }  /*-------------------------------------------------------------------*/  /* Process incoming RESET by aborting socket.                        */  /*-------------------------------------------------------------------*/  if (Net.Tcp->flags & TCPF_RST)  {    TcpDrop(Sock, ECONNREFUSED);    return;  }  /*-------------------------------------------------------------------*/  /* Waiting in this state for a SYN.                                  */  /*-------------------------------------------------------------------*/  if ((Net.Tcp->flags & TCPF_SYN) == FALSE)    return;  /*-------------------------------------------------------------------*/  /* Initialize other socket data.                                     */  /*-------------------------------------------------------------------*/  Sock->snd_cwnd = Sock->snd_mss;  Sock->snd_window = Net.Tcp->window;  Sock->lw_seq = Net.Tcp->seq_num;  Sock->rd_nxt = Sock->rcv_nxt = Net.Tcp->seq_num + 1;  Sock->flags |= (SF_SENDFLG | TCPF_ACK);  /*-------------------------------------------------------------------*/  /* Ignore FINs in SYN_SENT.                                          */  /*-------------------------------------------------------------------*/  Net.Tcp->flags &= ~TCPF_FIN;  /*-------------------------------------------------------------------*/  /* Handle acknowledgments and window announcements.                  */  /*-------------------------------------------------------------------*/  ack_and_win();  /*-------------------------------------------------------------------*/  /* Advance sequence number due to SYN and process accompanying data. */  /*-------------------------------------------------------------------*/  ++Net.Tcp->seq_num;  if (TcpData(Sock))    return;  /*-------------------------------------------------------------------*/  /* If our SYN has not been ACKed, move to SYNRCVD.                   */  /*-------------------------------------------------------------------*/  if (Sock->flags & TCPF_SYN)  {    Sock->state = SS_SYNRCVD;  }  /*-------------------------------------------------------------------*/  /* Else, move to ESTABLISHED and wake task performing active open.   */  /*-------------------------------------------------------------------*/  else  {    /*-----------------------------------------------------------------*/    /* Wake task that called connect().                                */    /*-----------------------------------------------------------------*/    NetPostEvent(Sock, SE_OPENED);    /*-----------------------------------------------------------------*/    /* Socket is now established and connected.                        */    /*-----------------------------------------------------------------*/    ++Stats.TcpCurrEstab;    Sock->state = SS_ESTABLISHED;    Sock->flags |= SF_CONNECTED;    /*-----------------------------------------------------------------*/    /* Stop SYN acknowledgment timer.                                  */    /*-----------------------------------------------------------------*/    NetTimerStop(&Sock->state_tmr);  }}/***********************************************************************//*    syn_rcvd: Do SYN_RCVD state input processing                     *//*                                                                     *//***********************************************************************/static void syn_rcvd(void){  SOCKET psock = Sock->psock;  /*-------------------------------------------------------------------*/  /* Delete socket for RST or SYN, respond with RST to SYN.            */  /*-------------------------------------------------------------------*/  if (Net.Tcp->flags & (TCPF_RST | TCPF_SYN))  {    if (Net.Tcp->flags & TCPF_SYN)      TcpReset();    TcpDrop(Sock, ECONNREFUSED);    return;  }  /*-------------------------------------------------------------------*/  /* Check for SYN acknowledgment, return if missing or absurd ACK.    */  /*-------------------------------------------------------------------*/  if (ack_and_win())    return;  /*-------------------------------------------------------------------*/  /* If no parent socket, this is a simultaneous active open.          */  /*-------------------------------------------------------------------*/  if (psock == NULL)  {    NetPostEvent(Sock, SE_OPENED);  }  /*-------------------------------------------------------------------*/  /* Else this is a passive open.                                      */  /*-------------------------------------------------------------------*/  else  {    /*-----------------------------------------------------------------*/    /* Send RST and delete if parent is not listening.                 */    /*-----------------------------------------------------------------*/    if (psock->state != SS_LISTEN)    {      TcpReset();      TcpDrop(Sock, ECONNABORTED);      return;    }    /*-----------------------------------------------------------------*/    /* Ignore packet if listen queue is full.                          */    /*-----------------------------------------------------------------*/    if (psock->q_count >= psock->lis_backlog)      return;    /*-----------------------------------------------------------------*/    /* Otherwise, reserve socket and append to end of listen queue.    */    /*-----------------------------------------------------------------*/

⌨️ 快捷键说明

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