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

📄 pctcp.c

📁 dos下开发TCP网络的库文件部分
💻 C
📖 第 1 页 / 共 5 页
字号:

            break;
        case tcp_StateESTAB:
        case tcp_StateESTCL:
        case tcp_StateCLOSWT:

            /* handle lost SYN */
            if ((flags & tcp_FlagSYN) && (flags & tcp_FlagACK)) {
                tcp_send( s, __LINE__ );
                return;
            }

            if ( !(flags & tcp_FlagACK)) return;  /* must ack somthing */

#ifdef NOTUSED  // S. Lawson - above two IFs make this impossible
            if ( flags & tcp_FlagSYN ) {
                tcp_rst( ip , tp );
                return;
            }
#endif

            s->timeout = 0l;    /* we do not timeout at this point */

            /* process ack value in packet - but only if it falls
             * within current window */

            ldiff = intel( tp->acknum ) - s->seqnum;
            diff = (int) ldiff;

            if ( ldiff >= 0 && diff <= s->datalen ) {
                s->datalen -= diff;
                s->unacked -= diff;
                if (s->datalen < 0) s->datalen = 0; /* remote proto error */
                if ( s->queuelen ) {
                    s->queue += diff;
                    s->queuelen -= diff;
                } else
                    movmem(s->data + diff, s->data, s->datalen );
                s->seqnum += ldiff;
            } else {
#ifdef DEBUG
    if(debug_on >1) printf("tcphandler confused so set unacked back to 0 from %u\n",s->unacked);
#endif// DEBUG
                s->unacked = 0;
            }
            if (s->unacked < 0) s->unacked = 0;

            s->flags = tcp_FlagACK;
            tcp_ProcessData(s, tp, len, &ph, &flags);   // S. Lawson

#ifdef NOTUSED
        // S. Lawson - this chokes on some stacks. (data+fin) comes in, the
        // FIN isn't ACK'd and they resend the whole segment rather than
        // just the FIN (getting us back to not ACKing FIN on (data+fin)
            if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
                && ( s->acknum == intel( tp->seqnum ))) {
#else
            if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
                && s->frag[0]==0L) {
#endif
                s->acknum ++;
                if ( ! s->err_msg ) s->err_msg = "Connection closed";
                s->state = tcp_StateCLOSWT;
                tcp_send( s, __LINE__ );
                s->timeout = set_timeout( LASTACK_TIMEOUT );    // Added AGW 6 Jan 2001
                s->state = tcp_StateLASTACK;
                s->flags |= tcp_FlagFIN;
                s->unhappy = true;
            }

/* S. Lawson - added per below
 *   Eliminate the spurious ACK messages bug.
 *   For the window update, the length should be the
 *   data length only, so exclude the TCP header size
 *    -- Joe <jdhagen@itis.com> (this helped alot -gv)
 */
            len -= tcp_GetDataOffset(tp) << 2;

// S. Lawson - don't send on ACK unless there's more to send
//          if ( diff > 0 || len > 0 ) {
            if ( (diff > 0 && s->datalen) || len > 0 ) {   // S. Lawson
                /* need to update window, but how urgent ??? */
// S. Lawson            if ( diff > 0 || (len > (s->mss >> 1))) {
                if (s->frag[0] || (diff > 0 && s->datalen) || (len > (s->mss >> 1))) { // S. Lawson
                    tcp_send( s, __LINE__ );
                } else
                    tcp_sendsoon( s );

            }
            if ( s->state == tcp_StateESTCL )
                tcp_close( s );
            return;

        case tcp_StateFINWT1:
            /* They have not necessarily read all the data yet, we must
               still supply it as requested */

            ldiff = intel( tp->acknum ) - s->seqnum;
            diff = (int) ldiff;
            if ( ldiff >= 0 && diff <= s->datalen ) {
                s->datalen -= diff;
                s->unacked -= diff;
                if (s->datalen < 0) s->datalen = 0;
                if ( s->queuelen ) {
                    s->queue += diff;
                    s->queuelen -= diff;
                } else
                    movmem(s->data + diff, s->data, s->datalen );
                s->seqnum += ldiff;
                if (ldiff == 0 || s->unacked < 0) s->unacked = 0;

            }

            /* they may still be transmitting data, we must read it */

            tcp_ProcessData(s, tp, len, &ph, &flags);   // S. Lawson

            /* check if other tcp has acked all sent data and is ready
               to change states */

// S. Lawson        if ( (flags & (tcp_FlagFIN|tcp_FlagACK) ) == (tcp_FlagFIN|tcp_FlagACK)) {
            if ( s->frag[0]==0L && (flags & (tcp_FlagFIN|tcp_FlagACK) ) ==
                 (tcp_FlagFIN|tcp_FlagACK)) {           // S. Lawson

#ifdef NOTUSED  // S. Lawson - below is untrue, misses a condition, and moves
                //             to the wrong state anyway

                /* trying to do similtaneous close */
                if (( intel( tp->acknum ) >= s->seqnum + 1 ) &&
                    ( intel( tp->seqnum) == s->acknum )) {
                    s->seqnum++;
// we shouldn't be inc'ing the ack
//                  s->acknum++;
                    s->flags = tcp_FlagACK;
                    tcp_send( s, __LINE__ );
                    s->unhappy = false;
                    s->timeout = set_timeout( 2 );
                    s->state = tcp_StateCLOSED;
                }
#else

                if ( intel( tp->seqnum) == s->acknum ) {
                    word next_state;

                    s->acknum++;                // we must ACK their FIN!
                    if (( intel( tp->acknum ) >= s->seqnum + 1 )) {
                        // Not simultaneous close (they've ACKed our FIN)
                        // We need to ACK their FIN and move to TIME_WAIT
                        s->seqnum++;
                        next_state=tcp_StateTIMEWT;
                    } else {
                        // Simultaneous close (haven't ACKed our FIN yet)
                        // We need to ACK their FIN and move to CLOSING
                        next_state=tcp_StateCLOSING;
                    }
                    s->flags = tcp_FlagACK;
                    tcp_send( s, __LINE__ );
                    s->unhappy = false;
                    if ((s->state = next_state) == tcp_StateTIMEWT)
                        s->timeout = set_timeout( TW_TO );
                    else
                        s->timeout = set_timeout( tcp_TIMEOUT );
                }
#endif
            } else if ( flags & tcp_FlagACK ) {
                /* other side is legitimately acking our fin */
                if (( intel( tp->acknum ) == s->seqnum + 1 ) &&
                    ( intel( tp->seqnum ) == s->acknum ) &&
                    (  s->datalen == 0 )) {
                        s->seqnum++;
// they are just acking our seq num, not sending more data for us to ack
//                      s->acknum++;
                        s->state = tcp_StateFINWT2;
                        s->timeout = set_timeout( tcp_TIMEOUT );  // S. Lawson
                        s->unhappy = false; /* we don't send anything */
                }
            }
            break;

        case tcp_StateFINWT2:

            /* they may still be transmitting data, we must read it */
            tcp_ProcessData(s, tp, len, &ph, &flags);           // S. Lawson

            if (s->frag[0] != 0L) break;        // S. Lawson
            if ((flags & (tcp_FlagACK | tcp_FlagFIN)) ==
                  (tcp_FlagACK | tcp_FlagFIN)) {
                if (( intel( tp->acknum ) == s->seqnum) &&
                    ( intel( tp->seqnum ) == s->acknum )) {
                    s->acknum++;
                    s->flags = tcp_FlagACK;
                    tcp_send( s, __LINE__ );
                    s->unhappy = false; /* we don't send anything */
#ifdef NOTUSED  // S. Lawson - move to TIME_WAIT, not CLOSED
                    s->timeout = set_timeout( 2 );
                    s->state = tcp_StateCLOSED;
#else
                    s->timeout = set_timeout( TW_TO );
                    s->state = tcp_StateTIMEWT;
#endif
                    return;
                }
            }
            break;

        case tcp_StateCLOSING:
            if ((flags & (tcp_FlagACK | tcp_FlagFIN)) == tcp_FlagACK ) {
// S. Lawson - per FINWT1 above, tcp->acknum should be s->seqnum+1, which
//             we should cause us to bump s->seqnum to match
//              if (( tp->acknum == intel(s->seqnum) ) &&
//AGW           if (( tp->acknum >= (intel(s->seqnum) + 1) ) &&  // S. Lawson

                if ((laterthan(intel(tp->acknum),s->seqnum) ) && //AGW - moved intel() so +1 OK 6th Jan 2001
                    ( tp->seqnum == intel(s->acknum))) {
                    s->seqnum++;                                 // S. Lawson
                    s->state = tcp_StateTIMEWT;
                    s->timeout = set_timeout( TW_TO );
                    s->unhappy = false;
                }
            }
            break;

        case tcp_StateLASTACK:
            if ( flags & tcp_FlagFIN )
            {   /* they lost our two packets, back up */
                        s->flags = tcp_FlagACK | tcp_FlagFIN;
                        tcp_send( s, __LINE__ );
                        s->unhappy = TRUE;  /* FALSE; */
                        return;
            } else
            {
//                      if (( intel( tp->acknum ) == (s->seqnum + 1 )) &&
                        if ((laterthan(intel(tp->acknum),s->seqnum) ) &&        // AGW allow for any later acks 6th Jan 2001
                            ( intel( tp->seqnum ) == s->acknum ))
                        {
                                s->state = tcp_StateCLOSED;     /* no 2msl necessary */
                                s->unhappy = false;             /* we're done */
                                return;
                    }
            }
            break;

        case tcp_StateTIMEWT:
            if ( (flags & (tcp_FlagACK | tcp_FlagFIN)) == (tcp_FlagACK | tcp_FlagFIN)) {
                /* he needs an ack */
                s->flags = tcp_FlagACK;
                tcp_send( s, __LINE__ );
                s->unhappy = false;
                s->state = tcp_StateCLOSED;     /* support 2 msl in rst code */
            }
            break;
        }
    if (s->unhappy) tcp_sendsoon(s);
}

/*
 * Process the data in an incoming packet.
 * Called from all states where incoming data can be received: established,
 * fin-wait-1, fin-wait-2
 * S. Lawson - added flagsp so we can disable FIN with segment(s) missing
 */
static void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len,
                            tcp_PseudoHeader *ph, word *flagsp)
{
    long ldiff, tmpldiff;               // S. Lawson
    int diff, tmpdiff, x;               // S. Lawson
    word flags;
    byte *dp;

// S. Lawson    word *options, numoptions, opt_temp;
    byte *options;                      // S. Lawson
    word numoptions, opt_temp;          // S. Lawson

    if ( s->stress > 0 ) s->stress--;

    if ( (s->window = intel16( tp->window )) > 0x7fff )
        s->window = 0x7fff;

    flags = intel16( tp->flags );
    ldiff = s->acknum - intel( tp->seqnum );

    if ( flags & tcp_FlagSYN ) ldiff--;  /* back up to 0 */
    diff = abs((int) ldiff);            // S. Lawson - make positive

    /* find the data portion */
    x = tcp_GetDataOffset(tp) << 2;     /* quadword to byte format */
    dp = (byte *)tp + x;

    /* process those options */
    if ( (numoptions = x - sizeof( tcp_Header )) != 0 ) {
// S. Lawson    options = (word *)((byte *)(tp) + sizeof( tcp_Header));
        options = ((byte *)(tp) + sizeof( tcp_Header)); // S. Lawson
        while ( numoptions-- > 0 ) {
            switch ( *options++ ) {
                case  0 : numoptions = 0;       /* end of options */
                          break;
                case  1 : break;                /* nop */

                          /* we are very liberal on MSS stuff */
// S. Lawson - this is broken, *options includes type/len bytes
//              case  2 : if (*options == 2) {
                case  2 : if (*options == 4) {
                              opt_temp = intel16( *(word*)(&options[1]));
                              if (opt_temp < s->mss )
                                  s->mss = opt_temp;
                          }
#ifdef NOTUSED  // S. Lawson - this is broken, *options includes type/len
                          numoptions -= 2 + *options;
                          options += *options;
                          break;
#else
                // S. Lawson - fallthrough (case 2),
                //             also skips unknown options (thanks GV)
                default:                // S. Lawson - handle 2 and others
                          numoptions -= (*options - 1);
                          options += (*options - 1);
                          break;
#endif
            }
        }
    }
    /* done option processing */

    len -= x;           /* remove the header length */
    if ( ldiff >= 0 ) {  /* skip already received bytes */
        dp += diff;
        len -= diff;

        if (s->dataHandler) {
            s->acknum += s->dataHandler(s, dp, len, ph, tp);  // 94.11.19
//          s->acknum += s->dataHandler(s, dp, len);
        } else {
            /* no handler, just dump to buffer, should be indexed, handles goofs */
            /* limit receive size to our window */
            if ( s->rdatalen >= 0 ) {
                if ( len > ( x = s->maxrdatalen - s->rdatalen )) {
                    len = x;
                }
                // S. Lawson - no writing into fragment
                if (s->frag[0] != 0L) {
                    tmpldiff=s->frag[0] - s->acknum;
                    tmpdiff= abs((int) tmpldiff);
                    if (tmpldiff>=0 && len>tmpdiff) len=tmpdiff;
                }

                if ( len > 0 ) {
                    s->acknum += len;   /* our new ack begins at end of data */
                    movmem(dp, s->rdata + s->rdatalen, len );
                    s->rdatalen += len;
/*
                    s->karn_count = 3;
*/
                }
                // S. Lawson - see if we reached fragment
                if (s->frag[0] != 0L) {
                    if (s->frag[0]==s->acknum) {
                       tmpldiff=s->frag[1] - s->acknum;
                       tmpdiff=abs((int) tmpldiff);
                       if (tmpldiff>0) {
                          s->rdatalen += tmpdiff;
                          s->acknum=s->frag[1];
                       }
                       s->frag[0]=s->frag[1]=0L;
                    }
                }
            }
        }
        s->unhappy = (s->datalen) ? true : false;
        if (ldiff == 

⌨️ 快捷键说明

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