Thread: [Assorted-commits] SF.net SVN: assorted: [471] nano-httpd
Brought to you by:
yangzhang
From: <yan...@us...> - 2008-02-19 06:45:46
|
Revision: 471 http://assorted.svn.sourceforge.net/assorted/?rev=471&view=rev Author: yangzhang Date: 2008-02-18 22:45:50 -0800 (Mon, 18 Feb 2008) Log Message: ----------- added nano httpd (a ripoff of the sanos example web server) Added Paths: ----------- nano-httpd/ nano-httpd/trunk/ nano-httpd/trunk/README nano-httpd/trunk/src/ nano-httpd/trunk/src/Makefile nano-httpd/trunk/src/nanohttpd.cc Added: nano-httpd/trunk/README =================================================================== --- nano-httpd/trunk/README (rev 0) +++ nano-httpd/trunk/README 2008-02-19 06:45:50 UTC (rev 471) @@ -0,0 +1 @@ +janky little web server Added: nano-httpd/trunk/src/Makefile =================================================================== --- nano-httpd/trunk/src/Makefile (rev 0) +++ nano-httpd/trunk/src/Makefile 2008-02-19 06:45:50 UTC (rev 471) @@ -0,0 +1,8 @@ +all: nanohttpd +nanohttpd: nanohttpd.cc + g++ -Wall -g3 -o $@ $< +run: nanohttpd + ./nanohttpd +clean: + rm -f nanohttpd +.PHONY: clean run Added: nano-httpd/trunk/src/nanohttpd.cc =================================================================== --- nano-httpd/trunk/src/nanohttpd.cc (rev 0) +++ nano-httpd/trunk/src/nanohttpd.cc 2008-02-19 06:45:50 UTC (rev 471) @@ -0,0 +1,223 @@ +// Derived from: +// +// http://www.jbox.dk/sanos/webserver.htm +// +// Example HTTP request +// +// GET / HTTP/1.1 +// User-Agent: Opera/9.25 (Windows NT 5.1; U; en) +// Host: harvard:8000 +// Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1 +// Accept-Language: en-US,en;q=0.9 +// Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1 +// Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 +// Connection: Keep-Alive + +#define STANDALONE 1 + +extern "C" { +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <strings.h> +} + +#if STANDALONE +#include <iostream> +#include <cstdio> + +using namespace std; + +#define lwip_accept accept +#define lwip_bind bind +#define lwip_close close +#define lwip_connect connect +#define lwip_listen listen +#define lwip_socket socket +#define lwip_send send +#define lwip_recv recv + +#define cprintf printf + +void +panic(char *s) +{ + cerr << s << endl; + exit(1); +} + +#endif + +#define nprintf(s, ...) \ + do { \ + char b_[4096]; \ + int n_ = snprintf(b_, sizeof(b_), __VA_ARGS__); \ + if (send(s, b_, n_, 0) == 0) panic("XXX"); \ + } while (0); + +#define SERVER "webserver/1.0" +#define PROTOCOL "HTTP/1.0" +#define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT" +#define PORT 80 + +void send_headers(int f, int status, char *title, char *extra, char *mime, + int length, time_t date) +{ + time_t now; + char timebuf[128]; + + nprintf(f, "%s %d %s\r\n", PROTOCOL, status, title); + nprintf(f, "Server: %s\r\n", SERVER); + now = time(NULL); + strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now)); + nprintf(f, "Date: %s\r\n", timebuf); + if (extra) nprintf(f, "%s\r\n", extra); + if (mime) nprintf(f, "Content-Type: %s\r\n", mime); + if (length >= 0) nprintf(f, "Content-Length: %d\r\n", length); + if (date != -1) + { + strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&date)); + nprintf(f, "Last-Modified: %s\r\n", timebuf); + } + nprintf(f, "Connection: close\r\n"); + nprintf(f, "\r\n"); +} + +void send_error(int f, int status, char *title, char *extra, char *text) +{ + send_headers(f, status, title, extra, "text/html", -1, -1); + nprintf(f, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title); + nprintf(f, "<BODY><H4>%d %s</H4>\r\n", status, title); + nprintf(f, "%s\r\n", text); + nprintf(f, "</BODY></HTML>\r\n"); +} + +// XXX +void send_file(int f, char *path) +{ +// char data[4096]; +// int n; +// +// FILE *file = fopen(path, "r"); +// if (!file) +// send_error(f, 403, "Forbidden", NULL, "Access denied."); +// else +// { +// int length = S_ISREG(statbuf->st_mode) ? statbuf->st_size : -1; +// send_headers(f, 200, "OK", NULL, get_mime_type(path), length, statbuf->st_mtime); +// +// while ((n = fread(data, 1, sizeof(data), file)) > 0) fwrite(data, 1, n, f); +// fclose(file); +// } +} + +int +process(int f) +{ + char buf[4096]; + char *method; + char *path; + char *protocol; +// struct stat statbuf; +// char pathbuf[4096]; +// int len; + + if (recv(f, buf, sizeof(buf), MSG_WAITALL) < 0) return -1; + printf("URL: %s", buf); + + method = strtok(buf, " "); + path = strtok(NULL, " "); + protocol = strtok(NULL, "\r"); + if (!method || !path || !protocol) return -1; + + if (strcasecmp(method, "GET") != 0) + send_error(f, 501, "Not supported", NULL, "Method is not supported."); +// else if (stat(path, &statbuf) < 0) +// send_error(f, 404, "Not Found", NULL, "File not found."); +// else if (S_ISDIR(statbuf.st_mode)) +// { +// len = strlen(path); +// if (len == 0 || path[len - 1] != '/') +// { +// snprintf(pathbuf, sizeof(pathbuf), "Location: %s/", path); +// send_error(f, 302, "Found", pathbuf, "Directories must end with a slash."); +// } +// else +// { +// snprintf(pathbuf, sizeof(pathbuf), "%sindex.html", path); +// if (stat(pathbuf, &statbuf) >= 0) +// send_file(f, pathbuf, &statbuf); +// else +// { +// DIR *dir; +// struct dirent *de; +// +// send_headers(f, 200, "OK", NULL, "text/html", -1, statbuf.st_mtime); +// nprintf(f, "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD>\r\n<BODY>", path); +// nprintf(f, "<H4>Index of %s</H4>\r\n<PRE>\n", path); +// nprintf(f, "Name Last Modified Size\r\n"); +// nprintf(f, "<HR>\r\n"); +// if (len > 1) nprintf(f, "<A HREF=\"..\">..</A>\r\n"); +// +// dir = opendir(path); +// while ((de = readdir(dir)) != NULL) +// { +// char timebuf[32]; +// struct tm *tm; +// +// strcpy(pathbuf, path); +// strcat(pathbuf, de->d_name); +// +// stat(pathbuf, &statbuf); +// tm = gmtime(&statbuf.st_mtime); +// strftime(timebuf, sizeof(timebuf), "%d-%b-%Y %H:%M:%S", tm); +// +// nprintf(f, "<A HREF=\"%s%s\">", de->d_name, S_ISDIR(statbuf.st_mode) ? "/" : ""); +// nprintf(f, "%s%s", de->d_name, S_ISDIR(statbuf.st_mode) ? "/</A>" : "</A> "); +// if (de->d_namlen < 32) nprintf(f, "%*s", 32 - de->d_namlen, ""); +// +// if (S_ISDIR(statbuf.st_mode)) +// nprintf(f, "%s\r\n", timebuf); +// else +// nprintf(f, "%s %10d\r\n", timebuf, statbuf.st_size); +// } +// closedir(dir); +// +// nprintf(f, "</PRE>\r\n<HR>\r\n<ADDRESS>%s</ADDRESS>\r\n</BODY></HTML>\r\n", SERVER); +// } +// } +// } + else + send_file(f, path); // , &statbuf); + + return 0; +} + +int +main() +{ + cprintf("socket\n"); + int s = lwip_socket(PF_INET, SOCK_STREAM, 0); + if (s < 0) panic("XXX"); + + struct sockaddr_in sa; + bzero(&sa, sizeof(sa));; + sa.sin_family = AF_INET; + sa.sin_port = htons(8000); + sa.sin_addr.s_addr = htonl(INADDR_ANY); + + cprintf("bind\n"); + if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) != 0) panic("XXX"); + cprintf("listen\n"); + if (listen(s, 1) != 0) panic("XXX"); + + while (true) { + cprintf("accept\n"); + int t = accept(s, NULL, NULL); + if (t < 0) panic("XXX"); + + cprintf("processing\n"); + if (process(t) < 0) panic("XXX"); + } + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |