870 lines · 31.4 KB · Java
RawDownload
                } else {                    /* figure out what kind of connection this is */                    newconnection = true;                    if (https) {                        if (sslContext == null) {                            logger.warning ("SSL connection received. No https contxt created");                            throw new HttpError ("No SSL context established");                        }                        sslStreams = new SSLStreams (ServerImpl.this, sslContext, chan);                        rawin = sslStreams.getInputStream();                        rawout = sslStreams.getOutputStream();                        engine = sslStreams.getSSLEngine();                        connection.sslStreams = sslStreams;                    } else {                        rawin = new BufferedInputStream(                            new Request.ReadStream (                                ServerImpl.this, chan                        ));                        rawout = new Request.WriteStream (                            ServerImpl.this, chan                        );                    }                    connection.raw = rawin;                    connection.rawout = rawout;                }                Request req = new Request (rawin, rawout);                requestLine = req.requestLine();                if (requestLine == null) {                    /* connection closed */                    closeConnection(connection);                    return;                }                int space = requestLine.indexOf (' ');                if (space == -1) {                    reject (Code.HTTP_BAD_REQUEST,                            requestLine, "Bad request line");                    return;                }                String method = requestLine.substring (0, space);                int start = space+1;                space = requestLine.indexOf(' ', start);                if (space == -1) {                    reject (Code.HTTP_BAD_REQUEST,                            requestLine, "Bad request line");                    return;                }                String uriStr = requestLine.substring (start, space);                URI uri = new URI (uriStr);                start = space+1;                String version = requestLine.substring (start);                Headers headers = req.headers();                String s = headers.getFirst ("Transfer-encoding");                long clen = 0L;                if (s !=null && s.equalsIgnoreCase ("chunked")) {                    clen = -1L;                } else {                    s = headers.getFirst ("Content-Length");                    if (s != null) {                        clen = Long.parseLong(s);                    }                    if (clen == 0) {                        requestCompleted (connection);                    }                }                ctx = contexts.findContext (protocol, uri.getPath());                if (ctx == null) {                    reject (Code.HTTP_NOT_FOUND,                            requestLine, "No context found for request");                    return;                }                connection.setContext (ctx);                if (ctx.getHandler() == null) {                    reject (Code.HTTP_INTERNAL_ERROR,                            requestLine, "No handler for context");                    return;                }                tx = new ExchangeImpl (                    method, uri, req, clen, connection                );                String chdr = headers.getFirst("Connection");                Headers rheaders = tx.getResponseHeaders();                 if (chdr != null && chdr.equalsIgnoreCase ("close")) {                    tx.close = true;                }                if (version.equalsIgnoreCase ("http/1.0")) {                    tx.http10 = true;                    if (chdr == null) {                        tx.close = true;                        rheaders.set ("Connection", "close");                    } else if (chdr.equalsIgnoreCase ("keep-alive")) {                        rheaders.set ("Connection", "keep-alive");                        int idle=(int)ServerConfig.getIdleInterval()/1000;                        int max=(int)ServerConfig.getMaxIdleConnections();                        String val = "timeout="+idle+", max="+max;                        rheaders.set ("Keep-Alive", val);                    }                }                 if (newconnection) {                    connection.setParameters (                        rawin, rawout, chan, engine, sslStreams,                        sslContext, protocol, ctx, rawin                    );                }                /* check if client sent an Expect 100 Continue.                 * In that case, need to send an interim response.                 * In future API may be modified to allow app to                 * be involved in this process.                 */                String exp = headers.getFirst("Expect");                if (exp != null && exp.equalsIgnoreCase ("100-continue")) {                    logReply (100, requestLine, null);                    sendReply (                        Code.HTTP_CONTINUE, false, null                    );                }                /* uf is the list of filters seen/set by the user.                 * sf is the list of filters established internally                 * and which are not visible to the user. uc and sc                 * are the corresponding Filter.Chains.                 * They are linked together by a LinkHandler                 * so that they can both be invoked in one call.                 */                List<Filter> sf = ctx.getSystemFilters();                List<Filter> uf = ctx.getFilters();                 Filter.Chain sc = new Filter.Chain(sf, ctx.getHandler());                Filter.Chain uc = new Filter.Chain(uf, new LinkHandler (sc));                 /* set up the two stream references */                tx.getRequestBody();                tx.getResponseBody();                if (https) {                    uc.doFilter (new HttpsExchangeImpl (tx));                } else {                    uc.doFilter (new HttpExchangeImpl (tx));                }             } catch (IOException e1) {                logger.log (Level.FINER, "ServerImpl.Exchange (1)", e1);                closeConnection(connection);            } catch (NumberFormatException e3) {                reject (Code.HTTP_BAD_REQUEST,                        requestLine, "NumberFormatException thrown");            } catch (URISyntaxException e) {                reject (Code.HTTP_BAD_REQUEST,                        requestLine, "URISyntaxException thrown");            } catch (Exception e4) {                logger.log (Level.FINER, "ServerImpl.Exchange (2)", e4);                closeConnection(connection);            }        }         /* used to link to 2 or more Filter.Chains together */         class LinkHandler implements HttpHandler {            Filter.Chain nextChain;             LinkHandler (Filter.Chain nextChain) {                this.nextChain = nextChain;            }             public void handle (HttpExchange exchange) throws IOException {                nextChain.doFilter (exchange);            }        }         void reject (int code, String requestStr, String message) {            rejected = true;            logReply (code, requestStr, message);            sendReply (                code, false, "<h1>"+code+Code.msg(code)+"</h1>"+message            );            closeConnection(connection);        }         void sendReply (            int code, boolean closeNow, String text)        {            try {                StringBuilder builder = new StringBuilder (512);                builder.append ("HTTP/1.1 ")                    .append (code).append (Code.msg(code)).append ("\r\n");                 if (text != null && text.length() != 0) {                    builder.append ("Content-Length: ")                        .append (text.length()).append ("\r\n")                        .append ("Content-Type: text/html\r\n");                } else {                    builder.append ("Content-Length: 0\r\n");                    text = "";                }                if (closeNow) {                    builder.append ("Connection: close\r\n");                }                builder.append ("\r\n").append (text);                String s = builder.toString();                byte[] b = s.getBytes("ISO8859_1");                rawout.write (b);                rawout.flush();                if (closeNow) {                    closeConnection(connection);                }            } catch (IOException e) {                logger.log (Level.FINER, "ServerImpl.sendReply", e);                closeConnection(connection);            }        }     }     void logReply (int code, String requestStr, String text) {        if (!logger.isLoggable(Level.FINE)) {            return;        }        if (text == null) {            text = "";        }        String r;        if (requestStr.length() > 80) {           r = requestStr.substring (0, 80) + "<TRUNCATED>";        } else {           r = requestStr;        }        String message = r + " [" + code + " " +                    Code.msg(code) + "] ("+text+")";        logger.fine (message);    }     long getTicks() {        return ticks;    }     public long getTime() {        return time;    }     void delay () {        Thread.yield();        try {            Thread.sleep (200);        } catch (InterruptedException e) {}    }     private int exchangeCount = 0;     synchronized void startExchange () {        exchangeCount ++;    }     synchronized int endExchange () {        exchangeCount --;        assert exchangeCount >= 0;        return exchangeCount;    }     HttpServer getWrapper () {        return wrapper;    }     void requestStarted (HttpConnection c) {        c.creationTime = getTime();        c.setState (State.REQUEST);        reqConnections.add (c);    }     // called after a request has been completely read    // by the server. This stops the timer which would    // close the connection if the request doesn't arrive    // quickly enough. It then starts the timer    // that ensures the client reads the response in a timely    // fashion.     void requestCompleted (HttpConnection c) {        assert c.getState() == State.REQUEST;        reqConnections.remove (c);        c.rspStartedTime = getTime();        rspConnections.add (c);        c.setState (State.RESPONSE);    }     // called after response has been sent    void responseCompleted (HttpConnection c) {        assert c.getState() == State.RESPONSE;        rspConnections.remove (c);        c.setState (State.IDLE);    }     /**     * TimerTask run every CLOCK_TICK ms     */    class ServerTimerTask extends TimerTask {        public void run () {            LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();            time = System.currentTimeMillis();            ticks ++;            synchronized (idleConnections) {                for (HttpConnection c : idleConnections) {                    if (c.time <= time) {                        toClose.add (c);                    }                }                for (HttpConnection c : toClose) {                    idleConnections.remove (c);                    allConnections.remove (c);                    c.close();                }            }        }    }     class ServerTimerTask1 extends TimerTask {         // runs every TIMER_MILLIS        public void run () {            LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();            time = System.currentTimeMillis();            synchronized (reqConnections) {                if (MAX_REQ_TIME != -1) {                    for (HttpConnection c : reqConnections) {                        if (c.creationTime + TIMER_MILLIS + MAX_REQ_TIME <= time) {                            toClose.add (c);                        }                    }                    for (HttpConnection c : toClose) {                        logger.log (Level.FINE, "closing: no request: " + c);                        reqConnections.remove (c);                        allConnections.remove (c);                        c.close();                    }                }            }            toClose = new LinkedList<HttpConnection>();            synchronized (rspConnections) {                if (MAX_RSP_TIME != -1) {                    for (HttpConnection c : rspConnections) {                        if (c.rspStartedTime + TIMER_MILLIS +MAX_RSP_TIME <= time) {                            toClose.add (c);                        }                    }                    for (HttpConnection c : toClose) {                        logger.log (Level.FINE, "closing: no response: " + c);                        rspConnections.remove (c);                        allConnections.remove (c);                        c.close();                    }                }            }        }    }     void logStackTrace (String s) {        logger.finest (s);        StringBuilder b = new StringBuilder ();        StackTraceElement[] e = Thread.currentThread().getStackTrace();        for (int i=0; i<e.length; i++) {            b.append (e[i].toString()).append("\n");        }        logger.finest (b.toString());    }     static long getTimeMillis(long secs) {        if (secs == -1) {            return -1;        } else {            return secs * 1000;        }    }}

Lines 501–870 of 870. Previous lines