📄 tcp_data.c
字号:
/***********************************************************************//* *//* Module: tcp_ip/tcp/tcp_data.c *//* Release: 2001.3 *//* Version: 2001.0 *//* Purpose: TCP Input Data Processing *//* *//*---------------------------------------------------------------------*//* *//* 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 <string.h>#include <stdlib.h>/***********************************************************************//* Configuration *//***********************************************************************/#define OOS_RECORDS 20/***********************************************************************//* Type Definitions *//***********************************************************************/typedef struct srec{ struct srec *next; NetBuf *buf; tcpseq seq; int len;} SegRecord;/***********************************************************************//* Global Variable Definitions *//***********************************************************************/static SegRecord SegRecords[OOS_RECORDS];static SegRecord *FreeRecQ;/***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* add_seg: Add segment to "received out of order" segment queue *//* *//* Input: sock = pointer to socket control block *//* *//***********************************************************************/static void add_seg(SOCKET sock){ SegRecord *seg_record; tcpseq seq = Net.Tcp->seq_num; /*-------------------------------------------------------------------*/ /* Try to allocate a segment record, returning if unable. */ /*-------------------------------------------------------------------*/ if (FreeRecQ == NULL) return; seg_record = FreeRecQ; FreeRecQ = FreeRecQ->next; /*-------------------------------------------------------------------*/ /* Initialize segment record. */ /*-------------------------------------------------------------------*/ seg_record->seq = seq; seg_record->len = RxBuf->app_len; /*-------------------------------------------------------------------*/ /* If queue is empty, make this the first entry. */ /*-------------------------------------------------------------------*/ if (sock->oosq == NULL) { sock->oosq = seg_record; seg_record->next = NULL; } /*-------------------------------------------------------------------*/ /* Else insert record according to sequence number order. */ /*-------------------------------------------------------------------*/ else { SegRecord *next = sock->oosq; /*-----------------------------------------------------------------*/ /* If sequence number less than first entry, new queue head. */ /*-----------------------------------------------------------------*/ if (SEQ_LT(seq, next->seq)) { seg_record->next = next; sock->oosq = seg_record; } /*-----------------------------------------------------------------*/ /* Search queue for sequence number greater than this segment's. */ /*-----------------------------------------------------------------*/ else { SegRecord *prev; for (;;) { /*-------------------------------------------------------------*/ /* If sequence numbers match, free record and return. */ /*-------------------------------------------------------------*/ if (seq == next->seq) { seg_record->next = FreeRecQ; FreeRecQ = seg_record; return; } /*-------------------------------------------------------------*/ /* Save pointer to current record and advance to next. */ /*-------------------------------------------------------------*/ prev = next; next = next->next; /*-------------------------------------------------------------*/ /* If queue end is reached, append record to end. */ /*-------------------------------------------------------------*/ if (next == NULL) { prev->next = seg_record; seg_record->next = NULL; break; } /*-------------------------------------------------------------*/ /* If entry found with greater sequence number, insert record. */ /*-------------------------------------------------------------*/ if (SEQ_LT(seq, next->seq)) { seg_record->next = next; prev->next = seg_record; break; } } } } /*-------------------------------------------------------------------*/ /* Mark buffer as holding data and on segment queue. */ /*-------------------------------------------------------------------*/ RxBuf->flush = sock; RxBuf->seg_record = seg_record; /*-------------------------------------------------------------------*/ /* Save buffer pointer in segment record. */ /*-------------------------------------------------------------------*/ seg_record->buf = RxBuf; /*-------------------------------------------------------------------*/ /* Append buffer to free list and prevent later prepend free. */ /*-------------------------------------------------------------------*/ tcpRetRcvBuf(RxBuf); RxBuf = NULL;}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* TcpInit: Initialize TCP protocol software *//* *//***********************************************************************/void TcpInit(void){ int i; /*-------------------------------------------------------------------*/ /* Set initial segment sequence number. */ /*-------------------------------------------------------------------*/ Net.ISN = (rand() << 16) | rand(); /*-------------------------------------------------------------------*/ /* Initialize TCP socket list. */ /*-------------------------------------------------------------------*/ TcpLruList.next_fwd = TcpLruList.next_bck = &TcpLruList; /*-------------------------------------------------------------------*/ /* Initially link all segment records onto free list. */ /*-------------------------------------------------------------------*/ FreeRecQ = &SegRecords[0]; for (i = 0; i < OOS_RECORDS; ++i) SegRecords[i].next = &SegRecords[i + 1]; SegRecords[OOS_RECORDS - 1].next = NULL;}/***********************************************************************//* TcpFreeOoQ: Free socket's out-of-order segment record queue *//* *//* Input: sock = pointer to socket control block *//* *//***********************************************************************/void TcpFreeOoQ(SOCKET sock){ SegRecord *srp; while (sock->oosq) { /*-----------------------------------------------------------------*/ /* Remove record from socket's segment record list. */ /*-----------------------------------------------------------------*/ srp = sock->oosq; sock->oosq = sock->oosq->next; /*-----------------------------------------------------------------*/ /* If buffer attached, clear flush flag. */ /*-----------------------------------------------------------------*/ if (srp->buf) { srp->buf->flush = NULL; srp->buf->seg_record = NULL; srp->buf = NULL; } /*-----------------------------------------------------------------*/ /* Add record to free segment record list. */ /*-----------------------------------------------------------------*/ srp->next = FreeRecQ; FreeRecQ = srp; }}/***********************************************************************//* TcpData: Process current segment's data *//* *//* Input: sock = pointer to control block matched with segment *//* *//* Returns: 0 if no errors, else -1 *//* *//***********************************************************************/int TcpData(SOCKET sock){ /*-------------------------------------------------------------------*/ /* If data sent and application not receiving, send reset and drop. */ /*-------------------------------------------------------------------*/ if ((sock->rbuf == NULL) && RxBuf->app_len) { TcpReset(); TcpDrop(sock, ECONNABORTED); return -1; } /*-------------------------------------------------------------------*/ /* Check for urgent data flag. */ /*-------------------------------------------------------------------*/ if (Net.Tcp->flags & TCPF_URG) { /*-----------------------------------------------------------------*/ /* Calculate pointer to urgent data. */ /*-----------------------------------------------------------------*/ tcpseq up = Net.Tcp->seq_num + Net.Tcp->urg_ptr - 1; /*-----------------------------------------------------------------*/ /* If first occurrence or newly extended, set flag and post event. */ /*-----------------------------------------------------------------*/ if (!(sock->flags & SF_RUPOK) || SEQ_GT(up, sock->rurg_seq)) { sock->rurg_seq = up; sock->flags |= SF_RUPOK; NetPostEvent(sock, SE_URGENT); } } /*-------------------------------------------------------------------*/ /* Check if run of contiguous sequence numbers has been extended. */ /*-------------------------------------------------------------------*/ if (sock->rcv_nxt == Net.Tcp->seq_num) { /*-----------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -