sockets.c
来自「mcf5307实验源代码」· C语言 代码 · 共 1,494 行 · 第 1/5 页
C
1,494 行
this server/task_id */
uint16 counter; /* used for initialization of
Task_Entry */
/* Validate the socket number. */
if ((socketd < 0) || (socketd >= NSOCKETS) ||
(socket_list[socketd] == NU_NULL))
return(NU_INVALID_SOCKET);
/* Don't let any other users in until we are done. */
#ifdef PLUS
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else
NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif
/* Allocate memory required for a Task_Entry structure, connection status
array, and portlist 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.
*/
#ifdef PLUS
status = NU_Allocate_Memory(&System_Memory, (VOID *) &return_ptr,
(UNSIGNED)(sizeof(struct TASK_TABLE_STRUCT) +
(backlog * sizeof(unsigned short)) +
(backlog * sizeof(int16))),
(UNSIGNED)NU_NO_SUSPEND);
#else
status = NU_Alloc_Memory(sizeof(struct TASK_TABLE_STRUCT) +
(backlog * sizeof(unsigned short)) +
(backlog * sizeof(int16)),
(unsigned int **)&return_ptr,
NU_NO_TIMEOUT);
#endif
/* verify a successful allocation */
if (status == NU_SUCCESS)
{
return_ptr = normalize_ptr(return_ptr);
/* Break up the block of memory allocated into three seperate chunks. */
Task_Entry = (struct TASK_TABLE_STRUCT *)return_ptr;
Task_Entry->stat_entry = (short *)(return_ptr +
sizeof(struct TASK_TABLE_STRUCT));
Task_Entry->port_entry = (int16 *)(return_ptr +
sizeof(struct TASK_TABLE_STRUCT) +
(backlog * sizeof(unsigned short)));
/* retrieve the local port number from the socket descriptor
for the task table */
Task_Entry->local_port_num =
(uint16)socket_list[socketd]->local_addr.port_num;
/* record the socket number in the socketd field of Task_Entry */
Task_Entry->socketd = socketd;
/* retrieve the current task id for the task table */
#ifdef PLUS
task_id = NU_Current_Task_Pointer();
/* verify that a task is running */
if (task_id != NU_NULL)
#else
task_id = NU_Current_Task_ID();
/* verify that a task is running */
if (task_id != NU_SYSTEM)
#endif
Task_Entry->Task_ID = task_id;
else
/* return the error to the caller */
return_status = NU_NOT_A_TASK;
/* initialize the port_entries and stat_entries */
for (counter = 0; counter < backlog; counter++)
{
Task_Entry->port_entry[counter] = NU_IGNORE_VALUE;
Task_Entry->stat_entry[counter] = NU_IGNORE_VALUE;
}
/* 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 accept flag. */
Task_Entry->acceptFlag = 0;
/* initialize the next pointer to NU_NULL */
Task_Entry->next = NU_NULL;
/* call a routine to attach this structure to the
linked list of structures */
NU_TaskTableAdd(Task_Entry);
/* Mark this socket as a listener. */
socket_list[socketd]->listener = NU_TRUE;
}
else
{
NU_Tcp_Log_Error(TCP_SESS_MEM, TCP_RECOVERABLE,
__FILE__, __LINE__);
/* Tell them no more memory. */
return_status = NU_NO_SOCK_MEMORY;
}
/* allow others to use the TCP resource */
#ifdef PLUS
NU_Release_Semaphore(&TCP_Resource);
#else
NU_Release_Resource(TCP_Resource);
#endif
/* Turn on blocking for this socket so that blocking is the default for the
NU_Accept call */
NU_fcntl(socketd, NU_SETFLAG, NU_BLOCK, 0);
/* return to the caller */
return(return_status);
} /* end of NU_Listen */
/*************************************************************************/
/* */
/* 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. */
/* */
/* CALLED FROM */
/* */
/* User Applications */
/* */
/* CALLS */
/* */
/* NU_Obtain_Semaphore */
/* NU_Release_Semaphore */
/* NU_Allocate_Memory */
/* NU_Current_Task_Pointer */
/* suspend_task */
/* NU_SearchTaskList */
/* */
/* History: */
/* created - 10/22/92, bgh */
/* */
/*************************************************************************/
int16 NU_Accept(int16 socketd, struct addr_struct *peer, int16 *addrlen)
{
uint server_port_num;
#ifdef PLUS
NU_TASK *Task_ID; /* current task pointer */
#else
sint Task_ID; /* current task id */
#endif
struct port *pprt, *prt; /* port pointer */
struct TASK_TABLE_STRUCT *Task_Entry = NU_NULL; /* structure of connections
for this server/task_id */
int16 pnum; /* portlist index */
int16 new_sock; /* index of new socket in socket_list */
int16 return_status = NU_INVALID_SOCKET;
/* Clean up warnings. This parameter is used for socket compatibility
but we are currently not making any use of it. */
server_port_num = (uint)*addrlen;
/* Validate the socket number. */
if ((socketd < 0) || (socketd >= NSOCKETS) ||
(socket_list[socketd] == NU_NULL) ||
(socket_list[socketd]->listener == NU_FALSE))
{
return(return_status);
}
/* init the new_sock value for the possible return if not set */
new_sock = NU_NO_SOCKET_SPACE;
/* 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. */
/* Don't let anyone else in until we are through. */
#ifdef PLUS
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else
NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif
/* get the current task id for the next 2 service calls */
#ifdef PLUS
Task_ID = NU_Current_Task_Pointer();
#else
Task_ID = NU_Current_Task_ID();
#endif
/* retrieve the local port number from the socket descriptor
for comparison to the task table */
server_port_num = (uint16)socket_list[socketd]->local_addr.port_num;
/* Check for an established connection. If there isn't one, then
suspend the calling task until the connection is made. */
do
{
/* search the task table for this port number/task id */
Task_Entry = NU_SearchTaskList(Task_Entry, Task_ID,
server_port_num, SEST, -1);
/* continue only if a match was found in the task table */
if (Task_Entry != NU_NULL)
{
/* get a pointer into the port list table at the oldest
table entry */
pprt =
portlist[Task_Entry->port_entry[Task_Entry->current_idx]];
/* release the resource because NU_Socket will be needing it */
#ifdef PLUS
NU_Release_Semaphore(&TCP_Resource);
#else
NU_Release_Resource(TCP_Resource);
#endif
/* let NU_Socket allocate a new socket structure */
new_sock = NU_Socket(NU_FAMILY_IP, NU_TYPE_STREAM, 0);
/* Make sure we got one. */
if (new_sock >= 0)
{
/* get the resource back now that NU_Socket is finished */
#ifdef PLUS
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else
NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif
/* copy known information from the original socket
descriptor */
memcpy (socket_list[new_sock], socket_list[socketd],
sizeof(struct sock_struct));
/* fill the client portion of the new socket descriptor */
socket_list[new_sock]->foreign_addr.port_num =
(int16)intswap (pprt->tcpout.t.dest);
memcpy((uchar *)
&(socket_list[new_sock]->foreign_addr.ip_num),
pprt->tcps.dest,4);
/* store the new socket descriptor for return */
return_status = new_sock;
peer->family = NU_FAMILY_IP;
peer->port = (uint16)socket_list[new_sock]->foreign_addr.port_num;
memcpy (&peer->id, pprt->tcpout.i.ipdest, 4);
/* call a routine to delete this entry from the task
table and increment the current task entry pointer */
NU_UpdateTaskTable(Task_Entry);
/* Get the port number so that we can clear the transmit
Task ID */
if ((pnum = NU_GetPnum(socket_list[new_sock])) >= 0)
{
/* get the pointer */
prt = portlist[pnum];
/* Clear out the task entry information. */
prt->task_entry = NU_NULL;
/* clear the portlist task id */
#ifdef PLUS
prt->TXTask = NU_NULL;
#else
prt->TXTask = -1;
#endif
}
else
return_status = NU_NO_PORT_NUMBER;
}
else
{
/* return the error status returned from the socket call */
return_status = new_sock;
}
}
/* There are no connections to accept so check to see if the application
wants to block pending a connection. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?