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

📄 tcpss.c

📁 基于nucleus操作系统的GPRS无线数据传输终端全套源文件。包括支持ARM7的BSP,操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
                        /* Since we are setting the FIN bit we must
                           bump the tcp_data_len for this packet. This
                           length is used during seq number and ack
                           comparrision. */
                        (prt->out.nextPacket->mem_tcp_data_len)++;

                        /* Save a pointer to the next packet to send. Then move
                           the next pointer forward. nextPacket should always
                           be NULL after these steps. */
                        buf_ptr = prt->out.nextPacket;
                        prt->out.nextPacket = prt->out.nextPacket->next;

                        /* Clear the event flag. */
                        prt->xmitFlag = NU_CLEAR;

                        /* Send the buffer. */
                        TCP_Xmit(prt, buf_ptr);
                    }

                    prt->state = SFW1;           /* wait for ACK of FIN */

                    return_status = -1;

                }

                break;                      /* do nothing for now ?*/


            case SCWAIT:                    /* other side already closed */

                /* Send the FIN. */
                if (prt->out.nextPacket == NU_NULL)
                {
                    prt->out.tcp_flags = TFIN | TACK;

                    TCPSS_Send_SYN_FIN(prt, 0);
                }
                else
                {
                    if (prt->xmitFlag == NU_SET)
                    {
                        UTL_Timerunset (CONTX, (UNSIGNED)prt->pindex, (INT32)1);

                        prt->out.tcp_flags = TPUSH | TACK | TFIN;

                        /* Since we are setting the FIN bit we must
                           bump the tcp_data_len for this packet. This
                           length is used during seq number and ack
                           comparrision. */
                        (prt->out.nextPacket->mem_tcp_data_len)++;

                        /* Save a pointer to the next packet to send. Then move
                           the next pointer forward. nextPacket should always
                           be NULL after these steps. */
                        buf_ptr = prt->out.nextPacket;
                        prt->out.nextPacket = prt->out.nextPacket->next;

                        /* Clear the event flag. */
                        prt->xmitFlag = NU_CLEAR;

                        /* Send the buffer. */
                        TCP_Xmit(prt, buf_ptr);
                    }

                }

                /* Deallocate any date that is in the in window. */
                if (sock_ptr->s_recvbytes)
                {
                    MEM_Buffer_Cleanup(&sock_ptr->s_recvlist);
                }

                /* Update the connection state. */
                prt->state = SLAST;

                return_status = -1;

                break;

            case STWAIT:                    /* time out yet? */

                if (INT32_CMP( (TCP_Ports[pnum]->out.lasttime + WAITTIME),
                    NU_Retrieve_Clock()) < 0)
                {
                    prt->state = SCLOSED;
                }

                 /* Upon returning the socket will be released. So break 
                   the port's link to this socket. */
                 prt->p_socketd = -1;

                 return_status = NU_SUCCESS;

                 break;

            case SLAST:

                 /* If the state is SLAST, then a FIN has already been sent.  We
                    are waiting for an ACK.  If one is not received the
                    retransmit timeout will eventually close this connection.
                 */

                 return_status = -1;

                 break;

            case SCLOSING:
            case SCLOSED:

                 /* Upon returning the socket will be released. So break 
                   the port's link to this socket. */
                 prt->p_socketd = -1;

                 return_status = NU_SUCCESS;

                 break;

            default:

                break;
        }
    }
    else
    {
        return (1);
    }

    return (return_status);

}  /* end TCPSS_Net_Close() */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCPSS_Window_Probe                                               
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       Time out for three seconds.  Then if the window has not been 
*       updated send a 1 byte packet(windowprobe).                        
*                                                                       
*   INPUTS                                                                
*
*       *prt            Pointer to a port.                               
*       nbytes          The number of bytes in the buffer parameter.     
*       *buffer         Pointer to a data buffer.                        
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       The number of bytes that were sent in window probes.             
*                                                                       
*************************************************************************/
static INT32 TCPSS_Window_Probe(TCP_PORT *prt, UINT16 nbytes, UINT8 HUGE *buffer)
{
    UINT16      nsent = 0;
    NET_BUFFER  *buf_ptr = NU_NULL;

    /* Set the probe flag. */
    prt->probeFlag = NU_SET;

    /* Set a timer event to resume this task. */
    UTL_Timerset(WINPROBE, (UNSIGNED)prt->p_socketd, PROBETIMEOUT, 0);

    /* Probe the foreign host while he is advertising a window size of 0. */
    while(prt->out.size == 0)
    {

        /* Preserve the the task pointer. */
        SCK_Sockets[prt->p_socketd]->s_TXTask = NU_Current_Task_Pointer();

        /* Suspend this task. */
        SCK_Suspend_Task(SCK_Sockets[prt->p_socketd]->s_TXTask);

        SCK_Sockets[prt->p_socketd]->s_TXTask = NU_NULL;

        /* If a close was initiated while suspension was in effect abort
           the window probe. */
        if (prt->state != SEST)
            return(NU_NOT_ESTAB);

        /* if the windowsize is still zero and no unacknowledged data has been
         * sent and the buffer has untransmitted data, then send a window
         * probe.  We depend on the retransmit logic to resend the window probe
         * until either the probe is acknowledged or the window is opened. */

        if( (prt->out.size == 0) && (prt->out.contain == 0) && (nsent < nbytes))
        {
            buf_ptr = (NET_BUFFER *)MEM_Buffer_Dequeue(&MEM_Buffer_Freelist);

            if (buf_ptr != NU_NULL)
            {
               /* Point the data pointer at an offset into the buffer large
                  enough to leave room for the header information. */
               buf_ptr->data_ptr = buf_ptr->mem_parent_packet + 
                   NET_MAX_TCP_HEADER_SIZE;

               /* move the data into the packet buffer */
               memcpy(buf_ptr->data_ptr, buffer, 1);

               /* Initialize the data length of this buffer. */
               buf_ptr->data_len            = 1;
               buf_ptr->mem_tcp_data_len    = 1;
               buf_ptr->mem_total_data_len  = 1; 
               buf_ptr->mem_option_len      = 0;

               /* Initialize the list that this packet will be deallocated to when
                  transmission is complete.
               */
               buf_ptr->mem_dlist = &prt->out.packet_list;
               buf_ptr->mem_port_index = prt->pindex;

               /* Update the amount of data in this port. */
               prt->out.contain++;

               /* Update the number of packets in this port. */
               prt->out.num_packets++;

               /* Increment the number of bytes we have sent so far. */
               nsent++;

               /* Move the location from which we are copying forward. */
               buffer++;

               /* Send the completed Packet. */
               TCP_Xmit(prt, buf_ptr);
            }
        }
        else if (prt->out.size > 0)
            break;


        /* Set a timer event to resume this task just before the retransmits
           is about finishing. */
        UTL_Timerset(WINPROBE, (UNSIGNED)prt->p_socketd, 
            (UNSIGNED)(prt->p_rto - 1),0);

        /* reset retransmits number, make the probing forever. MQ  */
        if (buf_ptr)
            buf_ptr->mem_retransmits = 1;
    }

    /* At this point if there is a packet on the outgoing packet list.  Then
     * that means the foreign host opened up his window without
     * acknowledging the window probe.  Since the probe contains the next byte
     * expected by the foreign host, go ahead and retransmit it.  Otherwise, an
     * out of order packet situation will occur and it will take longer to fully
     * recover from the 0 windowsize. */

    if (prt->out.packet_list.head != NU_NULL)
    {
        /*  Clear the timer that will retransmit the window probe.  */
        UTL_Timerunset(WINPROBE, (UNSIGNED)prt->p_socketd, (INT32)1);

        TCP_Retransmit(prt, prt->out.packet_list.head->mem_seqnum);
    }

    /* Clear the probe flag. */
    prt->probeFlag = NU_CLEAR;

    return(nsent);

} /* end TCPSS_Window_Probe() */

/************************************************************************
*                                                                       
*   FUNCTION                                                             
*                                                                       
*       TCPSS_Net_Send                                                   
*                                                                       
*   DESCRIPTION                                                          
*                                                                       
*       This function examines the ports outwindow and sends the data 
*       that is queued in the windows packet_list.  All of the data may 
*       not be sent immediately.  The decision to send data immediately 
*       or to hold off is based on the Nagle Algorithm 
*       (RFC 1122, page 98).            
*                                                                       
*   INPUTS                                                               
*
*       *prt             Pointer to a port.                              
*       *buf_ptr                                                         
*                                                                       
*   OUTPUTS                                                              
*                                                                       
*       The number of bytes that were sent.                              
*                                                                       
*************************************************************************/
static STATUS TCPSS_Net_Send(TCP_PORT *prt, NET_BUFFER *buf_ptr)
{
    STATUS          nsent = 0, status;
    TCP_WINDOW      *wind;

    wind = &prt->out;

    /* Check to see if the PUSH flag has been set (i.e., the Nagle Algorithm
       has been disabled).  If so send every packet immediately with the
       push flag set. */
    if(wind->push)
    {
        prt->out.tcp_flags |= TPUSH;

        /* Send the packet. */
        if ((status = TCP_Xmit(prt, buf_ptr)) == NU_SUCCESS)
            /* Return the number of data bytes sent. */
            nsent = (STATUS)buf_ptr->mem_total_data_len;
        else
            /* Return the error value. */
            nsent = status;
    }

    /* Should the next packet be sent?  This decision is based on the Nagle
     * Algorithm (RFC 1122, page 98).  Following are the four cases when a
     * packet should be sent:
     * 1)  If a maximum size packet can be sent.
     * 2)  If there is no unacknowledged data and the data is pushed and
     *     all queued data can be sent.  Note that at this point all queued
     *     data can be sent, else it would not be queued.
     * 3)  If there is no unacknowledged data and some specified fraction of
     *     the maximum windowsize can be sent.  In this case we send if at
     *     least half the max windowsize can be sent.
     * 4)  If the data is pushed and an override timeout occurs.
    */
    else if( (buf_ptr->mem_total_data_len >= prt->sendsize) ||
            (wind->nxt == wind->ack) ||
            ((wind->nxt == wind->ack) && (buf_ptr->mem_total_data_len >=
                                         (prt->maxSendWin >> 1))) )
    {

        /* Send the packet. */
        if ((status = TCP_Xmit(prt, buf_ptr)) == NU_SUCCESS)
            /* Return the number of data bytes sent. */
            nsent = (UINT16) buf_ptr->mem_total_data_len;
        else
            /* Return the error value. */
            nsent = status;
    }

    /* Return the number of data bytes that were sent. */
    return(nsent);
}  /* end TCPSS_Net_Send() */

#endif /* INCLUDE_TCP == NU_TRUE */

⌨️ 快捷键说明

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