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

📄 nettcp.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
            if ((ntcb = topTcpCB) == NULL) {

                OS_EXIT_CRITICAL();

                

                /* This may fail, but we should at least try */

                tcpReset(inBuf, ipHdr, tcpHdr, (unsigned short)segLen);

                return;

            } else {

                topTcpCB = topTcpCB->next;

                ntcb->next = ntcb;  /* Next -> self => neither free nor linked. */

                ntcb->prev = NULL;  /* Always NULL when neither free nor linked. */

                STATS(if (--tcpStats.curFree.val < tcpStats.minFree.val)

                        tcpStats.minFree.val = tcpStats.curFree.val;)

                OS_EXIT_CRITICAL();

            }

            

            /* Duplicate the TCB but must preserve the semaphores. */

            connectSem = ntcb->connectSem;

            readSem = ntcb->readSem;

            writeSem = ntcb->writeSem;

            mutex = ntcb->mutex;

            memcpy(ntcb, tcb, sizeof(TCPCB));

            ntcb->connectSem = connectSem;

            ntcb->readSem = readSem;

            ntcb->writeSem = writeSem;

            ntcb->mutex = mutex;

#define TCP_SEM_FIX

#ifdef TCP_SEM_FIX

            /* Grab semaphores if they don't already exist. */

            if (!ntcb->readSem)

                if ((ntcb->readSem = OSSemCreate(0)) == 0)

                    netpanic("TCPERR_ALLOC");
            if (!ntcb->connectSem)

                if ((ntcb->connectSem = OSSemCreate(0)) == 0)

                    netpanic("TCPERR_ALLOC");


            if (!ntcb->writeSem)

                if ((ntcb->writeSem = OSSemCreate(0)) == 0)

                    netpanic("TCPERR_ALLOC");

            if (!ntcb->mutex)

                if ((ntcb->mutex = OSSemCreate(1)) == 0)

                    netpanic("TCPERR_ALLOC");

#endif

            /* 

             * Put this on the parent's accept queue.

             */

            listenQPush(tcb, ntcb);

            

            tcb = ntcb;

            

        /* Otherwise we use the original TCB. */

        } else {

            tcbUnlink(tcb); /* It'll be put back on later */

        }



        /* Load the local address and remote address and port into the TCB. */

        tcb->ipSrcAddr = tcb->conn.localIPAddr = ipHdr->ip_dst.s_addr;

        tcb->ipDstAddr = tcb->conn.remoteIPAddr = ipHdr->ip_src.s_addr;

        tcb->tcpDstPort = tcb->conn.remotePort = tcpHdr->srcPort;



        /* Initialize connection parameters. */     

        tcb->rcv.wnd = TCP_DEFWND;

        tcb->mss = ipMTU(tcb->ipDstAddr) - sizeof(IPHdr) - sizeof(TCPHdr);

        tcb->mss = MAX(tcb->mss, TCP_MINMSS);

        tcb->minFreeBufs = ((tcb->mss + NBUFSZ) / NBUFSZ);



        /* NOW put it on the right hash chain */

        tcbLink(tcb);

    }

    

    TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpInput[%d]: %s:%u->%s:%u %d@%lu",

                (int)(tcb - & tcbs[0]),

                ip_ntoa2(ipHdr->ip_src.s_addr), ntohs(tcpHdr->srcPort),

                ip_ntoa(ipHdr->ip_dst.s_addr), ntohs(tcpHdr->dstPort),

                segLen, tcpHdr->seq));

    TCPDEBUG((tcb->traceLevel, TL_TCP, "               %s %lu win %u",

                tcpFlagLabel[tcpHdr->flags & TCPFLAGLABELMASK],

                tcpHdr->ack, tcpHdr->win));

    TCPDEBUG((tcb->traceLevel + 2, TL_TCP, "          IP: %.*H", 

                ipHeadLen * 2, (char *)ipHdr));

    TCPDEBUG((tcb->traceLevel + 2, TL_TCP, "         TCP: %.*H", 

                tcpHeadLen * 2, (char *)tcpHdr));

    if (segLen > 0) {

        if (tcpHeadLen + sizeof(IPHdr) < inBuf->len) {

            TCPDEBUG((tcb->traceLevel, TL_TCP, "        DATA: %.*H",

                        MIN(segLen, 20) * 2, (char *)tcpHdr + tcpHeadLen));

        } else if (inBuf->nextBuf) {

      //      NBuf *n0 = inBuf->nextBuf;                                                     修改

            TCPDEBUG((tcb->traceLevel, TL_TCP, "        DATA: %.*H",

                        MIN(segLen, 20) * 2, nBUFTOPTR(n0, char *)));

        }

    }

                

    /*

     * If we're doing keep alive, update the keep alive timer.

     */

    if (tcb->keepAlive) {

        tcb->keepTime = OSTimeGet() + tcb->keepAlive;

        tcb->keepProbes = 0;

        TCPDEBUG((tcb->traceLevel + 1, TL_TCP, "tcpInput: Keepalive set for %lu", 

                    (int)(tcb - & tcbs[0]),

                    tcb->keepTime - OSTimeGet()));

        timeoutJiffy(

                &tcb->keepTimer, 

                tcb->keepTime, 

                keepTimeout, 

                tcb);

    }

    

    

    /* Do unsynchronized-state processing (p. 64-68) */

    switch(tcb->state){

    case CLOSED:

        if(tcpHdr->flags & TH_RST) {

            TCPDEBUG((tcb->traceLevel - 1, TL_TCP, "tcpInput[%d]: Dropping RESET on CLOSED",

                    (int)(tcb - & tcbs[0])));

            STATS(tcpStats.resetIn.val++;)

            nFreeChain(inBuf);

        } else

            tcpReset(inBuf, ipHdr, tcpHdr, (unsigned short)segLen);

        return;

    case LISTEN:

        if(tcpHdr->flags & TH_RST) {

            /*

             * XXX - What would it mean if we got a reset on a listening

             * connection?  After all, we shouldn't have sent anything!

             */

            TCPDEBUG((tcb->traceLevel - 1, TL_TCP, "tcpInput[%d]: Dropping RESET on LISTEN",

                    (int)(tcb - & tcbs[0])));

            STATS(tcpStats.resetIn.val++;)

            nFreeChain(inBuf);

            return;

        }

        if(tcpHdr->flags & TH_ACK){

            tcpReset(inBuf, ipHdr, tcpHdr, (unsigned short)segLen);

            return;

        }

        if(tcpHdr->flags & TH_SYN){

            /* 

             * Security check (RFC 793 pg 65) skipped here.

             *

             * Check incoming precedence (RFC 793 pg 66) and if it's

             * greater than ours, upgrade ours.  In fact we actually

             * adopt it's entire TOS.

             */

            if(IPTOS_PREC(ipHdr->ip_tos) > IPTOS_PREC(tcb->ipTOS)) {

                TCPDEBUG((tcb->traceLevel - 1, TL_TCP, 

                    "tcpInput[%d]: Changing TOS from %d to %d",

                    (int)(tcb - & tcbs[0]), tcb->ipTOS, ipHdr->ip_tos));

                tcb->ipTOS = ipHdr->ip_tos;

            }

    

            STATS(tcpStats.conin.val++;)

            procSyn(tcb, tcpHdr);

            sendSyn(tcb);

            setState(tcb, SYN_RECEIVED);        

            /* If the segment contains no data then we're done. */

            if(segLen == 0 && !(tcpHdr->flags & TH_FIN)) {

                nFreeChain(inBuf);

                tcpOutput(tcb);

                return;

            }

        } else {

            TCPDEBUG((tcb->traceLevel - 1, TL_TCP, "tcpInput[%d]: Dropping non-SYN in LISTEN",

                (int)(tcb - & tcbs[0])));

            nFreeChain(inBuf);

            return;

        }

        /* At this point the segment contains data - continue processing. */

        break;

    case SYN_SENT:

        if(tcpHdr->flags & TH_ACK){

            if(!seqWithin(tcpHdr->ack, tcb->iss + 1, tcb->snd.nxt)) {

                tcpReset(inBuf, ipHdr, tcpHdr, (unsigned short)segLen);

                return;

            }

        }

        if(tcpHdr->flags & TH_RST){ /* p 67 */

            if(tcpHdr->flags & TH_ACK){

                /*

                 * The ack must be acceptable since we just checked it.

                 * This is how the remote side refuses connect requests.

                 */

                closeSelf(tcb, TCPERR_RESET);

            }

            TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpInput[%d]: Dropping RESET on SYN-SENT",

                (int)(tcb - & tcbs[0])));

            STATS(tcpStats.resetIn.val++;)

            nFreeChain(inBuf);

            return;

        }

        

        /* (Security check skipped here) */

        

        /* Check incoming precedence; it must match if there's an ACK */

        if(tcpHdr->flags & TH_ACK) {

            if(IPTOS_PREC(ipHdr->ip_tos) != IPTOS_PREC(tcb->ipTOS)) {

                TCPDEBUG((LOG_WARNING, TL_TCP, "tcpInput[%d]: in TOS PREC %u != our PREC %u",

                        (int)(tcb - &tcbs[0]),

                        IPTOS_PREC(ipHdr->ip_tos), 

                        IPTOS_PREC(tcb->ipTOS)));

                tcpReset(inBuf, ipHdr, tcpHdr, (unsigned short)segLen);

                return;

            }

        } else {

            if(IPTOS_PREC(ipHdr->ip_tos) > IPTOS_PREC(tcb->ipTOS)) {

                TCPDEBUG((tcb->traceLevel - 1, TL_TCP, 

                    "tcpInput[%d]: Changing TOS from %d to %d",

                    (int)(tcb - & tcbs[0]), tcb->ipTOS, ipHdr->ip_tos));

                tcb->ipTOS = ipHdr->ip_tos;

            }

        }

        

        if(tcpHdr->flags & TH_SYN){

            procSyn(tcb, tcpHdr);

            if(tcpHdr->flags & TH_ACK){

                /*

                 * Our SYN has been acked, otherwise the ACK

                 * wouldn't have been valid.

                 */

                tcbUpdate(tcb, tcpHdr);

                setState(tcb,ESTABLISHED);

            } else {

                setState(tcb,SYN_RECEIVED);

            }

            /* If no data then we're done. */

            if(segLen == 0 && !(tcpHdr->flags & TH_FIN)) {

                nFreeChain(inBuf);  

                tcpOutput(tcb);

                return;

            }

            

        /* Ignore segment if neither SYN or RST is set */

        } else {

            TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpInput[%d]: Dropping non-SYN in SYN-SENT",

                (int)(tcb - & tcbs[0])));

            STATS(tcpStats.resetIn.val++;)

            nFreeChain(inBuf);  

            return;

        }

        

        default:             /* At this point there is valid data in the segment so continue processing. */     /**加了一个default****/

                    break;

    }

    

    /*

     * We reach this point directly in any synchronized state. Note that

     * if we fell through from LISTEN or SYN_SENT processing because of a

     * data-bearing SYN, then window trimming and sequence testing "cannot

     * fail".

     */



    /*

     * Trim segment to fit receive window.  If none of the segment is 

     * acceptable, then if the segment isn't a reset, resend the last

     * sent ACK. 

     */

    if ((segLen = trimSeg(tcb, tcpHdr, inBuf, ipHeadLen + tcpHeadLen, (unsigned short)segLen)) < 0) {

        if(!(tcpHdr->flags & TH_RST)){

            tcb->flags |= FORCE;

            tcpOutput(tcb);

        }

        TCPDEBUG((tcb->traceLevel - 1, TL_TCP, "tcpInput[%d]: Dropping unacceptable segment in %s", 

                    (int)(tcb - & tcbs[0]),

                    tcbStates[tcb->state]));

        STATS(tcpStats.resetIn.val++;)

        nFreeChain(inBuf);

        return;

    }

    

    /*

     * Check the segment's flags and if OK and the ACK field is set, process

     * the acknowledgement field here.  RFC 793 specifies that this is to

     * be done when the segment begins with the next expected octet

     * (i.e. at the top of the loop below) but we do it here so that we

     * clear what we can from the output queue BEFORE we drop this due

     * to a shortage of buffers or queue it in the resequencing queue.

     */

    switch(procInFlags(tcb, tcpHdr, ipHdr)) {

    case ACKCLOSE:

        closeSelf(tcb, 0);

        /*** Fall through... ***/

    case ACKDROP:

        nFreeChain(inBuf);

        return;

        

    case ACKRESET:

        tcpReset(inBuf, ipHdr, tcpHdr, (unsigned short)segLen);

        return;

    }

    

    /*

     * Before continuing, check that there are enough free buffers for normal

     * operation.  If not, we'll drop something.  If this is the next

     * data expected, drop chains from the resequencing queue until we've

     * cleared sufficient space.  If we're still short of buffers, drop this

     * segment.

     */

    if (nBUFSFREE() < (unsigned)(tcb->minFreeBufs)) {

        if(tcpHdr->seq == tcb->rcv.nxt) {

            while(nQHEAD(tcb->reseq) && nBUFSFREE() < (unsigned)(tcb->minFreeBufs)) {

                NBuf *segBuf;

                

                nDEQUEUE(tcb->reseq, segBuf);

                TCPDEBUG((tcb->traceLevel - 1, TL_TCP, 

                            "tcpInput[%d]: Clearing reseq queue",

                            (int)(tcb - & tcbs[0])));

                nFreeChain(segBuf);

            }

        }

        if (nBUFSFREE() < (unsigned)(tcb->minFreeBufs)) {

            TCPDEBUG((tcb->traceLevel - 1, TL_TCP, 

                        "tcpInput[%d]: Drop due to insufficient free bufs",

                        (int)(tcb - & tcbs[0])));

            nFreeChain(inBuf);

            inBuf = NULL;

        }

    

    /*

     * If this segment isn't the next one expected and there's data

     * or flags associated with it, put it on the resequencing

     * queue, resend the current ACK, and return.

     * NOTE: This may queue duplicate or overlapping segments.

     */

    } else if(tcpHdr->seq != tcb->rcv.nxt

            && (segLen > 0 || (tcpHdr->flags & TH_FIN))) {

        TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpInput[%d]: Queued %u", 

                    (int)(tcb - & tcbs[0]),

                    segLen));

        nEnqSort(tcb->reseq, 

⌨️ 快捷键说明

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