digitalmars.D - I need review this web server
- Eungkyu Song (218/218) Jun 12 2004 I wrote a very simple web server for testing d language. (in linux)
- Bruno A. Costa (9/18) Jun 14 2004 Hi,
- J C Calvarese (14/39) Jun 14 2004 Hmmm. It compiles fine for me using DMD 0.92 on WinXP (once I add
I wrote a very simple web server for testing d language. (in linux) It seems to work well. but a chunk of memory leeks per connection especially in thread mode. please help me. i need review for the code style too. below is the code Makefile: -------------------------------------------------------- TARGET = httpd httpd-inetd httpd-thread all: $(TARGET) httpd: httpd.d dmd -ofhttpd httpd.d httpd-inetd: httpd.d dmd -ofhttpd-inetd -version=inetd httpd.d httpd-thread: httpd.d dmd -ofhttpd-thread -version=thread httpd.d clean: rm -f *.o $(TARGET) -------------------------------------------------------- httpd.d: -------------------------------------------------------- import std.socket; import std.socketstream; import std.stream; import std.string; import std.file; import std.thread; alias char[][char[]] map; const char[] SERVER = "Dhttpd"; const char[] SERVER_ROOT = "/home/eungkyu/public_html"; const char[] DEFAULT = "index.html"; const char[] MIME_DEFAULT = "text/plain"; const int PORT = 8888; char[][int] code_string; char[][int] error; map mime_type; extern (C) { alias void function(int) sighandler_t; const int SIGPIPE = 13; const sighandler_t SIG_IGN = cast(sighandler_t) 2; sighandler_t signal(int signum, sighandler_t handler); void handle_signal(int signo) { /* do nothing */ } alias long time_t; time_t time(time_t* t); size_t strftime(char* s, size_t max, in char* format, in void* tm); void* localtime(time_t* timep); } void init() { code_string[200] = "OK"; code_string[400] = "Bad Request"; code_string[403] = "Forbidden"; code_string[404] = "Not Found"; code_string[501] = "Not Implemented"; error[400] = "error/400.html"; error[403] = "error/403.html"; error[404] = "error/404.html"; error[501] = "error/501.html"; mime_type["html"] = "text/html"; mime_type["htm"] = "text/html"; mime_type["gif"] = "image/gif"; mime_type["jpg"] = "image/jpeg"; mime_type["jpeg"] = "image/jpeg"; mime_type["png"] = "image/png"; mime_type["txt"] = "text/plain"; /* why ignoring or not touching the SIGPIPE cause segfault */ //signal(SIGPIPE, &SIG_IGN); signal(SIGPIPE, &handle_signal); chdir(SERVER_ROOT); } Socket init_listener(int port) { Socket listener = new TcpSocket; listener.bind(new InternetAddress(port)); listener.listen(10); return listener; } map parse_header(Stream input) { map header; char[] line, name, value; while ((line = input.readLine()) != null) { if (find(" \t", line[0]) == 0 && name != null) { header[name] ~= stripl(line); continue; } int delim = find(line, ':'); if (delim == -1) { name = null; continue; } name = line[0 .. delim]; value = stripl(line[delim + 1 .. line.length]); header[name] = value; } return header; } void print_header(Stream output, map header) { foreach(char[] name; header.keys) output.writeLine(name ~ ": " ~ header[name]); } char[] get_path(char[] location) { char[] path = "." ~ location; while (path.length > 0 && path[path.length - 1] == '/') path.length = path.length - 1; return path; } char[] get_mime_type(char[] path) { if (path == null) return MIME_DEFAULT; int extloc = rfind(path, '.'); if (extloc == -1) return MIME_DEFAULT; char[] ext = path[extloc + 1 .. path.length]; if (mime_type[ext] == null) return MIME_DEFAULT; return mime_type[ext]; } char[] get_date_string() { char[50] tmp; time_t t; time(&t); strftime(tmp, 50, "%a, %d %b %Y %H:%M:%S %z", localtime(&t)); /* return toString(tmp) doesn't work */ return toString(tmp).dup; } void response(Stream output, int code, char[] path = null) { map header; header["Server"] = SERVER; header["Connection"] = "closed"; header["Date"] = get_date_string(); if (code >= 400 && code < 600 && path == null) path = error[code]; if (path != null) { header["Content-Type"] = get_mime_type(path); header["Content-Length"] = toString(getSize(path)); } try { output.printf("HTTP/1.0 %i %.*s\r\n", code, code_string[code]); print_header(output, header); output.writeString("\r\n"); if (path != null) { File file = new File(path, FileMode.In); output.copyFrom(file, file.size); file.close(); } } catch (WriteError) { /* client closed the connection. just ignore it */ } } void process(Stream output, char[][] method, map header) { if (method.length == 0) return response(output, 400); if (method[0] != "GET") return response(output, 501); if (method[1][0] != '/') return response(output, 400); char[] path = get_path(method[1]); while (exists(path) == 1) { if (isdir(path) == 0) return response(output, 200, path); if (exists(path ~ "/" ~ DEFAULT) == 0) { return response(output, 403); } path ~= "/" ~ DEFAULT; } return response(output, 404); } int run(void* data) { Stream[] stream = *(cast(Stream[]*) data); char[][] method = split(stream[0].readLine()); map header = parse_header(stream[0]); process(stream[1], method, header); stream[0].close(); stream[1].close(); return 0; } int main(char[][] args) { init(); version (inetd) { Stream[] stream; stream.length = 2; stream[0] = stdin; stream[1] = stdout; run(&stream); } else { Socket listener = init_listener(PORT); while (1) { Stream[] stream; stream.length = 2; SocketStream sockstream = new SocketStream(listener.accept()); stream[0] = sockstream; stream[1] = sockstream; version (thread) { Thread runner = new Thread(&run, &stream); runner.start(); } else { run(&stream); } } } return 0; } --------------------------------------------------------
Jun 12 2004
Hi, the code does not compile. I am using dmd-0.92 with Linux: $ make httpd dmd -ofhttpd httpd.d httpd.d(200): e2ir: cannot cast from void* to Stream [] make: ** [httpd] Erro 1 The error occurs in function run(void* data) Bruno. Eungkyu Song wrote:I wrote a very simple web server for testing d language. (in linux) It seems to work well. but a chunk of memory leeks per connection especially in thread mode. please help me. i need review for the code style too. below is the code
Jun 14 2004
Bruno A. Costa wrote:Hi, the code does not compile. I am using dmd-0.92 with Linux:Hmmm. It compiles fine for me using DMD 0.92 on WinXP (once I add ws2_32.lib). I don't have Linux installed, so I can't check whether it'd compile for me on Linux. It could be a bug in the Linux version of the compiler.$ make httpd dmd -ofhttpd httpd.d httpd.d(200): e2ir: cannot cast from void* to Stream [] make: ** [httpd] Erro 1 The error occurs in function run(void* data) Bruno. Eungkyu Song wrote:I don't claim to be an expert on garbage collection (that's an understatement), but have you tried invoking a full collection at a strategic time? import std.gc; ... fullCollect();I wrote a very simple web server for testing d language. (in linux) It seems to work well. but a chunk of memory leeks per connection especially in thread mode.-- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/please help me. i need review for the code style too. below is the code
Jun 14 2004