X-Git-Url: http://dolda2000.com/gitweb/?p=jsvc.git;a=blobdiff_plain;f=src%2Fdolda%2Fjsvc%2Fscgi%2FServer.java;fp=src%2Fdolda%2Fjsvc%2Fscgi%2FServer.java;h=f01eae9bb738aa9f783ea5f59f69210df4a23f69;hp=0000000000000000000000000000000000000000;hb=13e578b10b388cc0dea88e05b79265c21416e3a0;hpb=b560fc1c45ee31c6d509781b53d5934121990189 diff --git a/src/dolda/jsvc/scgi/Server.java b/src/dolda/jsvc/scgi/Server.java new file mode 100644 index 0000000..f01eae9 --- /dev/null +++ b/src/dolda/jsvc/scgi/Server.java @@ -0,0 +1,111 @@ +package dolda.jsvc.scgi; + +import java.util.logging.*; +import java.io.*; +import java.net.*; +import java.util.*; + +public abstract class Server implements Runnable { + private final ServerSocket sk; + private final Logger logger = Logger.getLogger("dolda.jsvc.scgi"); + public String headcs = "UTF-8"; + + public Server(ServerSocket sk) { + this.sk = sk; + } + + private static int readnslen(InputStream in) throws IOException { + int ret = 0; + while(true) { + int c = in.read(); + if(c == ':') + return(ret); + else if((c >= '0') && (c <= '9')) + ret = (ret * 10) + (c - '0'); + else + throw(new InvalidRequestException("Malformed netstring length")); + } + } + + private static byte[] readns(InputStream in) throws IOException { + byte[] buf = new byte[readnslen(in)]; + int off = 0; + while(off < buf.length) { + int ret = in.read(buf, off, buf.length - off); + if(ret < 0) + throw(new InvalidRequestException("Unexpected EOS in netstring")); + off += ret; + } + if(in.read() != ',') + throw(new InvalidRequestException("Unterminated netstring")); + return(buf); + } + + private Map readhead(InputStream in) throws IOException { + byte[] rawhead = readns(in); + String head = new String(rawhead, headcs); + Map ret = new HashMap(); + int p = 0; + while(true) { + int p2 = head.indexOf(0, p); + if(p2 < 0) { + if(p == head.length()) + return(ret); + throw(new InvalidRequestException("Malformed headers")); + } + String key = head.substring(p, p2); + int p3 = head.indexOf(0, p2 + 1); + if(p3 < 0) + throw(new InvalidRequestException("Malformed headers")); + String val = head.substring(p2 + 1, p3); + ret.put(key, val); + p = p3 + 1; + } + } + + private boolean checkhead(Map head) { + if(!head.containsKey("SCGI") || !head.get("SCGI").equals("1")) + return(false); + return(true); + } + + protected abstract void handle(Map head, Socket sk) throws Exception; + + private void serve(Socket sk) { + try { + try { + InputStream in = sk.getInputStream(); + Map head = readhead(in); + if(!checkhead(head)) + return; + try { + handle(head, sk); + } catch(Exception e) { + logger.log(Level.WARNING, "Could not handle request", e); + return; + } + sk = null; + } finally { + if(sk != null) + sk.close(); + } + } catch(IOException e) { + logger.log(Level.WARNING, "I/O error encountered while serving SCGI request", e); + } + } + + public void run() { + try { + try { + while(true) { + Socket nsk = sk.accept(); + serve(nsk); + } + } finally { + sk.close(); + } + } catch(IOException e) { + logger.log(Level.SEVERE, "SCGI server encountered I/O error", e); + } + } +}