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

📄 tcpsend.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 4 页
字号:
/* #define FAST_REXMT_DEBUG *//* #define TRACE_SQXMIT *//**            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 fix from 1.35.2.2 $*  $Date: 2002/04/16 12:42:47 $*  $Source: M:/psisrc/stack/tcp/rcs/tcpsend.c $*  $Revision: 1.38.2.2 $***************************************************************************                         - Revision Log -                              ** Who   When        Why** FND   09/10/01    Rename t_start to fns_t_start to fix conflict *                   with pSOS.** FND   01/05/02    Eliminate compiler warning for the first assert()*                   in tcp_construct_seg_options().****************************************************************************  File Description:  TCP - Transmission Control Protocol*                          Transmit routines**************************************************************************/#include "std.h"#include "m.h"#include "so.h"#include "ip.h"#include "tcp.h"#include "timer.h"#include "fnsmib.h"#include "fnsproto.h"#include "nerrno.h"#include "debug.h"#include "flags.h"#define t_start fns_t_startpflocal st      tcp_sqdispfn(fast m * mp);import  u32     nc_hsize, tcp_try_max;#ifdef  DEBUGimport  boolean tcp_debug;#endif#ifdef  TRACEimport  boolean tcp_trace, tcp_tsqxmit, tcp_turgent;#endif#ifdef MSD_DEBUGimport  boolean msd_debug;                                      /*msddebug*/#endif#ifdef NAT_ROUTERimport u32 m_growmax;#endif#if 1static int inv_ctr = 0;export int sctr = 0;#endif/*************************************************************************//*************************************************************************//* TCP segments are "disposed of" via the following function. Its   purpose is to gain performance by holding on to mss-sized messages   rather than freeing them to the heap, in order to re-use them for    subsequent mss-sized messages. This saves freeing to the heap and   reallocating them. But also, keeps the heap tied up (if some time    were to pass before the message we are holding on to gets re-used) */																																pflocal int tcp_sqxmit_termfn(fast m * mp){    fast tcpsv_t *svp = mp->m_svp;	use_critical;	assert(svp != (tcpsv_t *) 0,"tcp_sqxmit_termfn -- NULL svp");		/* if its an mss-sized message, see if we have capacity to store it for later use,	   otherwise just let it be freed */       if (mp->m_len == svp->sv_mss_m_len) {          critical;          if (!(svp->sv_q.q_flags & F_Q_ZAPPED)) { /* don't keep message if we've scheduled											          the freeing of the state vector */             assert(svp->sv_num_mss_sized_msgs <= MAX_HOLD_MSS_SIZED_MSGS, 		            "Too many mss-sized msgs");	         if (svp->sv_num_mss_sized_msgs < MAX_HOLD_MSS_SIZED_MSGS) {                svp->sv_tcp_mss_sized_msgs[svp->sv_num_mss_sized_msgs++] = mp;	            normal;		        return(0); /* don't let msm free it */			 }		  }	      normal;	   }    sv_m_detach(mp);    return(1); /* let msm free it */} /* tcp_sqxmit_termfn */																/****************************************************************************//* inspect errors and reset the connection if they happen more than thrice * during connection establishment */pflocal st      tcp_sqconndispfn (fast m * mp){    fast    tcpsv_t * svp;    if (mp->m_err  &&  mp->m_err != FNS_EWOULDBLOCK) {        svp = mp->m_svp;        assert(svp != (tcpsv_t *)0, "tcp_sqconndispfn: 0 svp\n");        /* SYN couldn't get out of the box -- probably because it wasn't routeable at		   the IP layer. Abort the connection attempt -- application can retry if it		   wishes. */        if (svp->sv_state < ESTAB)            tcp_rslf(svp, mp->m_err);    }    return (st)smdispose;} /* tcp_sqconndispfn *//****************************************************************************//* Local defines for processing the options part of a TCP header            */#define TCP_OPT_INCLUDE_MSS            0x1#define TCP_OPT_INCLUDE_WSF            0x2#define TCP_OPT_INCLUDE_TIMESTAMPS     0x4#define TCP_OPT_INCLUDE_SACK_PERMITTED 0x8#ifdef TCP_SELACK_ENHANCEMENTS #define TCP_OPT_INCLUDE_SACK           0x10#endif /* TCP_SELACK_ENHANCEMENTS */#ifdef TCP_TRANSACTION_TCP#define TCP_OPT_INCLUDE_CC             0x20#define TCP_OPT_INCLUDE_CCNEW          0x40#define TCP_OPT_INCLUDE_CCECHO         0x80#endif /* TCP_TRANSACTION_TCP */#ifdef TCP_SELACK_ENHANCEMENTS /****************************************************************************//* Function to return, given a specified amount of space, how many SACK     *//* blocks can be included in a SACK option that would fit into that space.  *//* Takes into account the 2-byte overhead plus the 8 bytes per block        *//****************************************************************************/static int tcp_num_sack_blocks_room_for(int room){ int num_sack_blocks = 0; room -= TCPO_VAL; while (room >= TCPO_SACK_BLOCK_SIZE) {	 num_sack_blocks++;	 room -= TCPO_SACK_BLOCK_SIZE; } /* while */ return(num_sack_blocks);} /* tcp_num_sack_blocks_room_for *//****************************************************************************//* This function adjusts the variables pertaining to TCP options according to   the need and capacity for sending selective acknowledgements in this segment.   The "optsize_so_far" parameter is input/output. Upon input, it says   how much option space is already spoken for. Upon output, it contains'   its input value plus the additional amount needed for the   selective ack option. Also, "which_options" is input-output. The "selective   ack needed" flag is set if it is determined that it is, and all the other   bits are left untouched. *//* NOTE: This function should not be called until all the other options that   will be included in the segment are already known. */export void tcp_selective_ack_needed(fast tcpsv_t *svp,int *optsize,u16 *which_options){ int sack_block_count;  /* If the SACK BLOCK list is empty, don't need a SACK option */ if (svp->sv_num_out_sack_blocks == 0) return;  /* How many SACK blocks do we have room for in the space available? */ sack_block_count = tcp_num_sack_blocks_room_for(TCP_MAX_SEG_OPTSIZE - *optsize); /* Do we have room for any at all? */ if (sack_block_count == 0) return;   /* If we don't have as many SACK blocks as we have room for, adjust the count down */ if (svp->sv_num_out_sack_blocks < sack_block_count) {	 sack_block_count = svp->sv_num_out_sack_blocks; } /* if */ /* We do have room for at least one, the amount of additional option    space needed is the "header" of the SACK option plus the space for	the SACK BLOCKS */ *optsize += (TCPO_VAL + (sack_block_count * TCPO_SACK_BLOCK_SIZE) ); *which_options |= TCP_OPT_INCLUDE_SACK; /* The optsize must be rounded up to the nearest multiple of 4 */ if ( ( *optsize % 4) != 0 )    *optsize += (4 - ( *optsize % 4) ); } /* tcp_selective_ack_needed */#endif /* TCP_SELACK_ENHANCEMENTS *//****************************************************************************//* Function to determine which options to include in a TCP segment. Returns *//* bitflags indicating which option to include                              */local int tcp_seg_which_options(fast tcpsv_t *svp, int synseg){ int which_options = 0;  /* Take care of options that would only be included in a SYN segment */ if (synseg) {	 /* The MSS option will always be present, and first */     which_options = TCP_OPT_INCLUDE_MSS;#ifdef TCP_WND_SCALE     /* If a window scale option is to be included, it will always follow          the MSS option. It is to be included if:        -- Window scale option is enabled (per socket option)  AND	    -- We are the active side initiating a SYN OR	       we are responding to a SYN which contained the window scale option     */     if (svp->sv_flags2 & SV_WSCALE_PERMITTED) {        if ( (svp->sv_state == SYN_SENT) ||		     ( (svp->sv_state == SYN_RECVD) && 	           (svp->sv_flags2 & SV_WSCALE_ENABLED) ) )	         which_options |= TCP_OPT_INCLUDE_WSF;	 } /* if */#endif /* TCP_WND_SCALE */#ifdef TCP_SELACK_ENHANCEMENTS     /* If the socket option has been specified that we should permit selective acks,	    send that option */     if (svp->sv_flags2 & SV_PERMIT_IN_SACKS) {	         which_options |= TCP_OPT_INCLUDE_SACK_PERMITTED;	 } /* if */#endif /* TCP_SELACK_ENHANCEMENTS */ } /* if synseg */#ifdef TCP_TIMESTAMPS /* We need a timestamp option if:     -- The socket is configured to (via socket options) to generate timestamps,	    and this is the initiating SYN, so we want to try to negotiate timestamps 		on this connection	 -- This is the passive SYN, and the other end has indicated its desire to	    any segment other than an initiating SYN, and the peer has 	    indicated its desire to use timestamps by including a timestamp option		in its SYN (the SV_TIMESTAMPS_ENABLED indicates this)	 -- Any other segment, if timestamps were negotiated during the exchange of	    SYNs (i.e., the SV_TIMESTAMPS_ENABLED flag is set) */ { int timestamps_needed;   if ( (svp->sv_state == SYN_SENT) && (synseg) ) { /* this is the initiating SYN */       timestamps_needed = TIMESTAMPS_DESIRED(svp);   } else {	   timestamps_needed = (svp->sv_flags2 & SV_TIMESTAMPS_ENABLED);   } /* if-else */   if (timestamps_needed)      which_options |= TCP_OPT_INCLUDE_TIMESTAMPS; }#endif /* TCP_TIMESTAMPS */#ifdef TCP_TRANSACTION_TCP if (synseg) {	if (svp->sv_t_tcp_flags & SV_CCNEW) {	    which_options |= TCP_OPT_INCLUDE_CCNEW;	} else if (svp->sv_t_tcp_flags & SV_CC) {	    which_options |= TCP_OPT_INCLUDE_CC;	}	if (svp->sv_t_tcp_flags & SV_CCECHO) {	   which_options |= TCP_OPT_INCLUDE_CCECHO;	} } else { /* not a SYN segment */	/* RFC 1644: section 3.4, S3 */	if (svp->sv_ccrecv != 0) {		which_options |= TCP_OPT_INCLUDE_CC;	} else if ( (svp->sv_t_tcp_flags & SV_TRANSACTION) && (svp->sv_state == SYN_SENT) ){		/* Take care of case where the request message requires more than one segment		   because it is larger than the MSS */		t_tcp_cache_entry_ *ce;		ce = t_tcp_find_cache_entry(svp->sv_dest.ip_nethost);		if ( (ce != (t_tcp_cache_entry_ *) 0) &&			(ce->ce_ccsent != 0) ) {		   which_options |= TCP_OPT_INCLUDE_CC;		}	} }#endif /* TCP_TRANSACTION_TCP */ return(which_options);} /* tcp_seg_which_options *//****************************************************************************//* Function to determine the size of the options field of TCP segment.      *//* This, of course, depends on which options we need to send, and that      *//* depends on:                                                              *//*     -- compile time constants determining which options are compiled in  */

⌨️ 快捷键说明

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