📄 select.c
字号:
*
* 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 + -