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

📄 tcpss.c

📁 基于nucleus操作系统的GPRS无线数据传输终端全套源文件。包括支持ARM7的BSP,操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
*************************************************************************/
STATUS TCPSS_Net_Xopen(UINT8 *machine, UINT16 service, INT socketd)
{
    TCP_PORT        *prt;
    INT             pnum;
    SCK_SOCKADDR_IP *dest;
    DV_DEVICE_ENTRY *device;

    /*
    *  check the IP number and don't allow broadcast addresses
    */
    if (machine[3] == 255)
    {
        NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
        return (-4);
    }

   /*
    *  get the hardware address for that host, or use the one for the
    *  gateway all handled by 'netdlayer' by ARPs.
    */

    if ((pnum = TCP_Make_Port()) < 0)         /* set up port structure and packets */
        return (NU_NO_PORT_NUMBER);

    prt = TCP_Ports[pnum];           /* create a new port */

    prt->p_socketd = socketd;

    /* Determine which device will be used for communication.  This will allow
       us to decide which IP address to use on the local side. */
    /* The TCP port structure includes a route field that used to cache a route 
       to the foreign host.  Fill it in here. This will save us the trouble of 
       looking up the route at the IP layer for every packet sent.
    */
    /* Point to the destination. */
    dest = (SCK_SOCKADDR_IP *) &prt->tp_route.rt_ip_dest;
    dest->sck_family = SK_FAM_IP;
    dest->sck_len = sizeof (*dest);
    dest->sck_addr = IP_ADDR(machine);

    IP_Find_Route(&prt->tp_route);

    if (prt->tp_route.rt_route == NU_NULL)
    {
        prt->state = SCLOSED;

        /* Increment the number of packets that could not be delivered. */
        SNMP_ipOutNoRoutes_Inc;
        return -1;
    }

    device = prt->tp_route.rt_route->rt_device;

    prt->tcp_laddr = device->dev_addr.dev_ip_addr;

    /* make a copy of the ip number that we are trying for */
    prt->tcp_faddr = IP_ADDR(machine);

    /* Store off the port index for the associated port. */
    SCK_Sockets[prt->p_socketd]->s_port_index = pnum;


    /*
     *  Make the connection, if you can, we will get an event notification
     *  later if it connects.  Timeouts must be done at a higher layer.
     */

    /* If the connection was made return the index into the TCP_Ports of 
       the new port.  Else return failure. */
    if ( TCPSS_Do_Connect (pnum, service) == NU_SUCCESS)
        return (pnum);
    else
    {
        TCP_Cleanup(prt);
        return -1;
    }

} /* end TCPSS_Net_Xopen() */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCPSS_Do_Connect                                                 
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       This routine sends the actual packet out to try and establish a   
*       connection.                                                       
*                                                                       
*   INPUTS                                                                
*                                                                       
*       pnum                                                             
*       service                                                          
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       Nucleus Status Code
*                                                                       
*************************************************************************/
static STATUS TCPSS_Do_Connect(INT pnum, UINT16 service)
{
    TCP_PORT        *prt;
    STATUS          status;

    /* Get a pointer to the port. */
    prt = TCP_Ports[pnum];

    prt->out.port = service;                   /* service same as port num */
    prt->out.tcp_flags = TSYN;                 /* want to start up sequence */

    prt->state = SSYNS;

    status = TCPSS_Send_SYN_FIN(prt, 4);

    if (status == NU_SUCCESS)
    {
        /* Increment the number of TCP segments transmitted. */
        SNMP_tcpOutSegs_Inc;

        /* Increment the number active connections attempted. */
        SNMP_tcpActiveOpens_Inc;
    }
    else
        prt->state = SCLOSED;                 /* syn sent */

    return(status);

}   /* end TCPSS_Do_Connect() */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCPSS_Send_SYN_FIN                                               
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       This routine is responsible for sending a packet containing either
*       a SYN or FIN bit.                                                 
*                                                                       
*   INPUTS                                                                
*                                                                       
*       *prt                                                             
*       options                                                          
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       stat                                                             
*       -1                                                               
*                                                                       
*************************************************************************/
STATUS TCPSS_Send_SYN_FIN(TCP_PORT *prt, INT16 options)
{
    TCPLAYER    *tcp_ptr;
    NET_BUFFER  *buf_ptr;
    INT         tcp_hlen;
    STATUS      stat;
    UINT8       HUGE *options_ptr;

    /* One buffer will be large enough for the SYN FIN */
    buf_ptr = MEM_Buffer_Dequeue (&MEM_Buffer_Freelist);

    if(buf_ptr == NU_NULL)
        return -1;

    /* Init the pointers */
    buf_ptr->next           = NU_NULL;
    buf_ptr->next_buffer    = NU_NULL;

    /* Initialize each field in the buffer. */
    /* Point the data pointer at an offset into the buffer large enough to leave
       room for the IP and MAC layer headers. */
    buf_ptr->data_ptr = (buf_ptr->mem_parent_packet + 
            (NET_MAX_TCP_HEADER_SIZE - sizeof (TCPLAYER)));

    /* There are 4 bytes of option data in the SYN packet. */
    buf_ptr->data_len = buf_ptr->mem_total_data_len = (sizeof (TCPLAYER) + options);
    buf_ptr->mem_option_len = options;

    /* Set the TCP data length to one. This is used for ack and seqnum 
       comparison. A SYN or FIN only bumps the seqnum by 1. */
    buf_ptr->mem_tcp_data_len = 1;

    /* Store the sequence number of this packet. */
    buf_ptr->mem_seqnum = prt->out.nxt;

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

    /* Initialize the number of times this packet has been retransmitted. */
    buf_ptr->mem_retransmits = 0;

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

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

    /* Compute the sizeof the TCP header in words */
    tcp_hlen = ((sizeof(TCPLAYER) + options - 1) / 4) + 1;

    /* Update the header information. */
    TCP_Update_Headers(prt, buf_ptr, (UINT16)tcp_hlen);

    /* A SYN or FIN flag counts as one byte of data in the sequence space. */
    prt->out.nxt++;

    options_ptr = (buf_ptr->data_ptr + sizeof (TCPLAYER));
    tcp_ptr     = (TCPLAYER *) buf_ptr->data_ptr;

    /* Should option data be included. */
    if (options)
    {
        /* Add the TCP mac segment size option to this packet. */
        options_ptr[0] = 2;
        options_ptr[1] = 4;
        *(INT16 *)&options_ptr[2] = INTSWAP(MAX_SEGMENT_LEN);
    }

    /* Compute and fill in the checksum. */
    PUT16(tcp_ptr, TCP_CHECK_OFFSET, 
            UTL_Checksum(buf_ptr, prt->tcp_laddr, prt->tcp_faddr, IP_TCP_PROT) );

    /* If there is no timing being performed then time this transmission. */
    if (prt->p_rtt == 0)
    {
        prt->p_rtt = NU_Retrieve_Clock();
        prt->p_rtseq = buf_ptr->mem_seqnum;
    }
    
    /* Send this packet. */
    stat = IP_Send(buf_ptr, &prt->tp_route, prt->tcp_faddr,
                   prt->tcp_laddr, 0, IP_TIME_TO_LIVE, 
                   IP_TCP_PROT, 0, NU_NULL);

    if (stat == NU_SUCCESS)
    {
        /* If the transmit was a success, set a retransmit event for this
           packet.
        */
        UTL_Timerset (TCPRETRANS, (UNSIGNED)prt->pindex, 
                        (UNSIGNED)prt->p_rto, (INT32)prt->out.nxt);

        /* Increment the number of TCP segments transmitted. */
        SNMP_tcpOutSegs_Inc;
    }
    else
    {
        /* The packet was not sent.  Dealocate the buffer.  If the packet was
           transmitted it will be deallocated later by TCP. */
        MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
    }

    return (stat);

}  /* end TCPSS_Send_SYN_FIN() */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCPSS_Net_Close                                                  
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       Start the closing process on port pnum.                             
*                                                                       
*   INPUTS                                                                
*                                                                       
*       pnum            Number of the port to close.                     
*       *sock_ptr                                                        
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       NU_SUCCESS                                                       
*       -1                                                               
*                                                                       
*************************************************************************/
STATUS TCPSS_Net_Close(INT pnum, struct sock_struct *sock_ptr)
{
    TCP_PORT    *prt;
    INT16       return_status = -1;
    NET_BUFFER  *buf_ptr;

    if ((pnum < 0) || (pnum > TCP_MAX_PORTS))      /* is a valid port? */
        return (-1);

    if ((prt = TCP_Ports[pnum]) != NU_NULL)
    {
        /* something there */

        switch (prt->state)
        {
            case SLISTEN:               /* we don't care anymore */
            case SSYNS:

                /* Increment the number of connection failures. */
                SNMP_tcpAttemptFails_Inc;

                /* Close the connection. */
                prt->state = SCLOSED;
                TCP_Cleanup(prt);

                break;

            case SEST:                  /* must initiate close */


                /* Send FIN only if all data has been transmitted. */
                if (prt->out.nextPacket == NU_NULL)
                {
                    if(prt->portFlags & ACK_TIMER_SET)
                    {
                        /*  Delete the ACK timeout timer.  */
                        UTL_Timerunset(TCPACK, (UNSIGNED)prt->pindex, (INT32)1);

                        /* Clear the ACK timer flag in the port. */
                        prt->portFlags &= (~ACK_TIMER_SET);
                    }

                    prt->out.tcp_flags = TACK | TFIN;
                    TCPSS_Send_SYN_FIN(prt, 0);
                    prt->state = SFW1;           /* wait for ACK of FIN */

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

                    return_status = NU_SUCCESS;
                }
                else
                {
                    if (prt->xmitFlag == NU_SET)
                    {

                        UTL_Timerunset (CONTX, (UNSIGNED)prt->pindex, (INT32)1);

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

⌨️ 快捷键说明

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