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

📄 pctcp.c

📁 dos 下 网络协议 dos 下 网络协议
💻 C
📖 第 1 页 / 共 5 页
字号:
 */
int tcp_open( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler )
{
    largecheck( s, sizeof( tcp_Socket ));   /* stack space warnings */
    tcp_unthread(s);                        /* just in case not totally closed */

    memset( s, 0, sizeof( tcp_Socket));
    s->rdata = s->rddata;
    s->maxrdatalen = tcp_MaxBufSize;
    s->ip_type = TCP_PROTO;
    // S. Lawson - _mss is *IP DATAGRAM* size, set TCP MSS here
//    s->mss = _mss;
    s->mss = _mss - sizeof( in_Header ) - sizeof ( tcp_Header );
    s->state = tcp_StateSYNSENT;
    s->timeout = set_timeout( tcp_LONGTIMEOUT );
    s->cwindow = 1;
    s->wwindow = 0;     /* slow start VJ algorithm */
    s->vj_sa = 4;      /* about 250 ms */
    lport = findfreeport( lport, true );  /* get a nonzero port val (S. Lawson - added true) */
    s->myaddr = my_ip_addr;
    s->myport = lport;

    if ( ina - my_ip_addr <= multihomes ) return( 0 );
    if ( ! _arp_resolve(ina, &s->hisethaddr, 0) )
        return( 0 );

    s->hisaddr = ina;
    s->hisport = port;
    s->seqnum = intel( set_timeout( 1 )) & 0xffff0000uL;
    s->datalen = 0;
    s->flags = tcp_FlagSYN;
    s->unhappy = true;
    s->dataHandler = datahandler;
    s->usr_yield = system_yield;
    s->frag[0]=s->frag[1]=0L;           // S. Lawson

    s->safetysig = SAFETYTCP;       /* insert into chain */
    s->next = tcp_allsocs;
    tcp_allsocs = s;

    s->rtt_delay = s->rtt_smooth = 18;  /* one second startup */
    tcp_send(s, __LINE__ );
    s->rtt_time = set_timeout( 1 );
    return( 1 );
}

/*
 * Passive open: listen for a connection on a particular port
 */
int tcp_listen( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler, word timeout )
{
    largecheck( s, sizeof( tcp_Socket ));
    tcp_unthread(s);                        /* just in case not totally closed */
    memset( s, 0, sizeof( tcp_Socket));
    s->rdata = s->rddata;
    s->maxrdatalen = tcp_MaxBufSize;
    s->ip_type = TCP_PROTO;
    // S. Lawson - _mss is *IP DATAGRAM* size, set TCP MSS here
//    s->mss = _mss;
    s->mss = _mss - sizeof( in_Header ) - sizeof ( tcp_Header );
    s->cwindow = 1;
    s->wwindow = 0;     /* slow start VJ algorithm */
/*    s->vj_sa = 36;      /* about 250 ms */
/* tcpwinfix -- mdurkin */
    s->vj_sa = 4;      /* about 250 ms */    /* was wrong val 95.05.02 */

    s->state = tcp_StateLISTEN;
    if ( !timeout ) s->timeout = 0; /* forever... */
    else s->timeout = set_timeout( timeout );
    lport = findfreeport( lport, true );  /* get a nonzero port val (S. Lawson - added true)*/
    s->myport = lport;
    s->hisport = port;
    s->hisaddr = ina;
    s->seqnum = intel( (word)(s));
    s->datalen = 0;
    s->flags = 0;
    s->unhappy = false;
    s->dataHandler = datahandler;
    s->usr_yield = system_yield;
    s->frag[0]=s->frag[1]=0L;           // S. Lawson

    s->safetysig = SAFETYTCP;       /* insert into chain */
    s->next = tcp_allsocs;
    tcp_allsocs = s;

    return( 1 );
}

static udp_close( udp_Socket *ds )
{
    udp_Socket *s, **sp;

    sp = &udp_allsocs;
    for (;;) {
        s = *sp;
        if ( s == ds ) {
            *sp = s->next;
            break;
        }
        if ( !s ) break;
        if ( ! s->err_msg ) s->err_msg = "UDP Close called";
        sp = &s->next;
    }
    return( 0 );
}


/*
 * Send a FIN on a particular port -- only works if it is open
 *   Must still allow receives
 */
static void tcp_close( tcp_Socket *s )
{
    if ( s->ip_type != TCP_PROTO )
        return;
    if ( s->state == tcp_StateESTAB ||
                s->state == tcp_StateESTCL ||
                s->state == tcp_StateSYNREC )
        {
                if ( s->datalen )      /* must first flush all data */
                {
                    s->flags |= tcp_FlagPUSH | tcp_FlagACK;
                    if ( s->state < tcp_StateESTCL )
                    {
                                s->state = tcp_StateESTCL;
                                tcp_sendsoon( s );
                }
                }
                else
                { /* really closing */
                    s->flags = tcp_FlagACK | tcp_FlagFIN;
                    if (!s->err_msg)
                                s->err_msg = "Connection closed normally";
                    s->state = tcp_StateFINWT1;
                    s->timeout = set_timeout( tcp_TIMEOUT ); /* should be a pretty lengthy time */ /* S. Lawson - make longer */
                tcp_send( s, __LINE__ );
                }
                s->unhappy = true;
    }
    else if (s->state == tcp_StateCLOSWT )
    { /* need to ack the fin and get on with it */
                s->timeout = set_timeout( LASTACK_TIMEOUT );    // Added AGW 6 Jan 2001
                s->state = tcp_StateLASTACK;
                s->flags |= tcp_FlagFIN;
                tcp_send( s, __LINE__ );
                s->unhappy = true;
            // S. Lawson - Added per (10-Jun 1997, GV)
    }
    else if (s->state == tcp_StateSYNSENT)
    {
                s->state = tcp_StateCLOSED;
                tcp_unthread (s);               /* unlink failed connect */
    }
}

/*
 * Abort a tcp connection
 */
static void tcp_abort( tcp_Socket *s )
{
    if (!s->err_msg) s->err_msg = "TCP_ABORT";
    if ( s->state != tcp_StateLISTEN && s->state != tcp_StateCLOSED ) {
        s->flags = tcp_FlagRST  | tcp_FlagACK ;
        s->unhappy = true;
        tcp_send(s, __LINE__);
    }
    s->unhappy = false;
    s->datalen = 0;
    s->ip_type = 0;
    s->state = tcp_StateCLOSED;
/*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
    tcp_unthread(s);
}

void sock_abort( sock_type *s )
{
    if ( s->tcp.ip_type == TCP_PROTO )
        tcp_abort( (tcp_Socket *)s );
    else
        udp_close( (udp_Socket *)s );
}

/*
 * tcp_sendsoon - schedule a transmission pretty soon
 *              - this one has an imperfection at midnight, but it
 *                is not significant to the connection performance
 */
void tcp_sendsoon( tcp_Socket *s )
{
    longword temp;
    if (s->ip_type == TCP_PROTO ) {
        temp = set_ttimeout( 1 );
        if ( temp == s->rtt_time && s->rto < 2 && s->recent == 0 ) {
            s->karn_count = 0;
            tcp_send( s, __LINE__ );
            s->recent = 1;
            return;
        }
        if ((s->unhappy || s->datalen > 0 || s->karn_count == 1)
          && (s->rtt_time < temp && s->rtt_time != 0))  // S. Lawson - handle 0
            return;

        s->rtt_time = set_ttimeout( 1 + (s->rto >> 4) );
        s->karn_count = 1;
    }
}

/*
 * Retransmitter - called periodically to perform tcp retransmissions
 */
static longword retran_strat = 0L; /* timeout retran strategy */

static void tcp_Retransmitter( void )
{
    tcp_Socket *s;

    /* only do this once per RETRAN_STRAT_TIME milliseconds */
    if ( !chk_timeout( retran_strat ))
        return;
    retran_strat = set_ttimeout( RETRAN_STRAT_TIME );

    for ( s = tcp_allsocs; s; s = s->next ) {

        // S. Lawson - possible to be closed but still queued
        if ( s->state==tcp_StateCLOSED ) {
           if ( s->rdatalen == 0) tcp_unthread(s);
           continue;
        }

        if ( s->datalen > 0 || s->unhappy || s->karn_count == 1 ) {
            /* retransmission strategy */

// S. Lawson - clear the timeout once it fires (thanks GV)
#ifdef NOTUSED
            if ( chk_timeout( s->rtt_time)) {
#else
            if ( s->rtt_time && chk_timeout( s->rtt_time )) {
               s->rtt_time = 0;
#endif

#ifdef DEBUG
    if(debug_on >1) printf("regular retran TO set unacked back to 0 from %u\n", s->unacked);
#endif //DEBUG
                /* strategy handles closed windows   J.D. + E.E. */
               if (s->window == 0 && s->karn_count == 2)
                  s->window = 1;

                if ( s->karn_count == 0 ) {
                    /* if really did timeout */


                    s->karn_count = 2;

                    s->unacked = 0;
                    /* use the backed off rto - implied, no code necessary */
                    /* reduce the transmit window */
                    s->cwindow =  ((s->cwindow + 1) * 3) >> 2;
                    if ( s->cwindow == 0 ) s->cwindow = 1;
                    s->wwindow = 0;
                }
                if (s->datalen)
                    s->flags |= tcp_FlagPUSH | tcp_FlagACK;
                tcp_send(s, __LINE__);
            }
            /* EE 99.08.23 */
            if ( s->datatimer )
                if ( chk_timeout( s->datatimer )) {
                    sock_abort( (sock_type *) s );
                }
        }
        /* handle inactive tcp timeouts */
        if ( sock_inactive && s->inactive_to ) {
            if ( chk_timeout( s->inactive_to)) {
                /* this baby has timed out */
                s->err_msg = "Connection timed out - no activity";
                sock_close( (sock_type *) s );
            }
        }
        if ( s->timeout && chk_timeout( s->timeout)) {
            if ( s->state == tcp_StateTIMEWT ) {
                s->state = tcp_StateCLOSED;
                tcp_unthread(s);
                break;
            } else if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL ) {
                s->err_msg = "Timeout, aborting";
                tcp_abort(s);
                break;
            }
        }
    }
    /* do our various daemons */
    if ( wattcpd ) (*wattcpd)();
}


/*
 * Unthread a socket from the tcp socket list, if it's there
 */
static void tcp_unthread( tcp_Socket *ds )
{
    tcp_Socket *s, **sp;

    if (!ds->rdatalen || (ds->state > tcp_StateESTCL))
                ds->ip_type = 0;                /* fail io */
    ds->state = tcp_StateCLOSED;   /* tcp_tick needs this */
    sp = &tcp_allsocs;
    for (;;) {
                s = *sp;
                if ( s == ds )
                {
                    *sp = s->next;
                    continue;           /* unthread multiple copies if necessary */
                }
                if ( !s ) break;
                sp = &s->next;
    }
}

/*
 * tcp_tick - called periodically by user application
 *          - returns 1 when our socket closes (S. Lawson - wrong: 0)
 *          - called with socket parameter or NULL
 */
int tcp_tick( sock_type *s )
{
    in_Header *ip;
    static longword timeout = 0;
    static longword start = 0;
    extern int dhcp_expired(void);      /* S. Lawson - in pcbootp.c */

/*    int x; */
    int packettype;

    /* S. Lawson - handle DHCP lease expiration */
    if (dhcp_expired()) {
                if ( s ) s->udp.err_msg = "DHCP lease expired";
                return 0;
    }

    /* finish off dead sockets */
    if ( s ) {
                if (( s->tcp.ip_type == TCP_PROTO ) &&
                    ( s->tcp.state == tcp_StateCLOSED ) &&
                    ( s->tcp.rdatalen == 0 )) {
                        tcp_unthread( & s->tcp );
                        s->tcp.ip_type = 0;
                }
    }


    /* plan our next retransmit */

    if ( !timeout )
        timeout = make_timeout( tcp_RETRANSMITTIME );

    while ( (ip = (in_Header *)_eth_arrived( (word *) &packettype )) != NULL )
    {
                start = *realclock;

                switch ( packettype )
                {
                case /*0x800*/ 0x008 :
                    /* do IP */
                    if ( checksum(ip, in_GetHdrlenBytes(ip)) == 0xffff ) {
                        switch ( ip->proto ) {
                            case TCP_PROTO :
                                tcp_handler(ip);
                                break;
                            case UDP_PROTO :
                                udp_handler(ip);
                                break;
                            case ICMP_PROTO :

⌨️ 快捷键说明

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