1 package dolda.jsvc.scgi;
3 import java.util.logging.*;
8 public abstract class Server implements Runnable {
9 private final ServerSocket sk;
10 private final Logger logger = Logger.getLogger("dolda.jsvc.scgi");
11 private boolean running = false;
12 public String headcs = "UTF-8";
14 public Server(ServerSocket sk) {
18 private static int readnslen(InputStream in) throws IOException {
24 else if((c >= '0') && (c <= '9'))
25 ret = (ret * 10) + (c - '0');
27 throw(new InvalidRequestException("Malformed netstring length"));
31 private static byte[] readns(InputStream in) throws IOException {
32 byte[] buf = new byte[readnslen(in)];
34 while(off < buf.length) {
35 int ret = in.read(buf, off, buf.length - off);
37 throw(new InvalidRequestException("Unexpected EOS in netstring"));
41 throw(new InvalidRequestException("Unterminated netstring"));
45 private Map<String, String> readhead(InputStream in) throws IOException {
46 byte[] rawhead = readns(in);
47 String head = new String(rawhead, headcs);
48 Map<String, String> ret = new HashMap<String, String>();
51 int p2 = head.indexOf(0, p);
53 if(p == head.length())
55 throw(new InvalidRequestException("Malformed headers"));
57 String key = head.substring(p, p2);
58 int p3 = head.indexOf(0, p2 + 1);
60 throw(new InvalidRequestException("Malformed headers"));
61 String val = head.substring(p2 + 1, p3);
67 private boolean checkhead(Map<String, String> head) {
68 if(!head.containsKey("SCGI") || !head.get("SCGI").equals("1"))
73 protected abstract void handle(Map<String, String> head, Socket sk) throws Exception;
75 private void serve(Socket sk) {
78 InputStream in = sk.getInputStream();
79 Map<String, String> head = readhead(in);
84 } catch(Exception e) {
85 logger.log(Level.WARNING, "Could not handle request", e);
93 } catch(IOException e) {
94 logger.log(Level.WARNING, "I/O error encountered while serving SCGI request", e);
103 throw(new IllegalStateException("SCGI server is already running"));
107 Socket nsk = sk.accept();
113 } catch(IOException e) {
114 if((e instanceof SocketException) && !running) {
115 /* Assume that stop() has closed the socket. */
117 logger.log(Level.SEVERE, "SCGI server encountered I/O error", e);
129 } catch(IOException e) {
130 throw(new RuntimeException(e));
134 protected void shutdown() {