📄 tcp_util.c
字号:
/***********************************************************************//* *//* Module: tcp_ip/tcp/tcp_util.c *//* Release: 2001.3 *//* Version: 2001.0 *//* Purpose: TCP Utility 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"/***********************************************************************//* Global Data Definitions *//***********************************************************************/CircLink TcpLruList;/***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* state: Process expired state timer *//* *//***********************************************************************/static void state(void *object){ SOCKET sock = object; /*-------------------------------------------------------------------*/ /* If connection is established, this is a keep-alive timeout. */ /*-------------------------------------------------------------------*/ if (sock->state == SS_ESTABLISHED) { --sock->snd_nxt; TcpSendSeg(sock, 1); NetTimerStart(&sock->out_tmr, sock->retrans_timeo); } /*-------------------------------------------------------------------*/ /* Otherwise, the connection has timed out and should be dropped. */ /*-------------------------------------------------------------------*/ else { /*-----------------------------------------------------------------*/ /* Send RST, except for TIME_WAIT and SYN acknowledgment timeouts. */ /*-----------------------------------------------------------------*/ if ((sock->state != SS_TIMEWAIT) && ((sock->flags & TCPF_SYN) == 0)) { sock->flags |= TCPF_RST; TcpSendSeg(sock, 0); } /*-----------------------------------------------------------------*/ /* Drop the connection. */ /*-----------------------------------------------------------------*/ TcpDrop(sock, ETIMEDOUT); }}/***********************************************************************//* delay: Send delayed acknowledgment *//* *//***********************************************************************/static void delay(void *object){ SOCKET sock = object; sock->flags |= SF_SENDFLG; ++sock->reserve_cnt; TcpOut(sock);}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* TcpRcvWin: Calculate receive window announcement *//* *//* Input: sock = pointer to socket control block *//* *//***********************************************************************/ui16 TcpRcvWin(SOCKET sock){ int actual = sock->rb_size - sock->rb_count; int limited = (actual > 0xFFFF) ? 0xFFFF : actual; int rounded = limited - (limited % sock->rcv_mss); /*-------------------------------------------------------------------*/ /* Check if buffer space allows announcement of a larger window that */ /* is an integer multiple of the maximum receive segment size. */ /*-------------------------------------------------------------------*/ if (rounded > sock->rcv_win) sock->rcv_win = rounded; /*-------------------------------------------------------------------*/ /* Ensure non-zero announcement if space > half receive buffer size. */ /*-------------------------------------------------------------------*/ else if ((sock->rcv_win == 0) && (actual > (sock->rb_size >> 1))) sock->rcv_win = limited; /*-------------------------------------------------------------------*/ /* Return value is written to outbound TCP header, so convert order. */ /*-------------------------------------------------------------------*/ return htons((ui16)sock->rcv_win);}/***********************************************************************//* TcpReset: Generate a reset in response to a bad packet *//* *//***********************************************************************/void TcpReset(void){ NetBuf *bufout; Ip *ip_out; Tcp *tcp_out; int seglen; Route *route; /*-------------------------------------------------------------------*/ /* Don't send a reset in response to a reset. */ /*-------------------------------------------------------------------*/ if (Net.Tcp->flags & TCPF_RST) return; /*-------------------------------------------------------------------*/ /* Find route for this destination. */ /*-------------------------------------------------------------------*/ route = RtSearch(Net.Ip->src_ip); if (route == NULL) { ++Stats.IpOutNoRoutes; return; } /*-------------------------------------------------------------------*/ /* Get a buffer to use for the response. */ /*-------------------------------------------------------------------*/ bufout = tcpGetBuf(NIMHLEN + IPMHLEN + TCPMHLEN); if (bufout == NULL) return; /*-------------------------------------------------------------------*/ /* Calculate segment length (SYN and FIN each occupy a position). */ /*-------------------------------------------------------------------*/ seglen = Net.Ip->length - (IP_HLEN(Net.Ip) + TCP_HLEN(Net.Tcp)); if (Net.Tcp->flags & TCPF_SYN) ++seglen; if (Net.Tcp->flags & TCPF_FIN) ++seglen; /*-------------------------------------------------------------------*/ /* Start TCP header fields. */ /*-------------------------------------------------------------------*/ tcp_out = bufout->ip_data; tcp_out->src_port = Net.Tcp->dst_port; tcp_out->dst_port = Net.Tcp->src_port; if (Net.Tcp->flags & TCPF_ACK) { tcp_out->seq_num = Net.Tcp->ack_num; tcp_out->flags = TCPF_RST; } else { tcp_out->seq_num = 0; tcp_out->flags = TCPF_RST | TCPF_ACK; } tcp_out->ack_num = Net.Tcp->seq_num + seglen; tcp_out->offset = TCPHOFFSET; tcp_out->window = tcp_out->urg_ptr = 0; /*-------------------------------------------------------------------*/ /* Begin IP header initialization. */ /*-------------------------------------------------------------------*/ ip_out = (Ip *)bufout->ip_pkt; ip_out->protocol = IPT_TCP; ip_out->dst_ip = Net.Ip->src_ip; ip_out->src_ip = Net.Ip->dst_ip; /*-------------------------------------------------------------------*/ /* Convert TCP header to network order. */ /*-------------------------------------------------------------------*/ tcp_out->seq_num = htonl(tcp_out->seq_num); tcp_out->ack_num = htonl(tcp_out->ack_num); tcp_out->window = htons(tcp_out->window); tcp_out->urg_ptr = htons(tcp_out->urg_ptr); /*-------------------------------------------------------------------*/ /* Calculate TCP checksum. */ /*-------------------------------------------------------------------*/ bufout->length = TCPMHLEN; tcp_out->cksum = 0; tcp_out->cksum = TcpCheckSum(bufout); /*-------------------------------------------------------------------*/ /* Pass to IP for delivery and track how many TCP segments are sent. */ /*-------------------------------------------------------------------*/ IpSend(route, bufout, TCPMHLEN, Net.Ip->ip_tos); ++Stats.TcpOutSegs;}/***********************************************************************//* TcpNewSock: Allocate TCP socket memory and kernel objects *//* *//* Input: mode = WITH_BUFS or NO_BUFS *//* *//* Returns: pointer to new TCP socket control block *//* *//***********************************************************************/void *TcpNewSock(int mode){ SOCKET sock; void *sbuf, *rbuf; /*-------------------------------------------------------------------*/ /* Allocate socket control block if one is available. */ /*-------------------------------------------------------------------*/ sock = SockAlloc(SOCK_STREAM); if (sock == NULL) return NULL; /*-------------------------------------------------------------------*/ /* Get send and receive buffers, if requested. */ /*-------------------------------------------------------------------*/ sock->sb_size = (SOCK_SBUF_SIZE > 0xFFFF) ? 0xFFFF : SOCK_SBUF_SIZE; sock->rb_size = SOCK_RBUF_SIZE; if (mode == WITH_BUFS) { sbuf = tcpGetBuf(sock->sb_size); if (sbuf == NULL) { SockRelease(sock); return NULL; } rbuf = tcpGetBuf(sock->rb_size); if (rbuf == NULL) { tcpRetBuf(&sbuf); SockRelease(sock); return NULL; } } else sbuf = rbuf = NULL; sock->sbuf = sbuf; sock->rbuf = rbuf; /*-------------------------------------------------------------------*/ /* Initialize non-zero socket fields. */ /*-------------------------------------------------------------------*/ sock->out_state = TCPO_IDLE; sock->ssthresh = sock->sb_size; sock->retrans_timeo = INIT_RXT; sock->state_tmr.action = state; sock->state_tmr.object = sock; INIT_TMR(sock->state_tmr); sock->out_tmr.action = TcpOutTimeout; sock->out_tmr.object = sock; INIT_TMR(sock->out_tmr); sock->ack_tmr.action = delay; sock->ack_tmr.object = sock; INIT_TMR(sock->ack_tmr); /*-------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -