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

📄 pctcp.c

📁 dos下开发TCP网络的库文件部分
💻 C
📖 第 1 页 / 共 5 页
字号:
    word len;
    byte *dp;
    longword temp;
    udp_Socket *s;

    temp = intel( ip->destination );

    // temp = ip number
    //     or 255.255.255.255
    //     or sin_mask.255.255

    if ( ((~temp & ~sin_mask) != 0) &&  /* not a broadcast packet*/
        ((( temp - my_ip_addr) > multihomes )   /* not my address */
        && my_ip_addr))                 /* and I know my address */
          return;


    len = in_GetHdrlenBytes(ip);
    up = (udp_Header *)((byte *)ip + len);      /* udp segment pointer */
    len = intel16( up->length );

    /* demux to active sockets */
    for ( s = udp_allsocs; s; s = s->next ) {
#ifdef DEBUG
        if ( s->safetysig != SAFETYUDP ) {
            if (debug_on) outs("\n\rUDP: Chain Error\n\r");  // R. Whitby
        }
#endif
        if ( (s->hisport != 0) &&
             (intel16( up->dstPort ) == s->myport) &&
             (intel16( up->srcPort ) == s->hisport) &&
             ((intel( ip->destination ) & sin_mask)  == (s->myaddr & sin_mask)) &&
             (intel( ip->source ) == s->hisaddr )) break;
    }
// R. Whitby    if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, up, 0);
    if ( !s ) {
        /* demux to passive sockets */
        for ( s = udp_allsocs; s; s = s->next )
            if ( ((s->hisaddr == 0) || (s->hisaddr == 0xffffffffuL))
              && intel16( up->dstPort ) == s->myport ) {

                // do we record this information ???
                if ( s->hisaddr == 0 ) {
                    s->hisaddr = intel( ip->source );
                    s->hisport = intel16( up->srcPort );

                    // S. Lawson - combined from these observations (alot of
                    //             explanation to remove one line)
                    //    Dashui Zhou <dszhou@cs.sdu.edu.cn>
                    //       ARP answer packet overwrites the first datagram
                    //       that arrives at a newly opened passive UDP
                    //       socket. (DZ fix moved _arp_resolve)
                    //    CpV <crudesoft@yahoo.com>
                    //       _arp_resolve() calls tcp_tick() which calls
                    //       calls this udp_handler() again (recurses)
                    //       Anyway, we don't need to resolve now, we can
                    //       resolve when we want to send something.
//                  _arp_resolve(intel(ip->source), &s->hisethaddr, 0);

                    // take on value of expected destination unless it
                    // is broadcast
                    if ( (intel(~ip->destination) & ~sin_mask) != 0 )
                        s->myaddr = intel( ip->destination );
                }
                break;
            }
    }
#ifdef NOTUSED      // S. Lawson - "passive sockets" scan above does this!
    if ( !s ) {
        /* demux to broadcast sockets */

        // S. Lawson - CpV <crudesoft@yahoo.com> has a change here that
        // causes broadcasts to go to a socket even if it is bound to a
        // remote IP address - I'm not including this because binding to
        // a specific machine should imply you're not interested in getting
        // packets from other machines on that socket.  You can always keep
        // a socket bound to the broadcast address for receiving broadcasts.

        for ( s = udp_allsocs; s; s = s->next )
            if ( (s->hisaddr == 0xffffffffuL) &&
                 (intel16( up->dstPort ) == s->myport )) break;
    }
#endif

    if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, up, 0);  // R. Whitby

    if ( !s ) {
        // S. Lawson - return ICMP port unreachable on non-broadcast
        if (my_ip_addr && temp!=0xffffffffuL && (~temp & ~sin_mask)) {
#ifdef DEBUG
           if (debug_on) outs("\n\rUDP: Discarding Packet\n\r");
#endif
           icmp_Unreach(ip);
        }
        return;
    }

    // these parameters are used for things other than just checksums
    ph.src = ip->source;    /* already INTELled */
    ph.dst = ip->destination;
    ph.mbz = 0;
    ph.protocol = UDP_PROTO;
    ph.length = up->length;
    if ( up->checksum ) {
        ph.checksum =  checksum(up, len);
        if (checksum(&ph, sizeof( tcp_PseudoHeader)) != 0xffff)
            return;
    }

    /* process user data */
    /* 2000.11.15 save first received packet rather than latest */
    if (( (len -= UDP_LENGTH ) > 0) && ( s->rdatalen == 0 )) {
        dp = (byte *)( up );
        if (s->dataHandler) s->dataHandler( s, &dp[ UDP_LENGTH ], len , &ph, up);
        else {
            if (len > s->maxrdatalen ) len = s->maxrdatalen;
            movmem( &dp[ UDP_LENGTH ], s->rdata, len );
            s->rdatalen = len;
        }
    }
}

static void tcp_handler( in_Header *ip )
{
    tcp_Header *tp;
    tcp_PseudoHeader ph;
    int len;
/*    byte *dp;  */
    int diff;
    tcp_Socket *s;
    word flags;
    long diffticks, ldiff;      /* must be signed */
    long scheduleto;


    if ( (longword)(intel( ip->destination ) - my_ip_addr) > multihomes )
        return;

#ifdef UNUSED   // S. Lawson - len wiped by 3rd line down anyway!
    len = in_GetHdrlenBytes(ip);
    len = intel16( ip->length ) - len;          /* len of tcp data */
#endif

    len = in_GetHdrlenBytes(ip);
    tp = (tcp_Header *)((byte *)ip + len);      /* tcp frame pointer */
    len = intel16( ip->length ) - len;          /* len of tcp data */
    flags = intel16( tp->flags );

#ifdef DEBUG
    if (debug_on > 1) {
            mono[160]++;
            colour[160]++;
            mono[162] = colour[162] = (flags & tcp_FlagSYN) ? 'S' : ' ';
            mono[164] = colour[164] = (flags & tcp_FlagACK) ? 'A' : ' ';
            mono[166] = colour[166] = (flags & tcp_FlagFIN) ? 'F' : ' ';
            mono[168] = colour[168] = (flags & tcp_FlagRST) ? 'R' : ' ';
        }
#endif
    /* demux to active sockets */
    for ( s = tcp_allsocs; s; s = s->next )
    {
#ifdef DEBUG
                if ( s->safetysig != SAFETYTCP )
                {
                if (debug_on) outs("\n\rTCP: Chain Error\n\r");   // R. Whitby
                }
#endif
                if ( s->hisport != 0 &&
                     intel16( tp->dstPort ) == s->myport &&
                     intel16( tp->srcPort ) == s->hisport &&
                     intel( ip->destination )   == s->myaddr     &&
                     intel( ip->source ) == s->hisaddr ) break;
        }
        if ( !s && (flags & tcp_FlagSYN))
        {
/* demux to passive sockets, must be a new session */
                for ( s = tcp_allsocs; s; s = s->next )
                    if ((s->hisport == 0) && (intel16( tp->dstPort ) == s->myport ))
                    {
                                s->myaddr = intel( ip->destination );
                                break;
                }
    }

    if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, tp, 0 );
    if ( !s )
    {
                if (!(flags & tcp_FlagRST)) tcp_rst( ip, tp );
//printf("tcp was reset\n");
                return;
    }

    ph.src = ip->source;        /* already INTELled */
    ph.dst = ip->destination;
    ph.mbz = 0;
    ph.protocol = TCP_PROTO;
    ph.length = intel16( len );
    ph.checksum =  checksum(tp, len);
    if ( checksum(&ph, sizeof(ph)) != 0xffff )
    {
#ifdef DEBUG
                 if (debug_on) outs("\n\rTCP: Bad Checksum\n\r");  // R. Whitby
#endif
                 tcp_sendsoon( s );
                 return;
    }

/* reset code */
    if ( flags & tcp_FlagRST ) {
#ifdef DEBUG
                if (debug_on) outs("\n\rTCP: Connection Reset\n\r");  // R. Whitby
#endif
                s->datalen = 0;
                if (s->state != tcp_StateCLOSED && s->state != tcp_StateLASTACK)
                   s->rdatalen = 0;
                s->err_msg = "Remote reset connection";
                s->state = tcp_StateCLOSED;
/*      if (s->dataHandler) s->dataHandler(s, 0, -1); */
                tcp_unthread(s);
        /* 2001.1.18 - make it fail tcp_tick() */
        s->ip_type = 0;
                return;
    }

    if ( sock_inactive )
        s->inactive_to = set_timeout( sock_inactive );


    /* update our retransmission stuff */
    /* new algorithms */
    if (s->karn_count == 2) {
        s->karn_count = 0;
#ifdef DEBUG
        if (debug_on > 1 ) printf("finally got it safely zapped from %u to ????\n\r",s->unacked);
#endif /* DEBUG */
    } else {
        if ( s->vj_last ) {
            /* unnecessary to use unhappy || s->datalen ) */
            if ((diffticks = set_ttimeout( 0 ) - s->vj_last) >= 0 ) {
                /* we ignore the overnight case */
                diffticks -= (longword)( s->vj_sa >> 3 );
                s->vj_sa += (int)diffticks;
                if (diffticks < 0)
                    diffticks = - diffticks;
                diffticks -= (s->vj_sd >> 2);
                s->vj_sd += (int)diffticks;
                if (s->vj_sa > MAXVJSA) s->vj_sa = MAXVJSA;
                if (s->vj_sd > MAXVJSD) s->vj_sd = MAXVJSD;
            }
            /* only recompute rtt hence rto after success */
            s->rto = (1 + ((s->vj_sa >> 2) + (s->vj_sd))) >> 1 ;
#ifdef DEBUG
            if (debug_on > 1 ) printf("rto  %u  sa  %u  sd  %u   cwindow %u  wwindow %u  unacked %u\n",
                s->rto, s->vj_sa, s->vj_sd, s->cwindow, s->wwindow, s->unacked );
#endif /* DEBUG */
        }
        s->karn_count = 0;
        if ( s->wwindow != 255 ) {
            if ( s->wwindow++ >= s->cwindow ) {
                if ( s->cwindow != 255 )
                    s->cwindow ++;
      /* tcpwinfix
       *    Movement of the next line *seems* to fix the failure of the TCP
       *    send window to open up (which makes TCP writes very slow, as
       *    seen with some previous releases of WatFTP), though it's been
       *    a long time since I made this change (today is 96.09.24) and
       *    I'm not sure how confident I was even then that it was correct.
       *    Also I don't have any description of the VJ algorithm and don't
       *    really understand this code all that well, but some time ago
       *    this seemed to be the right thing to do and seems to work.
       *    That said, if I'm wrong, I hope I haven't broken things worse :-)
       *    There is one other place, also marked 'tcpwinfix' above in this
       *    file, and those are the only two changes I made for this bug
       *    which may need undoing if I'm wrong. -- mdurkin
       */
                s->wwindow = 0;  /* mdurkin -- added 95.05.02 */
            }
/*            s->wwindow = 0;    /* mdurkin -- removed 95.05.02 */
        }
    }
    /* all new */
    scheduleto = set_ttimeout( s->rto + 2 );
    if ( s->rtt_time < scheduleto ) s->rtt_time = scheduleto;
    s->datatimer = 0;   /* EE 99.08.23 */

    switch ( s->state ) {

        case tcp_StateLISTEN:   /* accepting SYNs */
            /* save his ethernet address */
            if ( _pktipofs )
                movmem(&((((eth_Header *)ip) - 1)->source), &s->hisethaddr, sizeof(eth_address));
            if ( flags & tcp_FlagSYN ) {

                if ( ip->tos > s->tos )
                    s->tos = ip->tos;
                else if ( ip->tos < s->tos ) {
                    /* RFC 793 says we should close connection */
                    /* we best not do that while SunOS ignores TOS */
                }

                s->acknum = intel( tp->seqnum ) + 1;
                s->hisport = intel16( tp->srcPort );
                s->hisaddr = intel( ip->source );
                s->flags = tcp_FlagSYN | tcp_FlagACK;
                s->state = tcp_StateSYNREC;
                s->unhappy = true;
                tcp_send(s, __LINE__);    /* we must respond immediately */

                s->timeout = set_timeout( tcp_TIMEOUT );
            } else
                tcp_rst( ip , tp );  /* send a reset */

            return;

    case tcp_StateSYNSENT:  /* added ACK Section */
            if ( flags & tcp_FlagSYN ) {

                if ( ip->tos > s->tos )
                    s->tos = ip->tos;
                else if ( ip->tos < s->tos ) {
                    /* RFC 793 says we should close connection */
                    /* we best not do that while SunOS ignores TOS */
                }

                s->flags = tcp_FlagACK;
                s->timeout = set_timeout( tcp_TIMEOUT );

                /* FlagACK means connection established, else SYNREC */
                if ( flags & tcp_FlagACK) {
                    /* but is it for the correct session ? */
                if (tp->acknum == intel(s->seqnum + 1)) {
                s->state = tcp_StateESTAB;
                s->seqnum++;    /* good increment */
                s->acknum = intel( tp->seqnum  ) + 1;   /* 32 bits */
                tcp_ProcessData(s, tp, len, &ph, &flags);    /* someone may try it */ /* S. Lawson */
                s->unhappy = true;             /* rely on their attempts */
                tcp_send( s, __LINE__ );
            } else {
                /* wrong ack, force a RST and resend SYN soon*/
                s->flags = tcp_FlagRST;
                s->unhappy = true;
                tcp_send( s, __LINE__ );
                s->flags = tcp_FlagSYN;
                tcp_send( s, __LINE__ );
                    }
                } else {
                    s->acknum++;
                    s->state = tcp_StateSYNREC;
                    return;
                }
            } else
                tcp_rst( ip, tp );
            break;

        case tcp_StateSYNREC:   /* recSYNSENT, sentACK, waiting  EST */
            if ( flags & tcp_FlagSYN ) {
                s->flags = tcp_FlagSYN | tcp_FlagACK;
                s->unhappy = true;
                tcp_send(s, __LINE__);
                s->timeout = set_timeout( tcp_TIMEOUT );
                return;
            }
            if ( (flags & tcp_FlagACK) && (intel( tp->acknum ) == (s->seqnum + 1))) {
                if ( (s->window = intel16( tp->window )) > 0x7fff )
                    s->window = 0x7fff;
                s->flags = tcp_FlagACK;
                s->state = tcp_StateESTAB;
                s->seqnum++;
                s->timeout = 0;     /* never timeout */
                s->unhappy = false;
                return;
            }

⌨️ 快捷键说明

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