package com.sleepless.net.http; import java.net.*; import java.io.*; import java.util.*; public class HTTPDaemon extends Thread { // These can be useful for simulating a slow server. // 200 and 100 would probably simulate a 28Kbps connection // 200 and 50 would probably simulate a 56Kbps connection // A good set of values for normally operations would be 20000 and 0 // Of course this is just on my PII 400 sony vaio laptop. // Other engines will probably vary. static final int BUF_SIZE = 20000; static final int DELAY = 0; void m(String s){System.out.println(getClass().getName()+": "+s);} int port; public HTTPDaemon(int p) { port = p; } public void run() { try { m("Listening on port "+port); ServerSocket ss = new ServerSocket(port); while(true) { try { socket = ss.accept(); startTransaction(); } catch(IOException e) { m(e.getMessage()); } } } catch(IOException e) { e.printStackTrace(); } System.exit(1); } BufferedReader br; BufferedWriter bw; Socket socket; String firstLine; String path; int contentLength = 0; byte [] content; void startTransaction() throws IOException { InputStreamReader i = new InputStreamReader(socket.getInputStream()); br = new BufferedReader(i); OutputStreamWriter o = new OutputStreamWriter(socket.getOutputStream()); bw = new BufferedWriter(o); firstLine = null; path = null; contentLength = 0; content = null; doTransaction(); flush(); socket.close(); } String readStr() throws IOException { String s = br.readLine(); return s; } char [] readBytes(int n) throws IOException { char [] buf = new char[n]; br.read(buf, 0, n); return buf; } void writeStr(String s) throws IOException { bw.write(s, 0, s.length()); } void flush() throws IOException { bw.flush(); } void skipHeaders() throws IOException { String s; while(true) { s = readStr(); if(s == null) break; s = s.trim(); if(s.equals("")) break; if( s.startsWith("Content-Length: ") || s.startsWith("Content-length: ") || s.startsWith("content-length: ") ) { contentLength = (int)atol(s.substring(16)); } } } void doTransaction() throws IOException { firstLine = readStr(); if(firstLine == null) return; path = firstLine; int x = path.indexOf(' '); if(x == -1) { defaultTransaction(); return; } path = path.substring(x + 1); x = path.indexOf(' '); if(x == -1) { defaultTransaction(); return; } path = path.substring(0, x); int qu = path.indexOf('?'); if(qu != -1) { path = path.substring(0, qu); } skipHeaders(); // Is it a file? String fpath = "./"+path; File file = new File(fpath); if(file.isFile()) { fileTransaction(file); return; } // No clue. defaultTransaction(); } // Return a file to the client. void fileTransaction(File file) throws IOException { // write the http response headers writeStr("HTTP/1.0 200 OK\n"); writeStr("Server: "+getClass().getName()+" 1.0\n"); // Make some half-hearted attempt to provide a content-type String nl = file.getName().toLowerCase(); if(nl.endsWith(".html")) writeStr("Content-Type: text/html\n"); else if(nl.endsWith(".txt")) writeStr("Content-Type: text/plain\n"); else if(nl.endsWith(".java")) writeStr("Content-Type: text/plain\n"); else if(nl.endsWith(".jpg")) writeStr("Content-Type: image/jpeg\n"); else if(nl.endsWith(".bmp")) writeStr("Content-Type: image/bmp\n"); else if(nl.endsWith(".jpeg")) writeStr("Content-Type: image/jpeg\n"); else if(nl.endsWith(".gif")) writeStr("Content-Type: image/gif\n"); else if(nl.endsWith(".hdml")) writeStr("Content-Type: text/x-hdml\n"); else if(nl.endsWith(".wml")) writeStr("Content-Type: text/vnd.wap.wml\n"); else if(nl.endsWith(".wbmp")) writeStr("Content-Type: image/vnd.wap.wbmp\n"); // write out length long len = file.length(); writeStr("Content-Length: "+len+"\n"); // separated with a blank line writeStr("\n"); flush(); // write out the file FileInputStream fis = new FileInputStream(file); OutputStream sos = socket.getOutputStream(); byte [] buf = new byte[BUF_SIZE]; long n = 0; int r; while(true) { r = fis.read(buf); if(r == -1) break; sos.write(buf, 0, r); n += r; if(DELAY > 0) { try { Thread.sleep(DELAY); } catch(InterruptedException e) { } } } sos.flush(); fis.close(); } // Send back "I can't find what you requested" response void defaultTransaction() throws IOException { String ip = socket.getInetAddress().getHostAddress(); htmlMsg("HTTPDaemon
Document not found.", 404); flush(); // on your way, my lovelies! } // Write out a message as an html page. void htmlMsg(String msg, int code) throws IOException { // write the http response headers writeStr("HTTP/1.0 "+code+" OK\n"); writeStr("Server: "+getClass().getName()+" 1.0\n"); writeStr("Content-Type: text/html\n"); // separated with a blank line writeStr("\n"); // write out the html writeStr("\n"); writeStr(" Hi. \n"); writeStr("\n"); writeStr( msg+"\n"); writeStr("\n"); writeStr("\n"); } static public long atol(String s) { long n = 0; boolean negate = false; for(int i = 0; i < s.length(); i++) { char c = s.charAt(i); if((i == 0) && (c == '-')) { negate = true; continue; } if(c < '0') break; if(c > '9') break; n = (n * 10) + (c - '0'); } if(negate) n *= -1; return n; } public static void main(String [] args) { int p = 80; if(args.length > 0) { p = (int)atol(args[0]); } new HTTPDaemon(p).start(); } }