📄 sockets.c
字号:
/* Don't let any other users in until we are done. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
if((myaddr->port != 0) &&
(UTL_Is_Unique_Port_Number(SCK_Sockets[socketd]->s_protocol, myaddr->port) != NU_TRUE))
{
/* Allow others to use the TCP resource */
NU_Release_Semaphore(&TCP_Resource);
/* Switch back to user mode. */
NU_USER_MODE();
return NU_INVALID_PORT;
}
/* Validate the IP address. Before we bind this address to a socket
we must first make sure that there is a device in the system
that has this addresss or that this address is IP_ADDR_ANY. (spr438)
*/
if (!DEV_Get_Dev_By_Addr (myaddr->id.is_ip_addrs) &&
(*(UINT32 *)myaddr->id.is_ip_addrs != IP_ADDR_ANY))
{
/* Allow others to use the TCP resource */
NU_Release_Semaphore(&TCP_Resource);
/* Switch back to user mode. */
NU_USER_MODE();
return (NU_INVALID_ADDRESS);
}
/* Fill the local portion of the socket descriptor */
memcpy (&(SCK_Sockets[socketd]->s_local_addr.ip_num), &(myaddr->id),
IP_ADDR_LEN);
SCK_Sockets[socketd]->s_local_addr.port_num = myaddr->port;
/* Allow others to use the TCP resource */
NU_Release_Semaphore(&TCP_Resource);
/* Switch back to user mode. */
NU_USER_MODE();
/* Return the updated socket descriptor to the caller */
return(socketd);
} /* end of NU_Bind */
#if (INCLUDE_TCP == NU_TRUE)
/*************************************************************************
*
* FUNCTION
*
* NU_Listen
*
* DESCRIPTION
*
* This function is responsible for indicating that the server is
* willing to accept connection requests from clients.
*
* INPUTS
*
* socketd
* backlog
*
* OUTPUTS
*
* NU_SUCCESS
* NU_INVALID_SOCKET
* NU_NO_SOCK_MEMORY
*
*************************************************************************/
STATUS NU_Listen(INT socketd, UINT16 backlog)
{
INT16 return_status = NU_SUCCESS; /* initialize to SUCCESS */
STATUS status;
struct TASK_TABLE_STRUCT *task_entry; /* structure of connections for
this server/task_id */
UINT16 counter; /* used for initialization of
Task_Entry */
NU_SUPERV_USER_VARIABLES
/* Validate the socket number. */
if ((socketd < 0) || (socketd >= NSOCKETS) ||
(SCK_Sockets[socketd] == NU_NULL))
return(NU_INVALID_SOCKET);
/* Switch to supervisor mode. */
NU_SUPERVISOR_MODE();
/* Don't let any other users in until we are done. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
/* Allocate memory required for a Task_Entry structure, connection status
array, and TCP_Ports entry array all at once. This is done for efficiency
(1 service call as opposed to 3). Also, each of the 3 indepedent
allocations was less than the default min allocation size (50 bytes) of
PLUS, so memory was being wasted.
*/
status = NU_Allocate_Memory(&System_Memory, (VOID **) &task_entry,
(UNSIGNED)(sizeof(struct TASK_TABLE_STRUCT) +
(backlog * sizeof(task_entry->stat_entry)) +
(backlog * sizeof(task_entry->socket_index))),
(UNSIGNED)NU_NO_SUSPEND);
/* verify a successful allocation */
if (status == NU_SUCCESS)
{
task_entry = (struct TASK_TABLE_STRUCT *)TLS_Normalize_Ptr(task_entry);
/* Break up the block of memory allocated into three seperate chunks.
Step past the chunk used for the main structure. */
task_entry->stat_entry = (INT *)(task_entry + 1);
/* Point past the chunck of memory used for the list of stat_entry's. */
task_entry->socket_index = (INT *)(task_entry->stat_entry + backlog);
/* retrieve the local port number from the socket descriptor
for the task table */
task_entry->local_port_num = SCK_Sockets[socketd]->s_local_addr.port_num;
/* record the socket number in the socketd field of task_entry */
task_entry->socketd = socketd;
/* Clear the task_id field. */
task_entry->Task_ID = NU_NULL;
/* initialize the port_entries and stat_entries */
for (counter = 0; counter < backlog; counter++)
{
SCK_Clear_Accept_Entry(task_entry, (INT)counter);
}
/* initialize the current connection pointer to the first
space in the table */
task_entry->current_idx = 0;
/* store the number of backlog queues possible */
task_entry->total_entries = backlog;
/* initialize the next pointer to NU_NULL */
task_entry->next = NU_NULL;
/* Associate the socket with its accept list. */
SCK_Sockets[socketd]->s_accept_list = task_entry;
/* Mark this socket as a listener. */
SCK_Sockets[socketd]->s_flags |= SF_LISTENER;
}
else
{
NERRS_Log_Error(NERR_RECOVERABLE, __FILE__, __LINE__);
/* Tell them no more memory. */
return_status = NU_NO_SOCK_MEMORY;
}
/* allow others to use the TCP resource */
NU_Release_Semaphore(&TCP_Resource);
/* Turn on blocking for this socket so that blocking is the default for the
NU_Accept call */
NU_Fcntl(socketd, NU_SETFLAG, NU_BLOCK);
/* Switch back to user mode. */
NU_USER_MODE();
/* return to the caller */
return(return_status);
} /* end of NU_Listen */
#endif /* INCLUDE_TCP == NU_TRUE */
#if (INCLUDE_TCP == NU_TRUE)
/*************************************************************************
*
* FUNCTION
*
* NU_Accept
*
* DESCRIPTION
*
* This function is responsible for establishing a new socket
* descriptor containing info on both the server and a client
* with whom a connection has been successfully established.
*
* INPUTS
*
* socketd
* *peer
* *addrlen
*
* OUTPUTS
*
* Returns the socket descriptor.
* NU_INVALID_SOCKET
* NU_INVALID_PARM
* NU_NO_PORT_NUMBER
* NU_NO_TASK_MATCH
*
*************************************************************************/
STATUS NU_Accept(INT socketd, struct addr_struct *peer, INT16 *addrlen)
{
TCP_PORT *pprt; /* port pointer */
struct TASK_TABLE_STRUCT *task_entry; /* structure of connections
for this server/task_id */
INT new_sock; /* index of new socket in SCK_Sockets */
INT return_status = NU_INVALID_SOCKET;
INT index;
NU_SUPERV_USER_VARIABLES
/* Validate the socket number. */
if ((socketd < 0) || (socketd >= NSOCKETS) ||
(SCK_Sockets[socketd] == NU_NULL) ||
!(SCK_Sockets[socketd]->s_flags & SF_LISTENER))
{
return(return_status);
}
/* If this is not a listening socket return an error. */
if ( !(SCK_Sockets[socketd]->s_flags & SF_LISTENER))
return(NU_INVALID_PARM);
task_entry = SCK_Sockets[socketd]->s_accept_list;
if ( (task_entry == NU_NULL) ||
(task_entry->Task_ID != NU_NULL))
return(NU_INVALID_PARM);
/* Validate the peer pointer. */
if (peer == NU_NULL)
return(NU_INVALID_PARM);
/* Prior to the NU_Accept() service call, an application must call
* NU_Listen(). NU_Listen() sets up a table to accept connection
* requests. This table must be ready before NU_Accept() begins
* to wait for connection attempts. */
/* Switch to supervisor mode. */
NU_SUPERVISOR_MODE();
/* Handle compiler warnings. */
UNUSED_PARAMETER(addrlen);
/* Don't let anyone else in until we are through. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
/* Check for an established connection. If there isn't one, then
suspend the calling task until the connection is made. */
for( ; ; )
{
/* search the task table for this port number/task id */
index = SCK_SearchTaskList(task_entry, SEST, -1);
/* continue only if a match was found in the task table */
if (index >= 0)
{
/* Grab the index of the socket that was created when the
connection was establisehd. */
new_sock = task_entry->socket_index[index];
/* Clear the entry that was used to accept this connection
so thjat it can be reused. */
SCK_Clear_Accept_Entry(task_entry, index);
/* Make sure we got one. */
if (new_sock >= 0)
{
/* Get a pointer to the associated port. */
pprt = TCP_Ports[SCK_Sockets[new_sock]->s_port_index];
/* copy known information from the original socket
descriptor */
memcpy ( &SCK_Sockets[new_sock]->s_local_addr,
&SCK_Sockets[socketd]->s_local_addr,
sizeof(struct sockaddr_struct) );
memcpy ( &SCK_Sockets[new_sock]->s_foreign_addr,
&SCK_Sockets[socketd]->s_foreign_addr,
sizeof(struct sockaddr_struct) );
SCK_Sockets[new_sock]->s_protocol = SCK_Sockets[socketd]->s_protocol;
/* fill the client portion of the new socket descriptor */
/* foreign side */
SCK_Sockets[new_sock]->s_foreign_addr.port_num = pprt->out.port;
*(UINT32 *)SCK_Sockets[new_sock]->s_foreign_addr.ip_num.is_ip_addrs =
LONGSWAP(pprt->tcp_faddr);
/* local side */
*(UINT32 *)SCK_Sockets[new_sock]->s_local_addr.ip_num.is_ip_addrs =
LONGSWAP(pprt->tcp_laddr);
/* fill in the client address structure that is returned */
peer->family = NU_FAMILY_IP;
peer->port = SCK_Sockets[new_sock]->s_foreign_addr.port_num;
*(UINT32 *)peer->id.is_ip_addrs = LONGSWAP(pprt->tcp_faddr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -