📄 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. * Copyright (C) 2003 Andrew Lunn. * * 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, Andrew.lunn@ascom.ch * 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;#ifdef CYGPKG_NET_INET6static int server_socket6 = -1;static struct sockaddr_in6 server_address6;#endif/* ================================================================= *//* 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 processing function *//* *//* Reads the HTTP header, look it up in the table and calls the *//* handler. */static void cyg_httpd_process( int client_socket, struct sockaddr *client_address ){ int calen = sizeof(*client_address); 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; char name[64]; char port[10]; getnameinfo(client_address, calen, name, sizeof(name), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV); HTTPD_DIAG("Connection from %s[%s]\n",name,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 ) ) { HTTPD_DIAG("calling %08x: %s\n", entry, 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 ) { HTTPD_DIAG("Not found %s\n",filename); cyg_httpd_send_html( client, NULL, NULL, cyg_httpd_not_found ); } fclose(client);}/* ================================================================= *//* Main HTTP server * * This just loops, collects client connections, and calls the main * process function on the connects*/static void cyg_httpd_server( cyg_addrword_t arg ){ do { int client_socket; struct sockaddr client_address; int calen = sizeof(client_address); fd_set readfds; int n; /* Wait for a connection. */ FD_ZERO(&readfds); FD_SET(server_socket, &readfds);#ifdef CYGPKG_NET_INET6 FD_SET(server_socket6, &readfds); n = (server_socket > server_socket6 ? server_socket : server_socket6) + 1;#else n = server_socket + 1;#endif select(n,&readfds,NULL,NULL,NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -