📄 tcp_in.c
字号:
/***********************************************************************//* *//* Module: tcp_ip/tcp/tcp_in.c *//* Release: 2001.3 *//* Version: 2001.0 *//* Purpose: TCP Input Routines *//* *//*---------------------------------------------------------------------*//* *//* 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"#include <string.h>/***********************************************************************//* Function Prototypes *//***********************************************************************/static SOCKET sock_match(void);static void do_opts(void);static int seq_ok(void);static void get_MSS(const ui16 *mssp);/***********************************************************************//* Global Data Definitions *//***********************************************************************/SOCKET Sock;/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* TcpIn: Deliver an inbound TCP segment to TCP socket *//* *//***********************************************************************/void TcpIn(void){ int hlen; void *aligned; /*-------------------------------------------------------------------*/ /* Read and verify TCP header length. */ /*-------------------------------------------------------------------*/ hlen = TCP_HLEN(RxBuf->ip_data); if ((hlen < TCPMHLEN) || (hlen > RxBuf->length)) return; /*-------------------------------------------------------------------*/ /* If not already set by VJHC decompression, assign application data */ /* pointer and length. */ /*-------------------------------------------------------------------*/ if (RxBuf->app_len == 0) { RxBuf->app_data = (ui8 *)RxBuf->ip_data + hlen; RxBuf->app_len = RxBuf->length - hlen; } /*-------------------------------------------------------------------*/ /* Ensure TCP header is four-byte aligned. */ /*-------------------------------------------------------------------*/ aligned = (void *)((ui32)RxBuf->ip_data & ~3); if (aligned != RxBuf->ip_data) { memmove(aligned, RxBuf->ip_data, hlen); RxBuf->ip_data = aligned; } /*-------------------------------------------------------------------*/ /* Assign global TCP segment pointer. */ /*-------------------------------------------------------------------*/ Net.Tcp = aligned; /*-------------------------------------------------------------------*/ /* Verify checksum validity (using length of entire segment). */ /*-------------------------------------------------------------------*/ if (TcpCheckSum(RxBuf)) return; /*-------------------------------------------------------------------*/ /* Set buffer length to length of application data. */ /*-------------------------------------------------------------------*/ RxBuf->length -= hlen; /*-------------------------------------------------------------------*/ /* Convert header fields to host order. */ /*-------------------------------------------------------------------*/ Net.Tcp->seq_num = ntohl(Net.Tcp->seq_num); Net.Tcp->ack_num = ntohl(Net.Tcp->ack_num); Net.Tcp->window = ntohs(Net.Tcp->window); Net.Tcp->urg_ptr = ntohs(Net.Tcp->urg_ptr); /*-------------------------------------------------------------------*/ /* Match segment to a socket and reserve socket. */ /*-------------------------------------------------------------------*/ Sock = sock_match(); if (Sock == NULL) { TcpReset(); return; } ++Sock->reserve_cnt; /*-------------------------------------------------------------------*/ /* Verify that sequence numbers are acceptable for current window. */ /*-------------------------------------------------------------------*/ if (seq_ok()) { /*-----------------------------------------------------------------*/ /* If segment contains options, process them. */ /*-----------------------------------------------------------------*/ if (hlen != TCPMHLEN) do_opts(); /*-----------------------------------------------------------------*/ /* Process buffer according to socket state. */ /*-----------------------------------------------------------------*/ TcpSwitch[Sock->state](); /*-----------------------------------------------------------------*/ /* Call output state machine if needed. */ /*-----------------------------------------------------------------*/ if (Net.TryOut || (Sock->flags & SF_SENDFLG)) { Net.TryOut = FALSE; ++Sock->reserve_cnt; TcpOut(Sock); } TcpAssert(Sock->out_state == TCPO_IDLE || Sock->out_tmr.running); } else { /*-----------------------------------------------------------------*/ /* Not acceptable, just acknowledge successful reception. */ /*-----------------------------------------------------------------*/ TcpJustAck(Sock); } /*-------------------------------------------------------------------*/ /* Release our socket reservation. */ /*-------------------------------------------------------------------*/ SockRelease(Sock);}/***********************************************************************//* TcpJustAck: Generate ACK for received segment that lies outside *//* current receive window *//* *//* Input: sock = TCP socket for incoming segment *//* *//***********************************************************************/void TcpJustAck(SOCKET sock){ NetBuf *rbuf; Tcp *tcp_out; Route *route; Ip *ip; /*-------------------------------------------------------------------*/ /* To prevent infinite loops, do not acknowledge RESET segments. */ /*-------------------------------------------------------------------*/ if (Net.Tcp->flags & TCPF_RST) return; /*-------------------------------------------------------------------*/ /* If no data and no SYN or FIN, must be old duplicate ACK. */ /*-------------------------------------------------------------------*/ if ((RxBuf->app_len == 0) && !(Net.Tcp->flags & (TCPF_SYN | TCPF_FIN))) return; /*-------------------------------------------------------------------*/ /* Get a buffer to use for the response. */ /*-------------------------------------------------------------------*/ rbuf = tcpGetBuf(NIMHLEN + IPMHLEN + TCPMHLEN); if (rbuf == NULL) return; /*-------------------------------------------------------------------*/ /* Find route for this destination, using cached route if available. */ /*-------------------------------------------------------------------*/ if (sock->route) route = sock->route; else { route = RtSearch(sock->remote.sin_addr.s_addr); if (route == NULL) { ++Stats.IpOutNoRoutes; tcpRetBuf(&rbuf); return; } sock->route = route; } /*-------------------------------------------------------------------*/ /* Begin IP header initialization. */ /*-------------------------------------------------------------------*/ ip = (Ip *)rbuf->ip_pkt; ip->protocol = IPT_TCP; ip->src_ip = sock->local.sin_addr.s_addr; ip->dst_ip = sock->remote.sin_addr.s_addr; /*-------------------------------------------------------------------*/ /* Complete TCP header fields. */ /*-------------------------------------------------------------------*/ tcp_out = rbuf->ip_data; tcp_out->src_port = Net.Tcp->dst_port; tcp_out->dst_port = Net.Tcp->src_port; tcp_out->seq_num = htonl(sock->snd_nxt); tcp_out->ack_num = htonl(sock->rcv_nxt); tcp_out->flags = TCPF_ACK; tcp_out->offset = TCPHOFFSET; tcp_out->window = TcpRcvWin(sock); tcp_out->urg_ptr = 0; /*-------------------------------------------------------------------*/ /* Calculate checksum. */ /*-------------------------------------------------------------------*/ rbuf->length = TCPMHLEN; tcp_out->cksum = 0; tcp_out->cksum = TcpCheckSum(rbuf); /*-------------------------------------------------------------------*/ /* Pass to IP for delivery and track how many TCP segments are sent. */ /*-------------------------------------------------------------------*/ IpSend(route, rbuf, rbuf->length, sock->ip_tos); ++Stats.TcpOutSegs;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -