📄 50a731bed5b9001c180780c9bab1766d
字号:
}
/* We've found the requested file; send its header and move on. */
else
{
ret_code = http_send_file_header(conn, filename, HTTP_OK);
}
return ret_code;
}
/*
* http_handle_post()
*
* Process the post request and take the appropriate action.
*/
int http_handle_post(http_conn* conn)
{
alt_u8* tx_wr_pos = conn->tx_buffer;
int ret_code = 0;
tx_wr_pos += sprintf(tx_wr_pos, HTTP_VERSION_STRING);
tx_wr_pos += sprintf(tx_wr_pos, HTTP_NO_CONTENT_STRING);
conn->close = 1;
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CLOSE);
tx_wr_pos += sprintf(tx_wr_pos, HTTP_END_OF_HEADERS);
send(conn->fd, conn->tx_buffer, (tx_wr_pos - conn->tx_buffer), 0);
if (!strcmp(conn->uri, mapping.name))
{
mapping.func();
}
return ret_code;
}
/*
* http_prepare_response()
*
* Service the various HTTP commands, calling the relevant subroutine.
* We only handle GET and POST.
*/
int http_prepare_response(http_conn* conn)
{
int ret_code = 0;
switch (conn->action)
{
case GET:
{
/* Find file from uri */
ret_code = http_find_file(conn);
break;
}
case POST:
{
/* Find file from uri */
ret_code = http_handle_post(conn);
break;
}
default:
{
break;
}
} /* switch (conn->action) */
return ret_code;
}
/*
* http_handle_receive()
*
* Work out what the request we received was, and handle it.
*/
void http_handle_receive(http_conn* conn, int http_instance)
{
int data_used, rx_code;
if (conn->state == READY)
{
rx_code = recv(conn->fd, conn->rx_wr_pos,
(HTTP_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1),
MSG_DONTWAIT);
/*
* If a valid data received, take care of buffer pointer & string
* termination and more on. Otherwise, we need to return and wait for more
* data to arrive (until we time out).
*/
if(rx_code > 0)
{
conn->rx_wr_pos += rx_code;
*(conn->rx_wr_pos+1) = 0;
if(strstr(conn->rx_buffer, HTTP_END_OF_HEADERS))
{
conn->state = PROCESS;
}
}
}
if(conn->state == PROCESS)
{
/*
* If we (think) we have valid headers, keep the connection alive a bit
* longer.
*/
conn->activity_time = alt_nticks();
/*
* Attempt to process the fundamentals of the HTTP request. We may
* error out and reset if the request wasn't complete, or something
* was asked from us that we can't handle.
*/
if (http_process_request(conn))
{
//fprintf(stderr, "[http_handle_receive] http_process_request failed\n");
conn->state = RESET;
http_manage_connection(conn, http_instance);
}
/*
* Step through the headers to see if there is any other useful
* information about our pending transaction to extract. After that's
* done, send some headers of our own back to let the client know
* what's happening. Also, once all in-coming headers have been parsed
* we can manage our RX buffer to prepare for the next in-coming
* connection.
*/
while(conn->state == PROCESS)
{
if(http_read_line(conn))
{
//fprintf(stderr, "[http_handle_receive] error reading headers\n");
conn->state = RESET;
http_manage_connection(conn, http_instance);
break;
}
if(http_process_headers(conn))
{
if( (conn->rx_rd_pos = strstr(conn->rx_rd_pos, HTTP_CR_LF)) )
{
conn->rx_rd_pos += 2;
conn->state = DATA;
conn->activity_time = alt_nticks();
}
else
{
//fprintf(stderr, "[http_handle_receive] Can't find end of headers!\n");
conn->state = RESET;
http_manage_connection(conn, http_instance);
break;
}
}
} /* while(conn->state == PROCESS) */
if( http_prepare_response(conn) )
{
conn->state = RESET;
//fprintf(stderr, "[http_handle_receive] Error preparing response\n");
http_manage_connection(conn, http_instance);
}
/*
* Manage RX Buffer: Slide any un-read data in our input buffer
* down over previously-read data that can now be overwritten, and
* zero-out any bytes in question at the top of our new un-read space.
*/
if(conn->rx_rd_pos > (conn->rx_buffer + HTTP_RX_BUF_SIZE))
{
conn->rx_rd_pos = conn->rx_buffer + HTTP_RX_BUF_SIZE;
}
data_used = conn->rx_rd_pos - conn->rx_buffer;
memmove(conn->rx_buffer,conn->rx_rd_pos,conn->rx_wr_pos-conn->rx_rd_pos);
conn->rx_rd_pos = conn->rx_buffer;
conn->rx_wr_pos -= data_used;
memset(conn->rx_wr_pos, 0, data_used);
}
}
/*
* http_handle_transmit()
*
* Transmit a chunk of a file in an active HTTP connection. This routine
* will be called from the thread's main loop when ever the socket is in
* the 'DATA' state and the socket is marked as available for writing (free
* buffer space).
*/
void http_handle_transmit(http_conn* conn, int http_instance)
{
if( http_send_file_chunk(conn) )
{
//fprintf(stderr, "[http_handle_transmit]: Send file chunk failed\n");
}
}
/*
* http_task()
*
* This MicroC/OS-II thread spins forever after first establishing a listening
* socket for HTTP connections, binding them, and listening. Once setup,
* it perpetually waits for incoming data to either a listening socket, or
* (if there is an active connection), an HTTP data socket. When data arrives,
* the approrpriate routine is called to either accept/reject a connection
* request, or process incoming data.
*
* This routine calls "select()" to determine which sockets are ready for
* reading or writing. This, in conjunction with the use of non-blocking
* send() and recv() calls and sending responses broken up into chunks lets
* us handle multiple active HTTP requests.
*/
void http_task()
{
int i, fd_listen, max_socket;
struct sockaddr_in addr;
struct timeval select_timeout;
fd_set readfds, writefds;
static http_conn conn[HTTP_NUM_CONNECTIONS];
/*
* Sockets primer...
* The socket() call creates an endpoint for TCP of UDP communication. It
* returns a descriptor (similar to a file descriptor) that we call fd_listen,
* or, "the socket we're listening on for connection requests" in our web
* server example.
*/
printf("http_task is called\n");
printf("create socket\n");
if ((fd_listen = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
die_with_error("[http_task] Listening socket creation failed");
}
/*
* Sockets primer, continued...
* Calling bind() associates a socket created with socket() to a particular IP
* port and incoming address. In this case we're binding to HTTP_PORT and to
* INADDR_ANY address (allowing anyone to connect to us. Bind may fail for
* various reasons, but the most common is that some other socket is bound to
* the port we're requesting.
*/
addr.sin_family = AF_INET;
addr.sin_port = htons(HTTP_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
printf("bind socket\n");
if ((bind(fd_listen,(struct sockaddr *)&addr,sizeof(addr))) < 0)
{
die_with_error("[http_task] Bind failed");
}
/*
* Sockets primer, continued...
* The listen socket is a socket which is waiting for incoming connections.
* This call to listen will block (i.e. not return) until someone tries to
* connect to this port.
*/
printf("listen socket\n");
if ((listen(fd_listen,1)) < 0)
{
die_with_error("[http_task] Listen failed");
}
/*
* At this point we have successfully created a socket which is listening
* on HTTP_PORT for connection requests from any remote address.
*/
for(i=0; i<HTTP_NUM_CONNECTIONS; i++)
{
printf("http_reset_connection socket\n");
http_reset_connection(&conn[i], i);
printf("conn[%d]=%d\n",i,conn[i].fd);
}
printf("while(1) fd_listen=%d\n",fd_listen);
while(1)
{
/*
* The select() call below tells the LWIP stack to return from this call
* when any of the events we have expressed an interest in happen (it
* blocks until our call to select() is satisfied).
*
* In the call below we're only interested in either someone trying to
* connect to us, or when an existing (active) connection has new receive
* data, or when an existing connection is in the "DATA" state meaning that
* we're in the middle of processing an HTTP request. If none of these
* conditions are satisfied, select() blocks until a timeout specified
* in the select_timeout struct.
*
* The sockets we're interested in (for RX) are passed in inside the
* readfds parameter, while those we're interested in for TX as passed in
* inside the writefds parameter. The format of readfds and writefds is
* implementation dependant, hence there are standard macros for
* setting/reading the values:
*
* FD_ZERO - Zero's out the sockets we're interested in
* FD_SET - Adds a socket to those we're interested in
* FD_ISSET - Tests whether the chosen socket is set
*/
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(fd_listen, &readfds);
max_socket = fd_listen+1;
for(i=0; i<HTTP_NUM_CONNECTIONS; i++)
{
if (conn[i].fd != -1)
{
printf("conn[%d].fd=%d\n",i,conn[i].fd);
/* We're interested in reading any of our active sockets */
FD_SET(conn[i].fd, &readfds);
/*
* We're interested in writing to any of our active sockets in the DATA
* state
*/
if(conn[i].state == DATA)
{
printf("conn[%d].state == DATA\n",i);
FD_SET(conn[i].fd, &writefds);
}
/*
* select() must be called with the maximum number of sockets to look
* through. This will be the largest socket number + 1 (since we start
* at zero).
*/
if (max_socket <= conn[i].fd)
{
max_socket = conn[i].fd+1;
}
}
}
/*
* Set timeout value for select. This must be reset for each select()
* call.
*/
select_timeout.tv_sec = 0;
select_timeout.tv_usec = 500000;
select(max_socket, &readfds, &writefds, NULL, &select_timeout);
/*
* If fd_listen (the listening socket we originally created in this thread
* is "set" in readfds, then we have an incoming connection request.
* We'll call a routine to explicitly accept or deny the incoming connection
* request.
*/
if (FD_ISSET(fd_listen, &readfds))
{
printf("we have an incoming connection request.\n");
http_handle_accept(fd_listen, conn);
printf("http_handle_accept.\n");
}
/*
* If http_handle_accept() accepts the connection, it creates *another*
* socket for sending/receiving data. This socket is independant of the
* listening socket we created above. This socket's descriptor is stored
* in conn[i].fd. Therefore if conn[i].fd is set in readfs, we have
* incoming data for our HTTP server, and we call our receive routine
* to process it. Likewise, if conn[i].fd is set in writefds, we have
* an open connection that is *capable* of being written to.
*/
for(i=0; i<HTTP_NUM_CONNECTIONS; i++)
{
if (conn[i].fd != -1)
{
if(FD_ISSET(conn[i].fd,&readfds))
{
http_handle_receive(&conn[i], i);
}
if(FD_ISSET(conn[i].fd,&writefds))
{
http_handle_transmit(&conn[i], i);
}
http_manage_connection(&conn[i], i);
}
}
} /* while(1) */
}
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -