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

📄 tcpxmit.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 2 页
字号:
/**            Copyright (c) 1998-2001 by NETsilicon Inc.**  This software is copyrighted by and is the sole property of*  NETsilicon.  All rights, title, ownership, or other interests*  in the software remain the property of NETsilicon.  This*  software may only be used in accordance with the corresponding*  license agreement.  Any unauthorized use, duplication, transmission,*  distribution, or disclosure of this software is expressly forbidden.**  This Copyright notice may not be removed or modified without prior*  written consent of NETsilicon.**  NETsilicon, reserves the right to modify this software*  without notice.**  NETsilicon*  411 Waverley Oaks Road                  USA 781.647.1234*  Suite 227                               http://www.netsilicon.com*  Waltham, MA 02452                       AmericaSales@netsilicon.com***************************************************************************  $Name: Fusion 6.52 Fusion 6.51 $*  $Date: 2002/01/16 16:34:17 $*  $Source: M:/psisrc/stack/tcp/rcs/tcpxmit.c $*  $Revision: 1.24 $***************************************************************************                         - Revision Log -                              ** Who   When        Why** FND   01/05/01    Rename t_start to fns_t_start to fix pSOS conflict****************************************************************************  File Description:  TCP - Transmission Control Protocol*                     Transmit routines**************************************************************************/#include "std.h"#include "fr.h"#include "ip.h"#include "pr.h"#include "m.h"#include "so.h"#include "tcp.h"#include "timer.h"#include "fnsmib.h"#include "fnsproto.h"#include "nerrno.h"#include "debug.h"#define t_start fns_t_startimport  pr_t    * tcp_prp;#ifdef  DEBUGimport  boolean tcp_debug;#endif#ifdef TRACEimport  boolean tcp_trace, tcp_tstate;#endif#ifdef  TCP_STATSimport  int     tcp_txmit;#endifimport  q       tcp_q;/* This function is used only by tcp_dink *//* Determine the receive window to be advertised in an outgoing packet.    Will advertise the amount of unused receive buffer space presently in    the socket's receive queue, unless we must presently advertise a    receive window of zero to avoid "silly window syndrome". In that case,    we will begin advertising the actual buffer space available when that    amount becomes at least as large as the lesser of (1) 1/2 the full size    of the socket's receive buffer, or (2) The MSS of this connection.*/export u16 tcp_rwind_to_advertise(fast tcpsv_t *svp){    fast    so_t    * sop;    u32 bsa;    /* obtain amount of buffer space available on the socket's receive queue */    sop = sv_valid_sop(svp, sop);     if (!sop) return(0); /* invalid socket pointer */    bsa = rwnd(sop);    /* are we presently recovering from a zero-window situation? */    if ( svp->sv_flags & SV_RECOVZWIN ) { /* yes */        /* has the available buffer space increased beyond the recovery threshold? */        if ( (bsa >= svp->sv_mssd) || (bsa >= (rwndmax(sop)/2)) ) { /* yes */            /* we have recovered, advertise actual available space */            svp->sv_flags &= ~SV_RECOVZWIN;        } else { /* no */            /* continue advertising zero window, not recovered yet */            bsa = 0;        }    } else { /* no, not presently in recovery mode */        if (bsa == 0) /* but we now need to enter recovery mode */            svp->sv_flags |= SV_RECOVZWIN;    }#ifdef TCP_WND_SCALE    return(bsa >> svp->sv_rwndscale);#else	return(bsa);#endif}/*************************************************************//* Function to scan the options field of the outgoing segment*//* and place proper values into the "value" fields of the    *//* options whose content is not supposed to be set until     *//* "dink" time.                                              *//* Input parameters are pointer to the beginning of the      *//* options portion of the TCP header and the state vector.   */local void tcp_dink_syn_options(fast TCPH_T *tcphp, fast tcpsv_t *svp){ /* The only one we need to do anything with here is the MSS option */ {  TCPO_T *msso;  msso = tcp_find_option(tcphp, TCPO_MSS_KIND);  if (msso != ((TCPO_T *) 0) )      HostToNet16(&msso[TCPO_VAL], svp->sv_rcv_mss); }} /* tcp_dink_syn_options *//************************************************************//* Final send & checksum generation */export  int     tcp_dink (m * mp){    fast    TCPH_T  * tcphp;        /* TCP Header Pointer */    fast    tcpsv_t * svp;    fast    PIPH_T  * piphp;        /* Pseudo IP Header Pointer */    fast    u16     flags;    fast    so_t    * sop;    fast    u16     u1;    int     if_mtu, send_mss;	int      mss_source;    netdev  * ndp;    u8      zbsave;    u16     checksum;    use_critical;    trace0(tcp_trace, "tcp_dink:\n");/*  we use ndp to get the IP mtu with the new router code */    ndp = mp->m_ndp;    tcphp = (TCPH_T *)mp->m_cp;    flags = NetToHost16(&tcphp[TCPH_FLAGS]);    svp = mp->m_svp;    if (SYN_ON(flags)) {        if (svp == (tcpsv_t *)0) {            debug0(tcp_debug, "tcp_dink: SYN w/o svp\n");            return FNS_ECONNABORTED;        }		/****************************************************************************/		/* MBM: The following code was put in for Fusion 6.5, replacing the code in		   "tcp_gsyn" which searched for a duplicate connection, slept (unconditionally,		   regardless of whether its a blocking socket) until that connection closed		   or went into the TIME_WAIT state, then killed that connection (i.e., 		   defeating the TIME_WAIT state) -- a complete violation of TCP fundamentals.		   Now we reject a connection attempt from the application if it will be a		   duplicate connection. */		/* If this is an initial SYN, we now know the outgoing interface for 	       this connection, and we can check to make sure that this isn't a duplicate	       connection (i.e., same pair of ipaddress:port endpoints). To do that, we 	       have to look at all of our state vectors to make sure that none of them are	       active with the same pair of endpoints. */        if (ACK_OFF(flags)) { /* This is the initial SYN */          int remote_port;           u32 remote_ipaddr;           int local_port;           u32 local_ipaddr;          tcpsv_t *nsvp;		  /* If we are not already bound to a local IP address, we will now "bind"		     ourself to the local IP address ot the interface that was selected 			 by the IP layer to send this SYN out on. */		  /* MBM note: This leaves an issue for dealing with later: What if the 		     interface that IP selected has a different IP address than the local			 IP address that we were previously bound to? Which address should 			 appear in the source-address field of the outgoing packets for this			 connection? And is it OK for the packets to be routed out a different			 interface than the one we are "bound" to? */          if (svp->sv_src.ip_nethost == INADDR_ANY) {             svp->sv_src.ip_nethost = ndp->nd_ipas[0];		  }          /* Look for duplicate connection */		  remote_port = svp->sv_dest.ip_port;          remote_ipaddr = svp->sv_dest.ip_nethost;          local_port = svp->sv_src.ip_port;          local_ipaddr = svp->sv_src.ip_nethost;#if 0		  /* We may not have been bound to a local ip address, in which case we get		     it from the device table */		  if (local_ipaddr == INADDR_ANY) {			  local_ipaddr = ndp->nd_ipas[0];		  }#endif          critical;          for (nsvp = (tcpsv_t *)tcp_q.q_next; nsvp != (tcpsv_t *) &tcp_q;                            nsvp = (tcpsv_t *) nsvp->sv_q.q_next) {             if (nsvp == svp) continue;             if ( (nsvp->sv_dest.ip_port    != remote_port) ||				  (nsvp->sv_dest.ip_nethost != remote_ipaddr) ||				  (nsvp->sv_src.ip_port     != local_port) ||				  (nsvp->sv_src.ip_nethost  != local_ipaddr) ) {				 continue;			 }			 /* We found a duplicate connection. */#ifdef TCP_TRANSACTION_TCP			 /* If both the current and the previous duplicate connection 			    are t/tcp, then if the previous is presently in th TIME_WAIT				state and its duration is less than an MSL, we can "kill" that				connection and accept this new one. -- per RFC 1644, section 3.4,			    O1.2 */			 if ( (svp->sv_t_tcp_flags & SV_TRANSACTION) &&				  (nsvp->sv_t_tcp_flags & SV_TRANSACTION) &&				  (nsvp->sv_state == TIME_WAIT) &&				  (nsvp->sv_t_tcp_flags & SV_LESS_THAN_MSL) ) {

⌨️ 快捷键说明

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