📄 ws_tasks.c
字号:
*
* The main server function. It receives the client connection
* and uses a queue to transmit the the connected socket once the
* it has been accepted.
*
* AUTHOR
*
* PicoServer Embedded Web Server
*
* Copywrite (c) 1995 1996 1997 CNiT
*
* Communication and Information Technology
*
* INPUTS
*
* None.
*
* OUTPUTS
*
* None.
*
************************************************************************/
static VOID WS_Receive_Task(UNSIGNED argc, VOID * argv)
{
INT newsock;
INT socketd; /* the socket descriptor */
struct addr_struct servaddr; /* holds the server addre struct */
struct addr_struct client_addr;
STATUS status;
short i;
WS_SERVER *this_server;
/* Remove warnings for unused parameters. */
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
#ifndef WS_FS_IN_MEMORY
/* Register Task as File User */
FAL_Become_File_User();
#endif
/* Intialize global counters. */
this_server = &WS_Master_Server;
/* Print banner. */
#ifdef NU_WEBSERV_DEBUG
printf("Nucleus Web Server\nHTTP 1.1 Server\n\n");
#endif
/* this process hangs in an endless loop
* doing socket accept's. Each accept yields
* a socket descriptor which is put on the Queue
*/
/* open a connection via the socket interface */
if ((socketd = NU_Socket(NU_FAMILY_IP, NU_TYPE_STREAM, 0)) >=0 )
{
/* fill in a structure with the server address */
servaddr.family = NU_FAMILY_IP;
servaddr.port = this_server->ws_port;
/* Set the ip address to IP addr ANY */
for(i = 0;i < 4;i++)
{
servaddr.id.is_ip_addrs[i] = 0;
}
/* make an NU_Bind() call to bind the server's address */
if ((NU_Bind(socketd, &servaddr, 0))>=0)
{
/* be ready to accept connection requests */
status = NU_Listen(socketd, 10);
if (status == NU_SUCCESS)
{
while(1)
{
/* block in NU_Accept until a client connects */
newsock = NU_Accept(socketd, &client_addr, 0);
if (newsock >= 0)
{
#ifdef NU_WEBSERV_DEBUG
printf("accept\n");
#endif
/* turn on the "block during a read" flag */
NU_Fcntl(newsock, NU_SETFLAG, NU_BLOCK);
/* process the new connection */
NU_Send_To_Queue(&WS_Socket_Queue,
&newsock, 1, NU_SUSPEND);
} /* end successful NU_Accept */
} /* end for loop */
} /* end successful NU_Listen */
} /* end successful NU_Bind */
} /* end successful NU_Socket */
}
/************************************************************************
* FUNCTION
*
* WS_Worker_Task
*
* DESCRIPTION
*
* This function does the main processing of the client connections.
* It first checks for a new socket in the global queue. If one is
* found, it adds it to it's local list of sockets. The task then
* locates a socket trying to communicate with the server and
* processes the connection.
*
* AUTHOR
*
* Don Sharer, Accelerated Technology
*
* INPUTS
*
* None.
*
* OUTPUTS
*
* None.
*
************************************************************************/
static VOID WS_Worker_Task(UNSIGNED argc, VOID *argv)
{
INT bytes_recieved;
INT connection_bytes;
INT sockfd = 0;
WS_REQUEST Req;
FD_SET readfs, writefs, exceptfs;
CHAR * line;
CHAR * out_head;
WS_REQ_DATA * reqdat;
WS_SOCK_LIST http_sock;
WS_SOCK_LIST free_sock;
WS_SOCKET_STRUCT *hsock_ent;
WS_SOCKET_STRUCT *hsock_temp;
STATUS status;
UNSIGNED suspend;
UNSIGNED actsize;
CHAR *data_start;
CHAR *s;
INT header_length;
INT content_length;
struct sockaddr_struct addr;
INT16 addr_length = sizeof(struct sockaddr_struct);
/* Remove warnings for unused parameters. */
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
NU_Allocate_Memory(&System_Memory, (VOID*)&reqdat, sizeof(WS_REQ_DATA), NU_SUSPEND);
line = &reqdat->ws_lbuf[0];
out_head = &reqdat->ws_out_head[0];
#ifndef WS_FS_IN_MEMORY
/* Each task must register task as a file user */
FAL_Become_File_User();
#endif
/* Initialize the pointers to the working list and the free list */
http_sock.ws_sock_list_head = NU_NULL;
http_sock.ws_sock_list_tail = NU_NULL;
free_sock.ws_sock_list_head = NU_NULL;
free_sock.ws_sock_list_tail = NU_NULL;
/* Initialize list of nodes to be used to store socket information */
WS_Create_Socket_List(&free_sock);
while(1) /* Endless loop processing HTTP requests */
{
/* Initialize the bitmap */
NU_FD_Init(&readfs);
/* Check for a new socket in the queue, suspend if there are no
* connections to proccess in the list or the queue
*/
if(free_sock.ws_sock_list_head != NU_NULL)
{
if(http_sock.ws_sock_list_head == NU_NULL)
suspend = (UNSIGNED)NU_SUSPEND;
else
suspend = (UNSIGNED)NU_NO_SUSPEND;
status = NU_Receive_From_Queue(&WS_Socket_Queue,(VOID *)&sockfd,
1, &actsize, suspend);
if(status == NU_SUCCESS)
WS_Add_Socket_Entry(&http_sock, &free_sock, sockfd);
}
if(!WS_Master_Server.ws_ip[0])
{
/* We now must get the Ip address of the device the connection was made on */
NU_Get_Sock_Name(sockfd, &addr, &addr_length);
IP_ADDR_COPY(WS_Master_Server.ws_ip , addr.ip_num.is_ip_addrs);
}
/* Check for any dead connections */
hsock_ent = http_sock.ws_sock_list_head;
while(hsock_ent)
{
if((NU_Is_Connected(hsock_ent->ws_socketd) == NU_TRUE) &&
NU_Retrieve_Clock() < (hsock_ent->ws_time_click + WS_SOCKET_GRACEFUL_TIMEOUT))
{
/* This connection is still good, mark it in the bitmap */
NU_FD_Set(hsock_ent->ws_socketd, &readfs);
hsock_ent = hsock_ent->ws_next_link;
}
else
{
/* This connection is bad, close it and remove it from the list */
NU_Close_Socket(hsock_ent->ws_socketd);
hsock_temp = hsock_ent;
hsock_ent = hsock_ent->ws_next_link;
WS_Remove_Socket_Entry(&http_sock,&free_sock,hsock_temp);
}
}
/* Select on all of the SOCKETS within the System based on an HTTP timeout */
if((NU_Select(NSOCKETS, &readfs, &writefs, &exceptfs, (TICKS_PER_SECOND >> 1))) == NU_SUCCESS)
{
/* Find which socket has the incoming data available */
for(hsock_ent = http_sock.ws_sock_list_head; hsock_ent; hsock_ent = hsock_ent->ws_next_link)
{
if(NU_FD_Check(hsock_ent->ws_socketd, &readfs) == NU_TRUE)
{
/* This socket has data ready to proccess */
sockfd = hsock_ent->ws_socketd;
/* Initialize the following before processing the connection */
connection_bytes = 0;
header_length = 0;
content_length = 0;
data_start = 0;
status = NU_SUCCESS;
Req.ws_hp.ws_header = NU_NULL;
Req.ws_hp.ws_data = NU_NULL;
Req.ws_hp.ws_tsize = 0;
Req.ws_hp.ws_free_buf_sz = 0;
Req.ws_hp.ws_header_size = 0;
Req.ws_hp.ws_header_set = 0;
Req.ws_hp.ws_no_pluginhead = 0;
do
{
bytes_recieved = (INT)(NU_Recv(sockfd, line + connection_bytes,
(UINT16)(WS_RECEIVE_SIZE - connection_bytes), (INT16)NU_NO_SUSPEND));
if (bytes_recieved < 0)
{
#ifdef NU_WEBSERV_DEBUG
printf("\n NU_Recv error\n");
#endif
NU_Close_Socket(hsock_ent->ws_socketd);
WS_Remove_Socket_Entry(&http_sock,&free_sock,hsock_ent);
status = -1;
break;
}
connection_bytes = connection_bytes + bytes_recieved;
/* Null Terminate String */
line[connection_bytes] = 0;
/* We want to get the entire request before calling the plugin. In the case of
* file upload, the entire content won't fit, so don't try to get more than the header.
*/
if (data_start == 0)
{
/* The data starts after the first CRLFCRLF delimiter.
* Keep receiving until we see that delimiter.
*/
if( (data_start = HTTP_In_String("\r\n\r\n",line)) == FAILURE )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -