📄 emhttp.c
字号:
/* * Embedded HTTP Server main * * ./software/ch7/emhttps/emhttp.c * * mtj@cogitollc.com * */#include <sys/socket.h>#include <arpa/inet.h>#include <signal.h>#include <stdio.h>#include <string.h>#include <sys/un.h>#include <unistd.h>#include "emhttp.h"#include "filehdlr.h"#include "dyncntnt.h"#include "log.h"const char *notimplemented={"HTTP/1.1 501 Not Implemented\n\n"};const char *notfound={"HTTP/1.1 404 File not found\n\n"};const char *success={"HTTP/1.1 200 OK\n"};const char *created={"HTTP/1.1 201 Created\n"};const char *content_types[]={ "text/html", "application/octet-stream", "image/jpeg", "image/gif", "text/plain", "text/x-hdml"};/*--------------------------------------------------------------------------- * ouch() - signal handler for SIGPIPE (UN*X host only) *-------------------------------------------------------------------------*/void ouch ( int sigNum ){ /* * Avoid EPIPE crash... */}/*--------------------------------------------------------------------------- * getFilename() - Parse a filename out of the URL *-------------------------------------------------------------------------*/void getFilename(char *inbuf, char *out, int start){ int i=start, j=0; /* * Skip any initial spaces */ while (inbuf[i] == ' ') i++; for ( ; i < strlen(inbuf) ; i++) { if (inbuf[i] == ' ') { out[j] = 0; break; } out[j++] = inbuf[i]; } if (!strcmp(out, "/")) strcpy(out, "/index.html");}/*--------------------------------------------------------------------------- * determineContentType() - self explanatory *-------------------------------------------------------------------------*/int determineContentType(int fileOffset){ char suffix[20]; int i; extern unsigned char filedata[]; fileOffset+=2; for ( ; filedata[fileOffset] != 0 ; fileOffset++) { if (filedata[fileOffset] == '.') break; } if (filedata[fileOffset] == 0) return(TEXT_PLAIN); else { fileOffset++; for (i = 0 ; filedata[fileOffset+i] != 0 ; i++) { suffix[i] = filedata[fileOffset+i]; } suffix[i] = 0; /* * Now that we've go the suffix, determine the content type */ if (!strncmp(suffix, "html", 4) || !strncmp(suffix, "HTML", 4) || !strncmp(suffix, "htm", 3) || !strncmp(suffix, "HTM", 3)) { return(TEXT_HTML); } else if (!strncmp(suffix, "class", 5) || !strncmp(suffix, "CLASS", 5) || !strncmp(suffix, "jar", 3) || !strncmp(suffix, "JAR", 3)) { return(OCTET_STREAM); } else if (!strncmp(suffix, "jpeg", 4) || !strncmp(suffix, "JPEG", 4) || !strncmp(suffix, "jpg", 4) || !strncmp(suffix, "JPG", 4)) { return(JPEG_IMAGE); } else if (!strncmp(suffix, "gif", 3) || !strncmp(suffix, "GIF", 3)) { return(GIF_IMAGE); } else if (!strncmp(suffix, "hdml", 4)) { return(TEXT_HDML); } else { return(OCTET_STREAM); } }}/*--------------------------------------------------------------------------- * returnFileHeader() - Emit the HTTP response message through the socket *-------------------------------------------------------------------------*/void returnFileHeader(int fd, int ct){ char line[MAX_LINE+1]; write(fd, success, strlen(success)); sprintf(line, "Server: emhttp\n"); write(fd, line, strlen(line)); sprintf(line, "Connection: close\n"); write(fd, line, strlen(line)); sprintf(line, "Content-Type: %s\n\n", content_types[ct]); write(fd, line, strlen(line));}/*--------------------------------------------------------------------------- * parseAndEmitFile() - Parse the HTML and replace dynamic content tags *-------------------------------------------------------------------------*/void parseAndEmitFile(int fd, struct fileHdrStruct *filehdr){ int i; char content[MAX_LINE+1]; extern unsigned char filedata[]; /* Emit the dynamic HTML file replacing the <DATA #> with the appropriate * content. */ for (i = 0 ; i < filehdr->size ; i++) { if (filedata[filehdr->fileStart+i] == '<') { if (!strncmp(&filedata[filehdr->fileStart+i+1], "DATA", 4)) { i+= 6; getDynamicContent(&filedata[filehdr->fileStart+i], content); /* * Emit the dynamic content */ write(fd, content, strlen(content)); for ( ; filedata[filehdr->fileStart+i] != '>' ; i++); } else { write(fd, &filedata[filehdr->fileStart+i], 1); } } else { write(fd, &filedata[filehdr->fileStart+i], 1); } }}/*--------------------------------------------------------------------------- * returnFile() - High level return message function *-------------------------------------------------------------------------*/void returnFile(int fd, struct fileHdrStruct *filehdr){ int ct; extern unsigned char filedata[]; ct = determineContentType(filehdr->hdrStart); returnFileHeader(fd, ct); if ((ct == TEXT_HTML) || (ct == TEXT_HDML)) { parseAndEmitFile(fd, filehdr); } else { write(fd, &filedata[filehdr->fileStart], filehdr->size); }}/*--------------------------------------------------------------------------- * findMsgBody() - Find the message body of an HTTP Request Message *-------------------------------------------------------------------------*/char *findMsgBody( char *buf ){ char *temp; char *separator={"\015\012\015\012"}; temp = strstr(buf, separator); if (temp == NULL) return NULL; else return temp+4;}/*--------------------------------------------------------------------------- * handleConnection() - Parse and handle the current HTTP request message *-------------------------------------------------------------------------*/void handleConnection(int fd){ int len, max, loop; char buffer[4096]={0}; char filename[256]={0}; int ret; struct fileHdrStruct filehdr; /* * Read in the Request Header */ max = 0; loop = 1; while (loop) { len = read(fd, &buffer[max], 255); buffer[max+len] = 0; if (len <= 0) return; max += len; if (!strncmp(buffer, "POST", 4)) { if (strstr(buffer, "+Query")) loop = 0; } else { if ((buffer[max-4] == 0x0d) && (buffer[max-3] == 0x0a) && (buffer[max-2] == 0x0d) && (buffer[max-1] == 0x0a)) loop = 0; } } /* * Determine request */ if (!strncmp(buffer, "GET", 3)) { getFilename(buffer, filename, 4); if (!strncmp(filename, "/log", 4)) { sendLog(fd); } else { ret = lookupFilename(filename, &filehdr); if (ret > 0) { returnFile(fd, &filehdr); } else { emitByte(PREFIX_BYTE); emitByte(UNKNOWN_FILE); emitString(filename); emitByte(SUFFIX_BYTE); write(fd, notfound, strlen(notfound)); } } } else if (!strncmp(buffer, "POST", 4)) { getFilename(buffer, filename, 5); ret = callDynamicHandler(filename, findMsgBody(buffer)); if (ret == 0) { write(fd, created, strlen(created)); } else { write(fd, notfound, strlen(notfound)); } emitByte(PREFIX_BYTE); emitByte(POST_REQUEST); emitString(filename); emitByte(SUFFIX_BYTE); } else { write(fd, notimplemented, strlen(notimplemented)); }}/*--------------------------------------------------------------------------- * main() - The embedded HTTP server main *-------------------------------------------------------------------------*/int main(int argc, char *argv[]){ int listenfd, connfd, on=1; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; extern void userInit(); /* Init the dynamic content test func */ userInit(); (void)signal(SIGPIPE, ouch); listenfd = socket(AF_INET, SOCK_STREAM, 0); setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ); bzero((void *)&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(80); bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd, 5); for ( ; ; ) { clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen); if (connfd <= 0) break; handleConnection(connfd); close(connfd); } close(listenfd); return(0);}/* * Copyright (c) 2002 Charles River Media. All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, is hereby granted without fee 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 Charles River Media 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 CHARLES RIVER MEDIA AND CONTRIBUTERS * 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CHARLES * RIVER MEDIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARAY, 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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -