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

📄 tcpsock.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 5 页
字号:
/**            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 $*  $Date: 2002/04/10 15:57:21 $*  $Source: M:/psisrc/stack/tcp/rcs/tcpsock.c $*  $Revision: 1.59 $***************************************************************************                         - Revision Log -                              ** Who   When        Why** FND   01/05/01    Rename t_start/t_delete to fns_t_start/fns_t_delete*                   to fix conflict with pSOS.** FND   01/05/02    Change variable 'oval' in tcp_setopt_ackdly to i32*                   because comparisons are made against negative values.****************************************************************************  File Description:  TCP - Transmission Control Protocol*           This file contains routines related to the ULP/TCP interface**************************************************************************/#include "std.h"#include "flags.h"#include "ip.h"#include "m.h"#include "netioc.h"#include "pr.h"#include "q.h"#include "select.h"     /* so_notify(), so_clr_notify() */#include "so.h"#include "timer.h"#include "fnsproto.h"#include "in.h"#include "tcp.h"#include "fnsmib.h"#include "nerrno.h"#include "debug.h"#include "fns_heap.h"#define t_start fns_t_start#define t_delete fns_t_deletepflocal so_t    * get_accept_sop(so_t * sop);pflocal void    tcp_glomopt(so_t * sop);#ifndef TCP_TRANSACTION_TCPpflocal void    tcp_sfin(tcpsv_t * svp);#elseexport void    tcp_sfin(tcpsv_t * svp, boolean xmit_now);#endif /* TCP_TRANSACTION_TCP */import  int     tcp_port;import  pr_t    * tcp_prp;import  q       tcp_q;import  tcb     * tcp_quiet;import  u32     max_backlog, tcp_sq_max, tcp_rq_max;#ifdef  DEBUGimport  boolean tcp_debug;#endif#ifdef TRACEimport  boolean tcp_taccept, tcp_tbind, tcp_tclose, tcp_tlinger;import  boolean tcp_trace, tcp_trcv, tcp_tstate, tcp_tsend, tcp_tsfin;import  boolean tcp_tud, tcp_turgent;#endifimport   int     tcp_seed;#ifdef MSD_DEBUGimport  boolean msd_debug;#endif#define rnd (tcp_seed = ((tcp_seed >> 1) + (int)t_time + 13) * 317, tcp_seed & 0xFF)/******************************************************************************//* Table for storing information about the TCP-level socket options we        *//* support. Enables the software to be table-driven rather than case statement*//* for each option                                                            *//******************************************************************************/static int tcp_get_seqno_option(so_t *sop,int optname,char *optval);static int tcp_get_sndbuf_option(so_t *sop,int optname,char *optval);static int tcp_get_oobinline_option(so_t *sop,int optname,char *optval);static int tcp_setopt_sndbuf(so_t *sop,int optname,char *optval);static int tcp_setopt_oobinline(so_t *sop,int optname,char *optval);static int tcp_setopt_rcvbuf(so_t *sop,int optname,char *optval);static int tcp_getopt_int(so_t *sop,int optname,char *optval);static int tcp_setopt_retr(so_t *sop,int optname,char *optval);static int tcp_setopt_bitflag2(so_t *sop,int optname,char *optval);static int tcp_getopt_bitflag2(so_t *sop,int optname,char *optval);static int tcp_get_maxseg_option(so_t *sop,int optname,char *optval);static int tcp_set_maxseg_option(so_t *sop,int optname,char *optval);static int tcp_set_rcvmss_option(so_t *sop,int optname,char *optval);static int tcp_setopt_ackdly(so_t *sop,int optname,char *optval);#ifdef TCP_TRANSACTION_TCPstatic int tcp_setopt_trans(so_t *sop,int optname,char *optval);#endif /* TCP_TRANSACTION_TCP  */static sockopt_entry_ tcp_sockopts[] = {	{TCP_O_SEQNO,      sizeof(u32), tcp_get_seqno_option,  0               },   	{TCP_MAXSEG,	   sizeof(int), tcp_get_maxseg_option, tcp_set_maxseg_option },	{TCP_USE_PEER_MSS_OPTION, sizeof(int), 0,              tcp_setopt_bitflag2 },	{TCP_SET_RCV_MSS, sizeof(int),         0,              tcp_set_rcvmss_option },#ifdef TCP_WND_SCALE    {TCP_WINDOW_SCALE, sizeof(int), tcp_getopt_bitflag2,tcp_setopt_bitflag2  },#endif /* TCP_WND_SCALE */#ifdef TCP_RTTM    {TCP_RTT_ALGORITHM, sizeof(int), tcp_getopt_bitflag2,tcp_setopt_bitflag2 },#endif /* TCP_RTTM */#ifdef TCP_TIMESTAMPS    {TCP_PROVIDE_TIMESTAMPS, sizeof(int), tcp_getopt_bitflag2,tcp_setopt_bitflag2},#endif /* TCP_TIMESTAMPS */#ifdef TCP_PAWS    {TCP_ENABLE_PAWS, sizeof(int), tcp_getopt_bitflag2,tcp_setopt_bitflag2},#endif /* TCP_PAWS */    {TCP_REX_MAX,     sizeof(int), tcp_getopt_int,     tcp_setopt_retr},    {TCP_REX_MIN,     sizeof(int), tcp_getopt_int,     tcp_setopt_retr},    {TCP_REX_INIT,    sizeof(int), tcp_getopt_int,     tcp_setopt_retr},    {TCP_ACKDELAYTIME, sizeof(int), tcp_getopt_int,     tcp_setopt_ackdly},    {TCP_ACKNSEG,     sizeof(int), tcp_getopt_int,     tcp_setopt_ackdly},#ifdef TCP_SELACK_ENHANCEMENTS    {TCP_PERMIT_SACKS, sizeof(int), tcp_getopt_bitflag2,tcp_setopt_bitflag2},    {TCP_SEND_SACKS,   sizeof(int), tcp_getopt_bitflag2,tcp_setopt_bitflag2},#endif /* TCP_SELACK_ENHANCEMENTS */#ifdef TCP_SS_CA_FRETR_FREC     {TCP_FAST_RETR_RECOV, sizeof(int), tcp_getopt_bitflag2, tcp_setopt_bitflag2},    {TCP_SLOW_START_CA,   sizeof(int), tcp_getopt_bitflag2, tcp_setopt_bitflag2},#endif /* TCP_SS_CA_FRETR_FREC  */    {TCP_NODELAY,      sizeof(int), tcp_getopt_bitflag2, tcp_setopt_bitflag2},#ifdef TCP_TRANSACTION_TCP    {TCP_ENABLE_TRANSACTION_TCP, sizeof(int), 0, tcp_setopt_trans},#endif /* TCP_TRANSACTION_TCP  */    {0,-1, 0, 0} /* sentinel entry, marks end of table */};static sockopt_entry_ tcp_sol_sockopts[] = {#ifndef SOCKET_USE_OLD_SOCKOPT_FUNCTIONS	{SO_SNDBUF,      sizeof(int), tcp_get_sndbuf_option,     tcp_setopt_sndbuf },        {SO_OOBINLINE,   sizeof(int), tcp_get_oobinline_option,  tcp_setopt_oobinline },	{SO_RCVBUF,      sizeof(int), 0,                         tcp_setopt_rcvbuf},#endif    {0,-1, 0, 0} /* sentinel entry, marks end of table */};	/*******************************************************************//* Hang on an insert into the listener's connection queue by 'tcp_passive'. * Make up a clone of the listener's socket.  The clone will retain the same * local host port number, a requirement of the TCP way of doing things. */export  int tcp_accept (so_t * sop, int * nfdp, int flags, saddr * addrname, 						int * addrlenp){    fast    tcpsv_t * svp;    fast    so_t    * nsop;    int     err;    struct  in_sockaddr *inaddr = (struct in_sockaddr *)addrname;    use_critical;    /* A lot of this is common code with other protocol families and     * should be moved into 'so_accept'.     */    trace0(tcp_trace, "tcp_accept:\n");/*  Let the user know that caccept is not supported anymore */    if (flags & MSG_PEEK) {        return FNS_EOPNOTSUPP; /* caccept not supported anymore */    }    /* Validate params */    if( addrlenp ) {        if( *addrlenp < sizeof(struct sockaddr_in)) {            return FNS_EFAULT;        }    }    if( !addrname ) {        /* We want a NULL length too then? */        if( addrlenp ) {            return FNS_EFAULT;        }    }    err = 0;    critical;    if ((svp = sop->so_svp) == (tcpsv_t *)0) {  /* no state vector (CLOSED) */        debug0(tcp_debug, "tcp_accept: no listen state vector\n");        normal;        return FNS_ENOTCONN;    }    if( svp->sv_state != LISTEN ) {		normal;        return FNS_EINVAL;    }/* We need to stay critical here UNTIL we do not touch nsop. So that nsop * does not disappear from under us  (in tcp_rslf) */    nsop = (so_t *)0;    trace1(tcp_taccept, "tcp_accept listen socket %d\n", sop->so_index);    while ( (nsop = get_accept_sop(sop)) == (so_t *)0 )    {        if (can_block(flags))        {            os_sleep((char *)sop);            /* Check whether user closed the listening socket */            svp = sop->so_svp;            if ( !svp || svp->sv_state != LISTEN )            {                err = sop->so_err;                if (err == 0)                    err = FNS_ECONNABORTED;                normal;                return err;            }        }        else {            normal;            return FNS_EWOULDBLOCK;        }    }    trace1(tcp_taccept, "tcp_accept accept socket %d\n", nsop->so_index);    *nfdp = nsop->so_index;    if ((svp = nsop->so_svp) == (tcpsv_t *)0)    {       /* no state vector (CLOSED) */        debug0(tcp_debug, "tcp_accept: no accept state vector\n");        /* socket freed in tcp_rsfl */        normal;        return FNS_ENOTCONN;    }    sv_bind(svp, tcp_accept, true);    /* copy peer's address */    /* sv_dest set in tcp_rsyn (after we have received the first SYN) */    if (addrname != (saddr *)0 && addrlenp != (int *)0) {        /* Make sure they passed us a sockaddr_in */        if( *addrlenp < sizeof(struct in_sockaddr) ) {            debug0(tcp_debug, "tcp_accept:  incorrect size of saddr structure\n");            *addrlenp = 0; /* Let them know we didn't fill it in */        }else {            *addrlenp = sizeof(struct in_sockaddr);            inaddr->sin_addr.s_addr = svp->sv_dest.ip_nethost;            inaddr->sin_family = AF_INET;            inaddr->sin_port = svp->sv_dest.ip_port;        }    }    err = 0;    q_out(&nsop->so_q);    /* user is now responsible for closing the socket */    nsop->so_flags &= ~F_SO_TEMP;    if (q_empty(&sop->so_q))        so_clr_notify(sop, READ_NOTIFY|ACCEPT_NOTIFY);  /* no more connection requests */    normal;    sv_detach(svp, tcp_accept, true);       /* detach the state vector */    return err;} /* tcp_accept *//*******************************************************************/export  int     tcpattach (so_t * sop){    fast    tcpsv_t * svp;    auto    int     err;    use_critical;    trace0(tcp_trace, "tcpattach:\n");    critical;    assert(sop->so_svp == (tcpsv_t *)0, "tcpattach: sv already bound\n");    normal;    /* Allocate a zeroed state-vector */    if ((svp = (tcpsv_t *)h_calloc((i32)(sizeof(tcpsv_t)), (int *)&err,                                   (boolean)can_block(sop->so_flags))) == (tcpsv_t *)0)        return err;    /* Allocate timers for the state vector */    critical;       /* bind svp <==> tcb */    if ((svp->sv_acktcb = t_new((tcb *)0, tcp_acktimer, svp, (u32)0L,                                 (u16)(give_bs(sop->so_flags)|F_T_STOPPED))) == (tcb *)0) {abort:;        if (svp->sv_acktcb)            t_delete(svp->sv_acktcb);        if (svp->sv_rextcb)            t_delete(svp->sv_rextcb);        normal;        h_free((i32 *)svp);        return FNS_EWOULDBLOCK;     /* can't block and can't allocate tcb */    }    if ((svp->sv_rextcb = t_new((tcb *)0, tcp_rextimer, svp, (u32)0L,                                 (u16)(give_bs(sop->so_flags)|F_T_STOPPED))) == (tcb *)0)        goto abort;    if ((svp->sv_perftcb = t_new((tcb *)0, tcp_perftimer, svp, (u32)0L,                                 (u16)(give_bs(sop->so_flags)|F_T_STOPPED))) == (tcb *)0)        goto abort;    /* Bind the state vector and timers together */    sv_bind(svp, svp->sv_acktcb, false);    sv_bind(svp, svp->sv_rextcb, false);    sv_bind(svp, svp->sv_perftcb, false);    normal;    q_init(&svp->sv_q, 0);    sv_bind(svp, tcpattach, true);    sv_so_bind(svp, sop);   /* Bind the socket and state vector together */    q_init(&sop->so_rq.gq_q, F_Q_HEADER|F_Q_BYTE_QUEUE);    q_init(&sop->so_sq.gq_q, F_Q_HEADER|F_Q_BYTE_QUEUE);    sop->so_err = 0;    /* note: don't offer an initial receive window UNTIL we know what     * the MSS will become */    svp->sv_sq_max = tcp_sq_max; /* default value until/unless over-ridden by the                                    SO_SNDBUF option */    svp->sv_rq_max = tcp_rq_max; /* default value until/unless over-ridden by the                                    SO_RCVBUF option */    ip_at_comm(sop, svp->sv_sq_max, (u32)0L);	svp->sv_num_mss_sized_msgs = 0;	svp->sv_num_ack_sized_msgs = 0;#ifdef IP_RFC_1191	svp->sv_peer_mss = 0;#endif /* IP_RFC_1191 *//* for backward compatibility with pre-Fusion 5.5 */#ifdef TCP_URGENT_DATA_INBAND_DEFAULT    svp->sv_urg_mode = SV_URGMODE_INLINE;#else    svp->sv_urg_mode = SV_URGMODE_OOB;#endif#ifdef TCP_WND_SCALE    svp->sv_flags2 |= SV_WSCALE_PERMITTED; /* by default we try to negotiate window scaling */	svp->sv_flags2 &= ~SV_WSCALE_ENABLED;  /* Assume its not negotiated until proven otherwise */    svp->sv_rwndscale = svp->sv_swndscale = 0;#endif     svp->sv_rcv_mss = 0;#ifdef TCP_RTTM	svp->sv_flags2 &= ~SV_RTTM_RFC_1323;  /* Assume using standard RTTM until/unless socket	                                         option says otherwise */#endif	/* retransmission timer value limits unless overridden by socket option */

⌨️ 快捷键说明

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