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

📄 tcp_in.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************//* Local Function Definitions                                          *//***********************************************************************//***********************************************************************//*  sock_match: Match incoming segment to an open socket               *//*                                                                     *//***********************************************************************/static SOCKET sock_match(void){  SOCKET ls_sock = NULL;  CircLink *link = TcpLruList.next_bck;  /*-------------------------------------------------------------------*/  /* Search socket table for match.                                    */  /*-------------------------------------------------------------------*/  for (; link != &TcpLruList; link = link->next_bck)  {    SOCKET sock = (SOCKET)link;    /*-----------------------------------------------------------------*/    /* Check for local port match.                                     */    /*-----------------------------------------------------------------*/    if (Net.Tcp->dst_port == sock->local.sin_port)    {      /*---------------------------------------------------------------*/      /* Check for IP address and remote port match.                   */      /*---------------------------------------------------------------*/      if ((Net.Tcp->src_port == sock->remote.sin_port) &&          (Net.Ip->src_ip == sock->remote.sin_addr.s_addr) &&          (Net.Ip->dst_ip == sock->local.sin_addr.s_addr))      {        /*-------------------------------------------------------------*/        /* If not already there, move matching socket to head of list. */        /*-------------------------------------------------------------*/        if (link != TcpLruList.next_bck)        {          /*-----------------------------------------------------------*/          /* Remove from socket list.                                  */          /*-----------------------------------------------------------*/          link->next_bck->next_fwd = link->next_fwd;          link->next_fwd->next_bck = link->next_bck;          /*-----------------------------------------------------------*/          /* Append to head of socket list.                            */          /*-----------------------------------------------------------*/          link->next_bck = TcpLruList.next_bck;          link->next_fwd = &TcpLruList;          TcpLruList.next_bck->next_fwd = link;          TcpLruList.next_bck = link;        }        return sock;      }      /*---------------------------------------------------------------*/      /* Remember socket in listen state that matches port.            */      /*---------------------------------------------------------------*/      if (sock->state == SS_LISTEN)        ls_sock = sock;    }  }  /*-------------------------------------------------------------------*/  /* If input contains SYN, use listen port match.                     */  /*-------------------------------------------------------------------*/  if ((Net.Tcp->flags & TCPF_SYN) && ls_sock)    return ls_sock;  /*-------------------------------------------------------------------*/  /* No match.                                                         */  /*-------------------------------------------------------------------*/  return NULL;}/***********************************************************************//*      seq_ok: Determine if incoming segment is acceptable            *//*                                                                     *//* Note: Checks if sequence numbers of incoming segment fall within    *//*       acceptable range. If not, returns 0 with segment unaltered.   *//*       TcpJustAck() will acknowledge segments containing data, SYN,  *//*       or FIN. If some part of segment is acceptable, returns 1      *//*       after trimming segment to just the acceptable range.          *//*                                                                     *//*       SYN and initial data may be trimmed from segment beginning.   *//*       FIN and ending data may be trimmed from segment end.          *//*                                                                     *//*       seq_ok() is generous in that it trims to the available buffer *//*       space, not just the announced receive window, and it doesn't  *//*       trim an ending FIN unless it also has to trim ending data.    *//*                                                                     *//***********************************************************************/static int seq_ok(void){  uint rcv_win = Sock->rb_size - Sock->rb_count;  /*-------------------------------------------------------------------*/  /* Allow all unsynchronized states (CLOSED, LISTEN, SYN-SENT).       */  /*-------------------------------------------------------------------*/  if (Sock->state < SS_SYNRCVD)    return TRUE;  /*-------------------------------------------------------------------*/  /* Trim segment if some is below next expected sequence number.      */  /*-------------------------------------------------------------------*/  if (SEQ_GT(Sock->rcv_nxt, Net.Tcp->seq_num))  {    int todrop = Sock->rcv_nxt - Net.Tcp->seq_num;    /*-----------------------------------------------------------------*/    /* Ensure trimmed part of received segment gets acknowledged.      */    /*-----------------------------------------------------------------*/    Sock->flags |= SF_SENDFLG;    /*-----------------------------------------------------------------*/    /* Trim SYN if present. Return if nothing else to drop.            */    /*-----------------------------------------------------------------*/    if (Net.Tcp->flags & TCPF_SYN)    {      Net.Tcp->flags &= ~TCPF_SYN;      --todrop;      ++Net.Tcp->seq_num;    }    /*-----------------------------------------------------------------*/    /* If data is completely below the receive window, return TRUE     */    /* with length set to zero in order to process acks and window.    */    /*-----------------------------------------------------------------*/    if (todrop >= RxBuf->app_len)    {      RxBuf->length = RxBuf->app_len = RxBuf->app_len2 = 0;      return TRUE;    }    /*-----------------------------------------------------------------*/    /* Adjust sequence number, data length and pointers.               */    /*-----------------------------------------------------------------*/    TcpTrimBeg(RxBuf, todrop);  }  /*-------------------------------------------------------------------*/  /* Trim segment end if some data extends beyond receive buffer end.  */  /*-------------------------------------------------------------------*/  if (SEQ_GT(Net.Tcp->seq_num + RxBuf->app_len, Sock->rcv_nxt + rcv_win))  {    int new_len;    /*-----------------------------------------------------------------*/    /* Return FALSE if segment is completely above receive window.     */    /*-----------------------------------------------------------------*/    if (SEQ_GT(Net.Tcp->seq_num, Sock->rcv_nxt + rcv_win))      return FALSE;    /*-----------------------------------------------------------------*/    /* Ensure trimmed part of received segment gets acknowledged.      */    /*-----------------------------------------------------------------*/    Sock->flags |= SF_SENDFLG;    /*-----------------------------------------------------------------*/    /* Trim to end of receive buffer.                                  */    /*-----------------------------------------------------------------*/    new_len = rcv_win - (Net.Tcp->seq_num - Sock->rcv_nxt);    RxBuf->length = new_len;    RxBuf->app_len = new_len;    /*-----------------------------------------------------------------*/    /* FIN takes no buffer space, but must be trimmed if end data is.  */    /*-----------------------------------------------------------------*/    Net.Tcp->flags &= ~TCPF_FIN;  }  return TRUE;}/***********************************************************************//*     do_opts: Handle TCP options for inbound segment                 *//*                                                                     *//***********************************************************************/static void do_opts(void){  ui8 *optp = Net.Tcp->options;  ui8 *tcp_data = optp + (TCP_HLEN(Net.Tcp) - TCPMHLEN);  /*-------------------------------------------------------------------*/  /* Loop through option list, parsing each option present.            */  /*-------------------------------------------------------------------*/  do  {    switch (*optp)    {    case TPO_NOOP: ++optp; break;    case TPO_EOOL: break;    case TPO_MSS:      get_MSS((ui16 *)(optp + 2));      /*lint -fallthrough */    default:      /*---------------------------------------------------------------*/      /* Advance option pointer by value in len field.                 */      /*---------------------------------------------------------------*/      optp += *(optp + 1);      break;    }  } while ((*optp != TPO_EOOL) && (optp < tcp_data));}/***********************************************************************//*     get_MSS: Set sender MSS from option in received segment         *//*                                                                     *//*       Input: mssp = pointer to mss option                           *//*                                                                     *//***********************************************************************/static void get_MSS(const ui16 *mssp){  ui16 mss;  /*-------------------------------------------------------------------*/  /* If this is not a SYN segment, ignore the MSS option.              */  /*-------------------------------------------------------------------*/  if ((Net.Tcp->flags & TCPF_SYN) == 0)    return;  /*-------------------------------------------------------------------*/  /* Extract the embedded MSS, converting it to host order.            */  /*-------------------------------------------------------------------*/  mss = ntohs(*mssp);  /*-------------------------------------------------------------------*/  /* Use the minimum of this and any previously sent MSS values.       */  /*-------------------------------------------------------------------*/  if (Sock->snd_mss)    Sock->snd_mss = min(mss, Sock->snd_mss);  else    Sock->snd_mss = mss;}

⌨️ 快捷键说明

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