/*
* Copyright (c) Martin Schoeberl, martin@jopdesign.com
* All rights reserved.
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Martin Schoeberl
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
*/
package ejip;
/**
* Simple HTTP server, based on Wolfgang's HTTPServer example.
*/
public class SimpleHttp extends TcpHandler {
public static final int CMD = 0;
public static final int CONT_CMD = 1;
public static final int CONT_REPLY = 2;
public static final int QUIT = 3;
public static final int MAX_CMDLEN = 4*1024;
private int state = CMD;
private StringBuffer sb = new StringBuffer();
private StringBuffer cmd = new StringBuffer();
public Packet request(Packet p) {
Ip.getData(p, Tcp.DATA, sb);
if (Logging.LOG) {
Logging.wr("\nHTTP request: ");
Logging.wr(sb);
}
// ignore messages unless we continue to send the message
if ((sb.length() == 0) && (state != CONT_REPLY)) {
return null;
}
switch(state) {
case CMD:
cmd.setLength(0);
state = CONT_CMD;
/* fall through */
case CONT_CMD:
cmd.append(sb);
if (cmd.indexOf("\r\n\r\n") >= 0) {
// parse command and send first reply
if (cmd.charAt(0)=='G' && cmd.charAt(1)=='E' && cmd.charAt(2)=='T' && cmd.charAt(3)==' ') {
if (cmd.charAt(4)=='/') {
sb.setLength(0);
sb.append("HTTP/1.0 200 OK\r\n\r\n");
Ip.setData(p, Tcp.DATA, sb);
state = CONT_REPLY;
} else {
Ip.setData(p, Tcp.DATA, "HTTP/1.0 404 File not found\r\nContent-Length: 3\r\n\r\n404");
state = QUIT;
}
} else {
Ip.setData(p, Tcp.DATA, "HTTP/1.0 501 I can only handle GET\r\nContent-Length: 3\r\n\r\n501");
state = QUIT;
}
} else {
if (cmd.length() > MAX_CMDLEN) {
state = QUIT;
}
// just ack what we have
return null;
}
break;
case CONT_REPLY:
// get the single page
setContent(sb, cmd);
Ip.setData(p, Tcp.DATA, sb);
// we serve only a single page
state = QUIT;
break;
case QUIT:
// ignore any messages when idle
return null;
}
return p;
}
public Packet established(Packet p) {
state = CMD;
return null;
}
public boolean finished() {
return state == QUIT;
}
private int hitCount;
/**
* Serve a single HTTP packet. Overwrite for an application HTTP
* server.
* @param sb the HTML content will be set here.
*/
void setContent(StringBuffer sb, StringBuffer cmd) {
sb.setLength(0);
sb.append("<html><head></head><body><h2>Hello WWW World!</h2>");
sb.append("<p>");
sb.append(++hitCount);
sb.append("</body></html>\r\n\r\n");
}
}