📄 httpd.c
字号:
/* =================================================================
*
* httpd.c
*
* A simple embedded HTTP server
*
* =================================================================
* ####ECOSGPLCOPYRIGHTBEGIN####
* -------------------------------------------
* This file is part of eCos, the Embedded Configurable Operating
* System.
* Copyright (C) 2002 Nick Garnett.
*
* eCos is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 or (at your option)
* any later version.
*
* eCos is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with eCos; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile this
* file and link it with other works to produce a work based on this
* file, this file does not by itself cause the resulting work to be
* covered by the GNU General Public License. However the source code
* for this file must still be made available in accordance with
* section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* -------------------------------------------
* ####ECOSGPLCOPYRIGHTEND####
* =================================================================
* #####DESCRIPTIONBEGIN####
*
* Author(s): nickg@calivar.com
* Contributors: nickg@calivar.com
* Date: 2002-10-14
* Purpose:
* Description:
*
* ####DESCRIPTIONEND####
*
* =================================================================
*/
#include <pkgconf/system.h>
#include <pkgconf/isoinfra.h>
#include <pkgconf/httpd.h>
#include <cyg/infra/cyg_trac.h> /* tracing macros */
#include <cyg/infra/cyg_ass.h> /* assertion macros */
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <network.h>
#include <arpa/inet.h>
#include <cyg/httpd/httpd.h>
/* ================================================================= */
#if 0
#define HTTPD_DIAG diag_printf
#else
#define HTTPD_DIAG(...)
#endif
/* ================================================================= */
/* Server socket address and file descriptor.
*/
static struct sockaddr_in server_address;
static int server_socket = -1;
/* ================================================================= */
/* Thread stacks, etc.
*/
static cyg_uint8 httpd_stacks[CYGNUM_HTTPD_THREAD_COUNT]
[CYGNUM_HAL_STACK_SIZE_MINIMUM+
CYGNUM_HTTPD_SERVER_BUFFER_SIZE+
CYGNUM_HTTPD_THREAD_STACK_SIZE];
static cyg_handle_t httpd_thread[CYGNUM_HTTPD_THREAD_COUNT];
static cyg_thread httpd_thread_object[CYGNUM_HTTPD_THREAD_COUNT];
/* ================================================================= */
/* Filename lookup table
*/
CYG_HAL_TABLE_BEGIN( cyg_httpd_table, httpd_table );
CYG_HAL_TABLE_END( cyg_httpd_table_end, httpd_table );
__externC cyg_httpd_table_entry cyg_httpd_table[];
__externC cyg_httpd_table_entry cyg_httpd_table_end[];
/* ================================================================= */
/* Page not found message
*/
static char cyg_httpd_not_found[] =
"<head><title>Page Not found</title></head>\n"
"<body><h2>The requested URL was not found on this server.</h2></body>\n";
/* ================================================================= */
/* Simple pattern matcher for filenames
*
* This performs a simple pattern match between the given name and the
* pattern. At present the only matching supported is either exact, or
* if the pattern ends in * then that matches all remaining
* characters. At some point we might want to implement a more
* complete regular expression parser here.
*/
static cyg_bool match( char *name, char *pattern )
{
while( *name != 0 && *pattern != 0 && *name == *pattern )
name++, pattern++;
if( *name == 0 && *pattern == 0 )
return true;
if( *pattern == '*' )
return true;
return false;
}
/* ================================================================= */
/* Main HTTP server
*
* This just loops, collects client connections, reads the HTTP
* header, look it up in the table and calls the handler.
*/
static void cyg_httpd_server( cyg_addrword_t arg )
{
do
{
int err;
int client_socket;
struct sockaddr_in client_address;
int calen;
int nlc = 0;
char request[CYGNUM_HTTPD_SERVER_BUFFER_SIZE];
FILE *client;
cyg_httpd_table_entry *entry = cyg_httpd_table;
char *filename;
char *formdata = NULL;
char *p;
cyg_bool success = false;
/* Wait for a connection.
*/
client_socket = accept( server_socket, (struct sockaddr *)&client_address, &calen );
HTTPD_DIAG("Connection from %08x[%d]\n",client_address.sin_addr.s_addr,
client_address.sin_port);
/* Convert the file descriptor to a C library FILE object so
* we can use fprintf() and friends on it.
*/
client = fdopen( client_socket, "r+");
/* We are really only interested in the first line.
*/
fgets( request, sizeof(request), client );
HTTPD_DIAG("Request >%s<\n", request );
/* Absorb the rest of the header. We nibble it away a
* character at a time like this to avoid having to define
* another buffer to read lines into. If we ever need to take
* more interest in the header fields, we will need to be a
* lot more sophisticated than this.
*/
do{
int c = getc( client );
HTTPD_DIAG("%c",c);
if( c == '\n' )
nlc++;
else if( c != '\r' )
nlc = 0;
} while(nlc < 2);
/* Extract the filename and any form data being returned.
* We know that the "GET " request takes 4 bytes.
* TODO: handle POST type requests as well as GET's.
*/
filename = p = request+4;
/* Now scan the filename until we hit a space or a '?'. If we
* end on a '?' then the rest is a form request. Put NULs at
* the end of each string.
*/
while( *p != ' ' && *p != '?' )
p++;
if( *p == '?' )
formdata = p+1;
*p = 0;
if( formdata != NULL )
{
while( *p != ' ' )
p++;
*p = 0;
}
HTTPD_DIAG("Request filename >%s< formdata >%s<\n",filename,formdata?formdata:"-NULL-");
HTTPD_DIAG("table: %08x...%08x\n",cyg_httpd_table, cyg_httpd_table_end);
/* Now scan the table for a matching entry. If we find one
* call the handler routine. If that returns true then we
* terminate the scan, otherwise we keep looking.
*/
while( entry != cyg_httpd_table_end )
{
HTTPD_DIAG("try %08x: %s\n", entry, entry->pattern);
if( match( filename, entry->pattern ) )
{
if( (success = entry->handler( client, filename, formdata, entry->arg )) )
break;
}
entry++;
}
/* If we failed to find a match in the table, send a "not
* found" response.
* TODO: add an optional fallback to go look for files in
* some filesystem, somewhere.
*/
if( !success )
cyg_httpd_send_html( client, NULL, NULL, cyg_httpd_not_found );
/* All done, close the connection
*/
err = fclose( client );
CYG_ASSERT( err == 0, "fclose() returned error");
} while(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -