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

📄 select.c

📁 基于nucleus操作系统的GPRS无线数据传输终端全套源文件。包括支持ARM7的BSP,操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
*                                                                         
*   OUTPUTS                                                               
*                                                                         
*       None
*                                                                         
*************************************************************************/
VOID NU_FD_Reset(INT socket, FD_SET *fd)
{
    fd->words[socket/FD_BITS] &= ~(NU_TRUE<<(socket%FD_BITS));
}

/*************************************************************************
*
*   FUNCTION                                                              
*                                                                         
*       SEL_Check_Recv                                                    
*                                                                         
*   DESCRIPTION                                                           
*                                                                         
*       Checks the sockets specified in a bitmap to see if any are data 
*       ready.  If any are found to be data ready the bitmap is modified 
*       so that only the bits for the data ready sockets are set.  Else 
*       the bitmap is untouched.
*                                                                         
*   INPUTS                                                                
*                                                                         
*       max_sockets          The max number of sockets that can be open.  
*       readfs               Bitmap of sockets to check for data.         
*                                                                         
*   OUTPUTS                                                               
*                                                                         
*       NU_SUCCESS if at least one socket is data ready, NU_NO_DATA 
*       otherwise
*                                                                         
*************************************************************************/
STATUS SEL_Check_Recv(INT max_sockets, FD_SET *readfs)
{
    INT    i;                   /* Loop counter */
    STATUS return_status = NU_NO_DATA;  /* Assume failure, if a data ready
                                           socket is found status will be updated
                                           to success. */
    FD_SET  tmpfs;
    struct sock_struct *sockptr; /* pointer to current socket */

    /* Preserve the current state of readfs.  It may be needed below. */
    NU_FD_Init(&tmpfs);
    memcpy(&tmpfs, readfs, sizeof(FD_SET));

    for (i = 0; i < max_sockets; i++)
    {
        /* Is the bit for socket i set. */
        if (NU_FD_Check(i, readfs)==NU_NULL)
            continue;

        /*  Pick up a pointer to the socket list. */
        if ((sockptr = SCK_Sockets[i]) == NU_NULL)
        {
            /* There is no socket for this bit in the select bit map. This 
               indicates a user error. Reset this bit so that this error
               will not occur next time. Set the status to NU_INVALID_SOCKET
               if we have not already had success on another socket. */
            NU_FD_Reset (i, readfs);

            if (return_status != NU_SUCCESS)
                return_status = NU_INVALID_SOCKET;

            continue;
        }

#if (INCLUDE_TCP == NU_TRUE)

        if (sockptr->s_protocol == NU_PROTO_TCP)
        {
            /* Check to see if this is a server socket or communication
               socket. */
            if ( !(sockptr->s_flags & SF_LISTENER))
            {
                /* Check to see if there is received data. At this point it does 
                   not matter if the connection has been closed. If there is 
                   received data then it should be passed to the application 
                   layer. 
                */

                /* First check to see if the connection has been closed by 
                   the foreign side. (spr471) */
                if (sockptr->s_state & SS_ISDISCONNECTING)
                {
                    /* Set the status to success so that we will return
                       to the calling task. */
                    return_status = NU_SUCCESS;

                    /* Start the loop again so that the next socket can 
                       be checked. */
                    continue;
                }
                
                if (sockptr->s_recvbytes == 0)
                {
                    NU_FD_Reset(i, readfs);
                    continue;
                }

                /* verify there are data in and no other task using this socket
                   and make sure no other process accessing it now ! */
                if (sockptr->s_RXTask == NU_NULL && (sockptr->s_recvbytes >0))
                    return_status = NU_SUCCESS;
                else
                    NU_FD_Reset(i, readfs);
            }
            else
            {
                /* search the task table for this port number/task id */
                if ( SCK_SearchTaskList(sockptr->s_accept_list, SEST, -1) >= 0)
                    return_status = NU_SUCCESS;
                else
                    NU_FD_Reset(i, readfs);
            }

        } /* end this is a TCP socket. */

#endif /* INCLUDE_TCP == NU_TRUE */
            
#if (INCLUDE_UDP == NU_TRUE)

        else if (sockptr->s_protocol == NU_PROTO_UDP)
        {
            if(!sockptr->s_local_addr.port_num)
            {
                NU_FD_Reset(i, readfs);
                continue;
            }

            if(NU_Get_UDP_Pnum(sockptr) == NU_IGNORE_VALUE)
            {
                if (UDP_Make_Port(sockptr->s_local_addr.port_num, i) < 0)
                {
                    NU_FD_Reset(i, readfs);
                    continue;
                }
            }

            if( (sockptr->s_RXTask == NU_NULL) && (sockptr->s_recvpackets))
                return_status = NU_SUCCESS;
            else
                NU_FD_Reset(i, readfs);

        }  /* end this is a UDP socket */

#endif /* INCLUDE_UDP == NU_TRUE */

#if (INCLUDE_IP_RAW == NU_TRUE)
        else if (sockptr->s_local_addr.port_num == 0) /* must be zero for Raw IP */
        {
            if(IPRaw_Get_PCB(i, sockptr) == NU_IGNORE_VALUE)
            {
                if (IPRaw_Make_Port(i) < 0)
                {
                    NU_FD_Reset(i, readfs);
                    continue;
                }
            }

            if( (sockptr->s_RXTask == NU_NULL) && (sockptr->s_recvpackets > 0))
                return_status = NU_SUCCESS;
            else
                NU_FD_Reset(i, readfs);

        }  /* end this is a RAW IP socket */

#endif /* INCLUDE_IP_RAW == NU_TRUE */

    } /* for (i=0; i<max_sockets; i++) */

    if(return_status != NU_SUCCESS)
        memcpy(readfs, &tmpfs, sizeof(FD_SET));

    return(return_status);

} /* end SEL_Check_Recv */

/*************************************************************************
*
*   FUNCTION                                                              
*                                                                         
*       SEL_Setup_Recv_Ports                                              
*                                                                         
*   DESCRIPTION                                                           
*                                                                         
*       This function marks the specified ports so that if data 
*       arrives on any of them the current task will be resumed.          
*                                                                         
*   INPUTS                                                                
*                                                                         
*       max_sockets                                                       
*       *readfs                                                           
*       *Task_ID                                                          
*                                                                         
*   OUTPUTS                                                               
*                                                                         
*       NU_SUCCESS or -1                                                  
*                                                                         
*************************************************************************/
STATUS SEL_Setup_Recv_Ports(INT max_sockets, FD_SET *readfs, NU_TASK *Task_ID)
{
    STATUS                      return_status = -1;
    INT                         i;
    INT16                       pnum;       /* local machine's port number */
    struct sock_struct          *sockptr;   /* pointer to current socket */
    struct TASK_TABLE_STRUCT    *task_entry;

#if (INCLUDE_IP_RAW == NU_TRUE)
    struct iport                *iprt;      /* IP Raw PCB structure */
#endif

#if (INCLUDE_UDP == NU_FALSE)
    UNUSED_PARAMETER(pnum);
#endif

    /* we need to assign the current thread to each (!!!) port
        we are checking, then NU_EventsDispatcher() could wake up
        this task when any of these ports gets data */
    for (i = 0; i < max_sockets; i++)
    {
        if (NU_FD_Check(i, readfs)==NU_NULL)
            continue;

        if ((sockptr = SCK_Sockets[i]) == NU_NULL)
            continue;

#if (INCLUDE_TCP == NU_TRUE)
        
        if (sockptr->s_protocol == NU_PROTO_TCP)
        {
            /* Check to see if this is a server socket or communication
               socket. */
            if ( !(sockptr->s_flags & SF_LISTENER) )
            {
                /* Check to see if data can still be received on the port. */
                if (( sockptr->s_state == SS_ISCONNECTED ) || (Task_ID == NULL))
                {
                    sockptr->s_RXTask = Task_ID;
                    return_status = NU_SUCCESS;
                }
            }
            else
            {
 
                /* If an entry was found, set it up. */
                if ((task_entry = sockptr->s_accept_list) != NU_NULL)
                {
                    /* Setup the Task ID field so that this task can be resumed. */
                    task_entry->Task_ID = Task_ID;

                    return_status = NU_SUCCESS;
                }
            }
        }
#endif        

#if INCLUDE_UDP
        else if(sockptr->s_protocol == NU_PROTO_UDP)
        {
            if ((pnum = NU_Get_UDP_Pnum(sockptr)) == NU_IGNORE_VALUE)
                continue;

            if (UDP_Ports[pnum] == NU_NULL)
                continue;

            sockptr->s_RXTask = Task_ID;
            return_status = NU_SUCCESS;
        }
#endif

#if (INCLUDE_IP_RAW == NU_TRUE)

        /* my_port should be zero when dealing with raw IP sockets */
        else if (sockptr->s_local_addr.port_num == 0)    
        {
            /*  Check if there is already a PCB structure set up
                for this IP communication.  */
            if ((pnum = IPRaw_Get_PCB(i, sockptr)) == NU_IGNORE_VALUE)
                continue;

            if ((iprt = IPR_Ports[pnum]) == NU_NULL)
                continue;

            /* Initialize the PCB that we are expecting to receive. */
            iprt->ip_lport = sockptr->s_local_addr.port_num;
            iprt->ip_socketd = i;
            iprt->ip_protocol = sockptr->s_protocol;

            iprt->ip_laddr = IP_ADDR (sockptr->s_local_addr.ip_num.is_ip_addrs);
            iprt->ip_faddr = IP_ADDR_ANY;
            
            sockptr->s_RXTask = Task_ID;
            return_status = NU_SUCCESS;
        }
#endif

    } /* end for i to max_sockets */

    return (return_status);

} /* SEL_Setup_Recv_Ports */

⌨️ 快捷键说明

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