📄 sockets.c
字号:
/* get the pointer */
SCK_Sockets[new_sock]->s_accept_list = NU_NULL;
/* clear the TCP_Ports task id */
SCK_Sockets[new_sock]->s_TXTask = NU_NULL;
/* A connection has been successfully accpted. */
return_status = new_sock;
break;
}
}
/* There are no connections to accept so check to see if the application
wants to block pending a connection. */
else if( !(SCK_Sockets[socketd]->s_flags & SF_BLOCK) )
{
/* Blocking is not desired so indicate that no connection was made. */
return_status = NU_NO_TASK_MATCH;
break;
}
else /* no match in task table */
{
/* Indicate that this task is accepting connections. */
task_entry->Task_ID = NU_Current_Task_Pointer();
/* Let others in while we are waiting for the connection. */
SCK_Suspend_Task(task_entry->Task_ID);
/* Clear the accept flag. */
task_entry->Task_ID = NU_NULL;
}
}
/* allow others to use the TCP resource */
NU_Release_Semaphore(&TCP_Resource);
/* Switch back to user mode. */
NU_USER_MODE();
/* return the new socket descriptor to the server */
return(return_status);
} /* NU_Accept */
#endif /* INCLUDE_TCP == NU_TRUE */
#if (INCLUDE_TCP == NU_TRUE)
/*************************************************************************
*
* FUNCTION
*
* NU_Send
*
* DESCRIPTION
*
* This function is responsible for transmitting data across a
* network during a connection-oriented transfer.
*
* INPUTS
*
* socketd
* *buff
* nbytes
* flags
*
* OUTPUTS
*
* Returns number of bytes sent.
* NU_INVALID_SOCKET
* NU_NOT_CONNECTED
* NU_NO_ROUTE_TO_HOST
* NU_CONNECTION_REFUSED
* NU_MSG_TOO_LONG
*
*************************************************************************/
INT32 NU_Send(INT socketd, CHAR *buff, UINT16 nbytes, INT16 flags)
{
NET_BUFFER_SUSPENSION_ELEMENT *waiting_for_buffer;
INT32 return_status; /* initialized to error status */
struct sock_struct *sockptr;
UINT16 count; /* number of bytes written */
UINT16 bytes_to_go; /* number of bytes yet to transmit */
UINT16 curr_count; /* number of bytes written this call */
INT status = 0;
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();
/* Clean up warnings. This parameter is used for socket compatibility
but we are currently not making any use of it. */
UNUSED_PARAMETER(flags);
/* Don't let anyone else in until we are through. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
/* Get a pointer to the socket */
sockptr = SCK_Sockets[socketd];
/* Check for a NULL socket ptr and a connected socket. */
if ( sockptr && (sockptr->s_state & SS_ISCONNECTED) )
{
/* initialize the byte counters */
count = 0;
bytes_to_go = nbytes;
while ((bytes_to_go > 0))
{
/* call tcp/ip library netwrite routine */
curr_count = (UINT16) TCPSS_Net_Write( sockptr, (UINT8 *)(buff + count), bytes_to_go,
&status);
/* If 0 was returned, then for some reason we failed to send the
data. Check to see if we failed because we have already
filled up the window of the remote host. If so just
continue. We will suspend below, and be awakened when the
remote host acks some of the data we have already sent. At
that point some more data can be transmitted. If we failed
for any other reason check to see if some data has already
been sent. If so return the number of bytes that have
already been sent. If no data has been sent (i.e., count ==
0) then set count equal to the error code so the application
layer will see the error.
*/
if (curr_count == 0)
{
if ((status != NU_WINDOW_FULL) && (status != NU_NO_BUFFERS))
{
if (count == 0)
count = curr_count;
break;
}
}
/* update the bytes counter */
bytes_to_go -= curr_count;
/* update the total bytes sent */
count += curr_count;
/* If the status is NO BUFFERS then we will suspend until
more buffers become available. */
if (status == NU_NO_BUFFERS)
{
/* Allocate memory for a suspension list element. */
status = NU_Allocate_Memory (&System_Memory,
(VOID **)&waiting_for_buffer,
sizeof (NET_BUFFER_SUSPENSION_ELEMENT),
NU_NO_SUSPEND);
/* Make sure we got the memory. */
if (status == NU_SUCCESS)
{
/* Add this task to the element. */
waiting_for_buffer->waiting_task = NU_Current_Task_Pointer();
/* Mark this task as suspended on TX. */
sockptr->s_TXTask = waiting_for_buffer->waiting_task;
/* Put this element on the buffer suspension list */
DLL_Enqueue (&MEM_Buffer_Suspension_List, waiting_for_buffer);
/* Suspend this task. */
SCK_Suspend_Task (waiting_for_buffer->waiting_task);
/* Clear it. */
sockptr->s_TXTask = NU_NULL;
/* Make sure this entry is removed from the list. */
DLL_Remove (&MEM_Buffer_Suspension_List, waiting_for_buffer);
/* Give the memory back. */
NU_Deallocate_Memory (waiting_for_buffer);
}
else
NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
}
/* If the number of bytes to go indicates more to be sent
then suspend until there are buffers available. */
else if (bytes_to_go > 0)
{
/* Increment the number of tasks that are waiting for
buffers before they can send. */
tasks_waiting_to_send++;
sockptr->s_TXTask = NU_Current_Task_Pointer();
SCK_Suspend_Task(sockptr->s_TXTask);
sockptr->s_TXTask = NU_NULL;
} /* still bytes to be sent */
} /* while still bytes to transmit. */
/* verify success of transfer, if a code of less than */
if (status == NU_SUCCESS)
/* return number of bytes transferred */
return_status = count;
/* If the port is not -1 and the value of the icmp_error field of
* the port is less than zero (an error code) return the error code */
else if ( (sockptr->s_port_index != NU_IGNORE_VALUE)
&& (TCP_Ports[sockptr->s_port_index]->icmp_error < 0) )
return_status = TCP_Ports[sockptr->s_port_index]->icmp_error;
else
return_status = status;
}
/* If the port is not -1 and the value of the icmp_error field of
* the port is less than zero (an error code) return the error code */
else if ( (sockptr->s_port_index != NU_IGNORE_VALUE)
&& (TCP_Ports[sockptr->s_port_index]->icmp_error < 0) )
return_status = TCP_Ports[sockptr->s_port_index]->icmp_error;
/* Either the socket pointer was NULL or the connection has closed. */
else
return_status = NU_NOT_CONNECTED;
/* allow others to use the TCP resource */
NU_Release_Semaphore(&TCP_Resource);
/* Switch back to user mode. */
NU_USER_MODE();
/* return to caller */
return(return_status);
} /* end of NU_Send */
#endif /* INCLUDE_TCP == NU_TRUE */
#if (INCLUDE_UDP == NU_TRUE)
/*************************************************************************
*
* FUNCTION
*
* NU_Send_To
*
* DESCRIPTION
*
* This function is responsible for transmitting data across
* a network during a connectionless transfer.
*
* INPUTS
*
* socketd
* *buff
* nbytes
* flags
* *to
* addrlen
*
* OUTPUTS
*
* Number of bytes sent.
* NU_NO_PORT_NUMBER
* NU_INVALID_SOCKET
* NU_INVALID_ADDRESS
* NU_NO_DATA_TRANSFER
*
*************************************************************************/
INT32 NU_Send_To(INT socketd, CHAR *buff, UINT16 nbytes, INT16 flags,
struct addr_struct *to, INT16 addrlen)
{
INT32 count; /* number of bytes written */
struct uport *uprt;
struct sock_struct *sockptr; /* pointer to current socket */
INT16 port_num; /* local machine's port number */
INT32 return_status = NU_NO_PORT_NUMBER; /* initialized to error status */
UINT16 dest_port;
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();
/* Clean up warnings. This parameter is used for socket compatibility
* but we are currently not making any use of it. */
UNUSED_PARAMETER(flags);
UNUSED_PARAMETER(addrlen);
/* Grab the stack semaphore. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
/* Pick up a pointer to the socket list entry. */
sockptr = SCK_Sockets[socketd];
if (!(sockptr->s_state & SS_DEVICEDOWN))
{
/* get the server's port number */
dest_port = to->port;
/* verify that a port number exists */
if (dest_port)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -