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

📄 tcp_data.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
    /* Check if extent of received data has been extended.             */    /*-----------------------------------------------------------------*/    if (RxBuf->app_len)    {      /*---------------------------------------------------------------*/      /* Increment receive sequence numbers and buffer count.          */      /*---------------------------------------------------------------*/      sock->rcv_nxt += RxBuf->app_len;      sock->rb_count += RxBuf->app_len;      sock->rcv_win  -= RxBuf->app_len;      /*---------------------------------------------------------------*/      /* Mark buffer as holding socket data.                           */      /*---------------------------------------------------------------*/      RxBuf->flush = sock;      TcpAssert(RxBuf->seg_record == NULL);      /*---------------------------------------------------------------*/      /* Append buffer to socket receive queue.                        */      /*---------------------------------------------------------------*/      RxBuf->next = NULL;      if (sock->rq_head == NULL)        sock->rq_head = RxBuf;      else        sock->rq_tail->next = RxBuf;      sock->rq_tail = RxBuf;      /*---------------------------------------------------------------*/      /* Append buffer to end of free list and prevent later free.     */      /*---------------------------------------------------------------*/      tcpRetRcvBuf(RxBuf);      RxBuf = NULL;      /*---------------------------------------------------------------*/      /* Check if out of order segments have been received.            */      /*---------------------------------------------------------------*/      if (sock->oosq)      {        SegRecord *seg_record = sock->oosq;        /*-------------------------------------------------------------*/        /* For fast recovery, acknowledge segments that close gaps.    */        /*-------------------------------------------------------------*/        sock->flags |= SF_SENDFLG;        /*-------------------------------------------------------------*/        /* Check if queued segment records close additional gaps.      */        /*-------------------------------------------------------------*/        while (SEQ_LE(seg_record->seq, sock->rcv_nxt))        {          int overlap = sock->rcv_nxt - seg_record->seq;          int len = seg_record->len - overlap;          NetBuf *buf = seg_record->buf;          /*-----------------------------------------------------------*/          /* Check if segment record extends the sequence space.       */          /*-----------------------------------------------------------*/          if (len > 0)          {            sock->rcv_nxt += len;            sock->rb_count += len;            sock->rcv_win  -= len;            /*---------------------------------------------------------*/            /* Check if segment record has an attached buffer.         */            /*---------------------------------------------------------*/            if (buf)            {              /*-------------------------------------------------------*/              /* Trim any duplicate data from beginning of buffer.     */              /*-------------------------------------------------------*/              if (overlap)                TcpTrimBeg(buf, overlap);              /*-------------------------------------------------------*/              /* Append buffer to (guaranteed non-empty) socket queue. */              /*-------------------------------------------------------*/              buf->next = NULL;              sock->rq_tail->next = buf;              sock->rq_tail = buf;              /*-------------------------------------------------------*/              /* Mark that buffer is no longer on segment queue.       */              /*-------------------------------------------------------*/              buf->seg_record = NULL;            }          }          /*-----------------------------------------------------------*/          /* Else, in preparation for freeing the segment record, if   */          /* there is an attached buffer, clear the flush flag.        */          /*-----------------------------------------------------------*/          else          {            if (buf)            {              buf->flush = NULL;              buf->seg_record = NULL;            }          }          /*-----------------------------------------------------------*/          /* Free record used by queue head and advance to next entry. */          /*-----------------------------------------------------------*/          sock->oosq = seg_record->next;          seg_record->next = FreeRecQ;          FreeRecQ = seg_record;          seg_record = sock->oosq;          if (seg_record == NULL)            break;        }        /*-------------------------------------------------------------*/        /* Set TCPF_FIN if FIN and all earlier data received.          */        /*-------------------------------------------------------------*/        if ((sock->flags & SF_OOOFIN) &&                                    SEQ_GE(sock->rcv_nxt, sock->ooo_fin))        {          TcpFreeOoQ(sock);          Net.Tcp->flags |= TCPF_FIN;        }      }      /*---------------------------------------------------------------*/      /* Schedule delayed acknowledgment.                              */      /*---------------------------------------------------------------*/      NetTimerStart(&sock->ack_tmr, ACK_DELAY);      /*---------------------------------------------------------------*/      /* Clipping to buffer, not announced window, may cause underrun. */      /*---------------------------------------------------------------*/      if (sock->rcv_win < 0)        sock->rcv_win = 0;      /*---------------------------------------------------------------*/      /* Unblock waiting readers by posting "data received" event.     */      /*---------------------------------------------------------------*/      NetPostEvent(sock, SE_DATA_RCVD);    }    /*-----------------------------------------------------------------*/    /* If FIN, advance sequence and flag ACK needed/receiver closed.   */    /*-----------------------------------------------------------------*/    if (Net.Tcp->flags & TCPF_FIN)    {      ++sock->rcv_nxt;      sock->flags |= SF_GOTFIN | SF_SENDFLG;      NetPostEvent(sock, SE_GOT_FIN);    }  }  /*-------------------------------------------------------------------*/  /* Else segment has been received out of order.                      */  /*-------------------------------------------------------------------*/  else  {    /*-----------------------------------------------------------------*/    /* If segment has FIN, set flag and remember sequence number.      */    /*-----------------------------------------------------------------*/    if (Net.Tcp->flags & TCPF_FIN)    {      sock->flags |= SF_OOOFIN;      sock->ooo_fin = Net.Tcp->seq_num + RxBuf->app_len;    }    /*-----------------------------------------------------------------*/    /* If data, add buffer to received out-of-order queue.             */    /*-----------------------------------------------------------------*/    if (RxBuf->app_len)      add_seg(sock);    /*-----------------------------------------------------------------*/    /* Acknowledge segments received out of order.                     */    /*-----------------------------------------------------------------*/    sock->flags |= SF_SENDFLG;  }  return 0;}/***********************************************************************//*    TcpFlush: Copy segment data to socket's receive buffer           *//*                                                                     *//*        Note: Handles case where data region straddles the end and   *//*              beginning of the socket receive buffer                 *//*                                                                     *//***********************************************************************/void TcpFlush(NetBuf *buf){  SOCKET sock = buf->flush;  int length, rcvoff;  struct tcp *tcp = buf->ip_data;  /*-------------------------------------------------------------------*/  /* If in OOS queue, clear associated buffer pointer.                 */  /*-------------------------------------------------------------------*/  if (buf->seg_record)  {    ((SegRecord *)buf->seg_record)->buf = NULL;    buf->seg_record = NULL;  }  /*-------------------------------------------------------------------*/  /* Else unlink buffer from socket receive queue.                     */  /*-------------------------------------------------------------------*/  else  {    NetBuf *ptr, *prev = NULL;    for (ptr = sock->rq_head; ptr != buf; ptr = ptr->next)    {      prev = ptr;      TcpAssert(ptr);    }    if (prev)      prev->next = buf->next;    else      sock->rq_head = buf->next;    if (sock->rq_tail == buf)      sock->rq_tail = prev;  }  /*-------------------------------------------------------------------*/  /* Calculate the data's offset into the socket receive buffer.       */  /*-------------------------------------------------------------------*/  rcvoff = sock->rb_start + (tcp->seq_num - sock->rd_nxt);  if (rcvoff >= sock->rb_size)    rcvoff -= sock->rb_size;  /*-------------------------------------------------------------------*/  /* Flush application data to socket buffer.                          */  /*-------------------------------------------------------------------*/  length = buf->app_len;  if ((rcvoff + length) <= sock->rb_size)  {    memcpy(&sock->rbuf[rcvoff], buf->app_data, length);  }  else  {    int len1 = sock->rb_size - rcvoff;    memcpy(&sock->rbuf[rcvoff], buf->app_data, len1);    memcpy(&sock->rbuf[0], buf->app_data + len1, length - len1);  }  /*-------------------------------------------------------------------*/  /* Clear buffer's flush flag/pointer.                                */  /*-------------------------------------------------------------------*/  buf->flush = NULL;}/***********************************************************************//*  TcpTrimBeg: Trims specified number of data bytes from front        *//*                                                                     *//*      Inputs: buf = pointer to buffer being trimmed                  *//*              todrop = number of bytes to drop                       *//*                                                                     *//***********************************************************************/void TcpTrimBeg(NetBuf *buf, int todrop){  struct tcp *tcp = buf->ip_data;  /*-------------------------------------------------------------------*/  /* Adjust segment's starting sequence number.                        */  /*-------------------------------------------------------------------*/  tcp->seq_num += todrop;  /*-------------------------------------------------------------------*/  /* Adjust data pointer and length.                                   */  /*-------------------------------------------------------------------*/  buf->app_data += todrop;  buf->length -= todrop;  buf->app_len -= todrop;}

⌨️ 快捷键说明

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