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

📄 nettcp.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 5 页
字号:

    "ACK+R+F",                  /* 21 = 16 + 4 + 1 */

    "ACK+R+S",                  /* 22 = 16 + 4 + 2 */

    "ACK+R+S+F",                /* 23 = 16 + 4 + 2 + 1 */

    "ACK+PUSH",                 /* 24 = 16 + 8 */

    "ACK+P+F",                  /* 25 = 16 + 8 + 1 */

    "ACK+P+S",                  /* 26 = 16 + 8 + 2 */

    "ACK+P+S+F",                /* 27 = 16 + 8 + 2 + 1 */

    "ACK+P+R",                  /* 28 = 16 + 8 + 4 */

    "A+P+R+F",                  /* 29 = 16 + 8 + 4 + 1 */

    "A+P+R+S",                  /* 30 = 16 + 8 + 4 + 2 */

    "A+P+R+S+F"                 /* 31 = 16 + 8 + 4 + 2 + 1 */

};



#if ECHO_SUPPORT > 0

//char tcpEchoStack[STACK_SIZE];          /* The TCP echo task stack. */

#endif



/***********************************/

/*** PUBLIC FUNCTION DEFINITIONS ***/

/***********************************/

/*

 * Initialize the TCP subsystem.

 */

void tcpInit(void)

{

    int i;

    

    /* The TCB free list. */

    memset(tcbs, 0, sizeof(tcbs));

    topTcpCB = &tcbs[0];

    for (i = 0; i < MAXTCP; i++) {

        tcbs[i].next = &tcbs[i + 1];

        /* Prev referencing self indicates that it's on the free list. */

        tcbs[i].prev = &tcbs[i];

        timerCreate(&tcbs[i].resendTimer);

        timerCreate(&tcbs[i].keepTimer);

        tcbs[i].state = CLOSED;

    }

    tcbs[MAXTCP - 1].next = NULL;



    /* The TCB hash table. */

    memset(&tcbTbl, 0, sizeof(tcbTbl));

    

    /* The TCP stats. */

#if STATS_SUPPORT > 0

    memset(&tcpStats, 0, sizeof(tcpStats));

    tcpStats.headLine.fmtStr    = "\t\tTCP STATISTICS\r\n";

    tcpStats.curFree.fmtStr     = "\tCURRENT FREE: %5lu\r\n";

    tcpStats.curFree.val        = MAXTCP;

    tcpStats.minFree.fmtStr     = "\tMINIMUM FREE: %5lu\r\n";

    tcpStats.minFree.val        = MAXTCP;

    tcpStats.runt.fmtStr        = "\tRUNT HEADERS: %5lu\r\n";

    tcpStats.checksum.fmtStr    = "\tBAD CHECKSUM: %5lu\r\n";

    tcpStats.conout.fmtStr      = "\tOUT CONNECTS: %5lu\r\n";

    tcpStats.conin.fmtStr       = "\tIN CONNECTS : %5lu\r\n";

    tcpStats.resetOut.fmtStr    = "\tRESETS SENT : %5lu\r\n";

    tcpStats.resetIn.fmtStr     = "\tRESETS REC'D: %5lu\r\n";

#endif

    

    /* The new sequence number offset. */

    newISNOffset = magic();

    

#if ECHO_SUPPORT > 0

    /* Start the TCP echo server. */

	/*

	 * porting to ros33

	 */

 //   sta_tsk(TCPTASK_ID, 0);  //start echotask

#endif

}

/************************************0001*************************************************************************/

/* 

 * Return a new TCP descriptor on success or an error code (negative) on 

 *  failure. 

 */

int tcpOpen(void)

{

    int st;

    TCPCB *tcb;

    

    OS_ENTER_CRITICAL();

    if ((tcb = topTcpCB) != NULL) {

        topTcpCB = topTcpCB->next;

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

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

    }

    OS_EXIT_CRITICAL();

   

    if (!tcb)

        st = TCPERR_ALLOC;

    else {

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

        tcb->next = tcb;        /* Self ref => unlinked. */

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

        tcb->freeOnClose = 0;

#if DEBUG_SUPPORT == 0               

    tcb->traceLevel = 0;

#else

        tcb->traceLevel = LOG_INFO;

#endif

        tcb->keepAlive = 0;

        tcb->keepProbes = 0;

 

        /* Grab semaphores. */

        if (!tcb->connectSem)

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

                st = TCPERR_ALLOC;

        if (!tcb->readSem)

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

                st = TCPERR_ALLOC;

        if (!tcb->writeSem)

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

                st = TCPERR_ALLOC;

        if (!tcb->mutex)

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

                st = TCPERR_ALLOC;

        TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpOpen[%d]: Opened", st));

    }

    

    return st;

}

/********************************************************0052***************************************/

/* 

 * Close a TCP connection and release the descriptor.

 * Any outstanding packets in the queues are dropped.

 * Return 0 on success when the peer acknowledges our message

 * or an error code on failure. 

 */

int tcpClose(u_int td)

{

    int st = 0;

    TCPCB *tcb = &tcbs[td];



    /* Protect from race on tcb->state. */

    OS_ENTER_CRITICAL();    

    if (td >= MAXTCP || tcb->prev == tcb) {

        OS_EXIT_CRITICAL();

        st = TCPERR_PARAM;



    } else if (tcb->state == CLOSED) {

        OS_EXIT_CRITICAL();

        TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpClose[%d]: Freeing closed", td));

        tcbFree(tcb);

        

    } else {

        /* 

         * Initiate a half-close on our side by sending a FIN.  The

         * freeOnClose flag is set so the TCB will be freed when the

         * state reaches CLOSED.  Note that a timer will limit the

         * time that we wait in FINWAIT2.

         */

        tcb->freeOnClose = !0;

        OS_EXIT_CRITICAL();

        

        st = tcpDisconnect(td);

        TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpClose[%d]: Closed", td));

    }   

	OSSemFree();
	
    return st;

}



/*

 * Bind an IP address and port number in the sockaddr structure as our

 * address on a TCP connection.

 * Note: The IP address must be zero (wild) or equal to localHost since that

 * is all that ipDispatch() will recognize.  You can only bind a CLOSED

 * connection.

 * Return 0 on success, an error code on failure.

 */

int tcpBind(u_int td, struct sockaddr_in *myAddr)

{

    int st = 0;

    TCPCB *tcb = &tcbs[td];

    

    if (td >= MAXTCP || tcb->prev == tcb || !myAddr)

        st = TCPERR_PARAM;

    else if (myAddr->ipAddr != 0 && myAddr->ipAddr != localHost)

        st = TCPERR_INVADDR;

    else if (tcb->state != CLOSED)

        st = TCPERR_CONNECT;    /* Can't bind an active connection. */

    else {

        tcb->ipSrcAddr = htonl(myAddr->ipAddr);	//该ip已经是net格式

        tcb->tcpSrcPort = htons(myAddr->sin_port);



        TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpBind[%d]: to %s:%u mss %d", 

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

                    ip_ntoa(tcb->ipSrcAddr), ntohs(tcb->tcpSrcPort),

                    tcb->mss));

    }

    

    return st;

}

/***************************************0053**********************************/

/*

 * Establish a connection with a remote host.  Unless tcpBind() has been called,

 * the local IP address and port number are generated automatically.

 * Return 0 on success, an error code on failure.

 */

int tcpConnectJiffy(u_int td, const struct sockaddr_in *remoteAddr, u_char tos, u_int timeout)

{

    int st = 0;

    TCPCB *tcb = &tcbs[td];

#if ONETASK_SUPPORT == 0      

    u_long abortTime;

#endif

    long dTime = timeout;

    u_int8 err;

    

/* We don't use the timeout argument when running in a single task! 

   We also don't want to be able to block.

   And we want to be able to do a quick poll, without having to make a timeout of at least 1 jiffy. */

#if ONETASK_SUPPORT == 0      

    if (timeout)

        abortTime = jiffyTime() + timeout;

#endif

        

    if (td >= MAXTCP || tcb->prev == tcb || !remoteAddr)

        st = TCPERR_PARAM;

    else if (remoteAddr->ipAddr == 0 || remoteAddr->sin_port == 0)

        st = TCPERR_INVADDR;

    else if (tcb->ipSrcAddr == 0 && localHost == 0)

        st = TCPERR_CONFIG;

    else if (tcb->state != CLOSED)

        st = TCPERR_CONNECT;    /* Already connected! */

    else {

        tcbInit(tcb);

        tcb->ipTOS = tos;

        if (tcb->ipSrcAddr == 0)

            tcb->ipSrcAddr = htonl(localHost);

        if (tcb->tcpSrcPort == 0) {

            OS_ENTER_CRITICAL();

            tcb->tcpSrcPort = htons(tcpFreePort++);

            OS_EXIT_CRITICAL();

        }

        tcb->ipDstAddr = htonl(remoteAddr->ipAddr);

        tcb->tcpDstPort = htons(remoteAddr->sin_port);

/******************************************************************0097**********************************/

        /* 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);



        /* 

         * Load the connection structure and link the TCB into the connection

         * table so that tcpInput can find it.

         */

        tcb->conn.remoteIPAddr = tcb->ipDstAddr;

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

        tcb->conn.localIPAddr = tcb->ipSrcAddr;

        tcb->conn.localPort = tcb->tcpSrcPort;

        tcbLink(tcb);



        TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpConnect[%d]: to %s:%u mss %d", 

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

                    ip_ntoa(tcb->ipDstAddr), ntohs(tcb->tcpDstPort),

                    tcb->mss));

        

        /* Send SYN, go into SYN_SENT state */

        tcb->flags |= ACTIVE;

        sendSyn(tcb);

        setState(tcb, SYN_SENT);

        tcpOutput(tcb);

        STATS(tcpStats.conout.val++;)

        

/* We don't use the timeout argument when running in a single task! 

   We also don't want to be able to block.

   And want to be able to do a quick poll, without having to make a timeout of at least 1 jiffy. */

#if ONETASK_SUPPORT == 0      

      

        /* Wait for connection or failure. */

        while(tcb->state != ESTABLISHED && !st) {

            if (tcb->state == CLOSED) {

                /* 

                 * Post the connect semaphore in case another task was also

                 * waiting on it.  Unlikely for connect but a single extra

                 * post costs little and improves robustness.

                 */

                OSSemPost(tcb->connectSem);

                if (tcb->closeReason)

                    st = tcb->closeReason;

                else

                    st = TCPERR_EOF;

            } else if (!timeout || (dTime = diffJTime(abortTime)) > 0) {

                OSSemPend(tcb->connectSem, (UINT)dTime, &err);

            } else {                    /* Abort on timeout. */

                closeSelf(tcb, TCPERR_TIMEOUT);

                tcbUnlink(tcb);

            }

        }

#endif



    }



   TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpConnect[%d]: %s", 

                (int)(tcb - &tcbs[0]), tcbStates[tcb->state]));

    

    return st;

}



/*

 * tcpDisconnect - Tell the peer that we will not be sending any more data

 * (i.e. perform a half close on a connection).  tcpRead() will then

 * wait until the connection closes.

 * Return 0 when the peer acknowledges our message or an error code on

 * failure.

 */

int tcpDisconnect(u_int td)

{

    int st = 0;

    TCPCB *tcb = &tcbs[td];

    

    TCPDEBUG((tcb->traceLevel, TL_TCP, "tcpDisconnect[%d]: state %s", 

                (int)(tcb - &tcbs[0]), tcbStates[tcb->state]));

                    

    if (td >= MAXTCP || tcb->prev == tcb)

        st = TCPERR_PARAM;

        

    else {

        switch(tcb->state){

        case LISTEN:

        case SYN_SENT:

            /*

             * We haven't established a connection yet so we can just

             * close this.

             */

            closeSelf(tcb, 0);

⌨️ 快捷键说明

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