📄 httpd.c
字号:
/**************************************************************************** * netutils/webserver/httpd.c * httpd Web server * * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * This is a leverage of similar logic from uIP: * * Author: Adam Dunkels <adam@sics.se> * Copyright (c) 2004, Adam Dunkels. * All rights reserved. * * The uIP web server is a very simplistic implementation of an HTTP * server. It can serve web pages and files from a read-only ROM * filesystem, and provides a very small scripting language. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. ****************************************************************************//**************************************************************************** * Included Files ****************************************************************************/#include <nuttx/config.h>#include <sys/socket.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <pthread.h>#include <errno.h>#include <debug.h>#include <net/uip/uip.h>#include <net/uip/uip-lib.h>#include <net/uip/httpd.h>#include "httpd.h"#include "httpd-cgi.h"/**************************************************************************** * Definitions ****************************************************************************/#define ISO_nl 0x0a#define ISO_space 0x20#define ISO_bang 0x21#define ISO_percent 0x25#define ISO_period 0x2e#define ISO_slash 0x2f#define ISO_colon 0x3a#undef CONFIG_NETUTILS_HTTPD_DUMPBUFFER#undef CONFIG_NETUTILS_HTTPD_DUMPPSTATE/**************************************************************************** * Private Data ****************************************************************************/static const char g_httpcontenttypebinary[] = "Content-type: application/octet-stream\r\n\r\n";static const char g_httpcontenttypecss[] = "Content-type: text/css\r\n\r\n";static const char g_httpcontenttypegif[] = "Content-type: image/gif\r\n\r\n";static const char g_httpcontenttypehtml[] = "Content-type: text/html\r\n\r\n";static const char g_httpcontenttypejpg[] = "Content-type: image/jpeg\r\n\r\n";static const char g_httpcontenttypeplain[] = "Content-type: text/plain\r\n\r\n";static const char g_httpcontenttypepng[] = "Content-type: image/png\r\n\r\n";static const char g_httpextensionhtml[] = ".html";static const char g_httpextensionshtml[] = ".shtml";static const char g_httpextensioncss[] = ".css";static const char g_httpextensionpng[] = ".png";static const char g_httpextensiongif[] = ".gif";static const char g_httpextensionjpg[] = ".jpg";static const char g_http404path[] = "/404.html";static const char g_httpindexpath[] = "/index.html";static const char g_httpcmdget[] = "GET ";static const char g_httpheader200[] = "HTTP/1.0 200 OK\r\n" "Server: uIP/1.0 http://www.sics.se/~adam/uip/\r\n" "Connection: close\r\n";static const char g_httpheader404[] = "HTTP/1.0 404 Not found\r\n" "Server: uIP/1.0 http://www.sics.se/~adam/uip/\r\n" "Connection: close\r\n";/**************************************************************************** * Private Functions ****************************************************************************/#ifdef CONFIG_NETUTILS_HTTPD_DUMPBUFFERstatic void httpd_dumpbuffer(const char *buffer, ssize_t nbytes){#ifdef CONFIG_DEBUG char line[128]; int ch; int i; int j; for (i = 0; i < nbytes; i += 16) { sprintf(line, "%04x: ", i); for ( j = 0; j < 16; j++) { if (i + j < nbytes) { sprintf(&line[strlen(line)], "%02x ", buffer[i+j] ); } else { strcpy(&line[strlen(line)], " "); } } for ( j = 0; j < 16; j++) { if (i + j < nbytes) { ch = buffer[i+j]; sprintf(&line[strlen(line)], "%c", ch >= 0x20 && ch <= 0x7e ? ch : '.'); } } dbg("%s\n", line); }#endif}#else# define httpd_dumpbuffer(buffer,nbytes)#endif#ifdef CONFIG_NETUTILS_HTTPD_DUMPPSTATEstatic void httpd_dumppstate(struct httpd_state *pstate, const char *msg){#ifdef CONFIG_DEBUG dbg("[%d] pstate(%p): [%s]\n", pstate->ht_sockfd, pstate, msg); dbg(" filename: [%s]\n", pstate->ht_filename); dbg(" htfile len: %d\n", pstate->ht_file.len); dbg(" sockfd: %d\n", pstate->ht_sockfd); dbg(" scriptptr: %p\n", pstate->ht_scriptptr); dbg(" scriptlen: %d\n", pstate->ht_scriptlen); dbg(" sndlen: %d\n", pstate->ht_sndlen);#endif}#else# define httpd_dumppstate(pstate, msg)#endifstatic void next_scriptstate(struct httpd_state *pstate){ char *p; p = strchr(pstate->ht_scriptptr, ISO_nl) + 1; pstate->ht_scriptlen -= (unsigned short)(p - pstate->ht_scriptptr); pstate->ht_scriptptr = p;}static int handle_script(struct httpd_state *pstate){ int len; char *ptr; while(pstate->ht_file.len > 0) { /* Check if we should start executing a script */ if (*pstate->ht_file.data == ISO_percent && *(pstate->ht_file.data + 1) == ISO_bang) { pstate->ht_scriptptr = pstate->ht_file.data + 3; pstate->ht_scriptlen = pstate->ht_file.len - 3; if (*(pstate->ht_scriptptr - 1) == ISO_colon) { httpd_fs_open(pstate->ht_scriptptr + 1, &pstate->ht_file); send(pstate->ht_sockfd, pstate->ht_file.data, pstate->ht_file.len, 0); } else { httpd_cgi(pstate->ht_scriptptr)(pstate, pstate->ht_scriptptr); } next_scriptstate(pstate); /* The script is over, so we reset the pointers and continue * sending the rest of the file */ pstate->ht_file.data = pstate->ht_scriptptr; pstate->ht_file.len = pstate->ht_scriptlen; } else { /* See if we find the start of script marker in the block of HTML * to be sent */ if (pstate->ht_file.len > HTTPD_IOBUFFER_SIZE) { len = HTTPD_IOBUFFER_SIZE; } else { len = pstate->ht_file.len; } if (*pstate->ht_file.data == ISO_percent) { ptr = strchr(pstate->ht_file.data + 1, ISO_percent); } else { ptr = strchr(pstate->ht_file.data, ISO_percent); } if (ptr != NULL && ptr != pstate->ht_file.data) { len = (int)(ptr - pstate->ht_file.data); if (len >= HTTPD_IOBUFFER_SIZE) { len = HTTPD_IOBUFFER_SIZE; } } send(pstate->ht_sockfd, pstate->ht_file.data, len, 0); pstate->ht_file.data += len; pstate->ht_file.len -= len; } } return OK;}static int httpd_addchunk(struct httpd_state *pstate, const char *buffer, int len){ int newlen; int chunklen; int ret; do { /* Determine the size of the next chunk so that it fits into the buffer */ newlen = pstate->ht_sndlen + len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -