Author: markt
Date: Tue Jan 13 15:47:50 2015
New Revision: 1651386

URL: http://svn.apache.org/r1651386
Log:
Switch APR to using non-blocking reads for HTTP request line and headers

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java
    tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java

Modified: tomcat/trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java?rev=1651386&r1=1651385&r2=1651386&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalAprInputBuffer.java Tue 
Jan 13 15:47:50 2015
@@ -16,11 +16,9 @@
  */
 package org.apache.coyote.http11;
 
-import java.io.EOFException;
 import java.io.IOException;
 import java.net.SocketTimeoutException;
 import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
 
@@ -31,7 +29,6 @@ import org.apache.juli.logging.LogFactor
 import org.apache.tomcat.jni.Socket;
 import org.apache.tomcat.jni.Status;
 import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.MessageBytes;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.SocketWrapperBase;
 
@@ -41,7 +38,7 @@ import org.apache.tomcat.util.net.Socket
  *
  * @author <a href="mailto:r...@apache.org";>Remy Maucherat</a>
  */
-public class InternalAprInputBuffer extends AbstractInputBuffer<Long> {
+public class InternalAprInputBuffer extends AbstractNioInputBuffer<Long> {
 
     private static final Log log =
         LogFactory.getLog(InternalAprInputBuffer.class);
@@ -53,11 +50,8 @@ public class InternalAprInputBuffer exte
      * Alternate constructor.
      */
     public InternalAprInputBuffer(Request request, int headerBufferSize) {
+        super(request, headerBufferSize);
 
-        this.request = request;
-        headers = request.getMimeHeaders();
-
-        buf = new byte[headerBufferSize];
         if (headerBufferSize < (8 * 1024)) {
             bbuf = ByteBuffer.allocateDirect(6 * 1500);
         } else {
@@ -65,14 +59,6 @@ public class InternalAprInputBuffer exte
         }
 
         inputStreamInputBuffer = new SocketInputBuffer();
-
-        filterLibrary = new InputFilter[0];
-        activeFilters = new InputFilter[0];
-        lastActiveFilter = -1;
-
-        parsingHeader = true;
-        swallowInput = true;
-
     }
 
 
@@ -108,432 +94,26 @@ public class InternalAprInputBuffer exte
     }
 
 
-    /**
-     * Read the request line. This function is meant to be used during the
-     * HTTP request header parsing. Do NOT attempt to read the request body
-     * using it.
-     *
-     * @throws IOException If an exception occurs during the underlying socket
-     * read operations, or if the given buffer is not big enough to accommodate
-     * the whole line.
-     * @return true if data is properly fed; false if no data is available
-     * immediately and thread should be freed
-     */
-    @Override
-    public boolean parseRequestLine(boolean useAvailableData)
-        throws IOException {
-
-        int start = 0;
-
-        //
-        // Skipping blank lines
-        //
-
-        byte chr = 0;
-        do {
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (useAvailableData) {
-                    return false;
-                }
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-            // Set the start time once we start reading data (even if it is
-            // just skipping blank lines)
-            if (request.getStartTime() < 0) {
-                request.setStartTime(System.currentTimeMillis());
-            }
-            chr = buf[pos++];
-        } while ((chr == Constants.CR) || (chr == Constants.LF));
-
-        pos--;
-
-        // Mark the current buffer position
-        start = pos;
-
-        if (pos >= lastValid) {
-            if (useAvailableData) {
-                return false;
-            }
-            if (!fill(true))
-                throw new EOFException(sm.getString("iib.eof.error"));
-        }
-
-        //
-        // Reading the method name
-        // Method name is always US-ASCII
-        //
-
-        boolean space = false;
-
-        while (!space) {
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-
-            // Spec says no CR or LF in method name
-            if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
-                throw new IllegalArgumentException(
-                        sm.getString("iib.invalidmethod"));
-            }
-            // Spec says single SP but it also says be tolerant of HT
-            if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
-                space = true;
-                request.method().setBytes(buf, start, pos - start);
-            }
-
-            pos++;
-
-        }
-
-        // Spec says single SP but also says be tolerant of multiple and/or HT
-        while (space) {
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-            if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
-                pos++;
-            } else {
-                space = false;
-            }
-        }
-
-        // Mark the current buffer position
-        start = pos;
-        int end = 0;
-        int questionPos = -1;
-
-        //
-        // Reading the URI
-        //
-
-        boolean eol = false;
-
-        while (!space) {
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-
-            // Spec says single SP but it also says be tolerant of HT
-            if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
-                space = true;
-                end = pos;
-            } else if ((buf[pos] == Constants.CR)
-                       || (buf[pos] == Constants.LF)) {
-                // HTTP/0.9 style request
-                eol = true;
-                space = true;
-                end = pos;
-            } else if ((buf[pos] == Constants.QUESTION)
-                       && (questionPos == -1)) {
-                questionPos = pos;
-            }
-
-            pos++;
-
-        }
-
-        if (questionPos >= 0) {
-            request.queryString().setBytes(buf, questionPos + 1,
-                                           end - questionPos - 1);
-            request.requestURI().setBytes(buf, start, questionPos - start);
-        } else {
-            request.requestURI().setBytes(buf, start, end - start);
-        }
-
-        // Spec says single SP but also says be tolerant of multiple and/or HT
-        while (space) {
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-            if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
-                pos++;
-            } else {
-                space = false;
-            }
-        }
-
-
-        // Mark the current buffer position
-        start = pos;
-        end = 0;
-
-        //
-        // Reading the protocol
-        // Protocol is always US-ASCII
-        //
-
-        while (!eol) {
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-
-            if (buf[pos] == Constants.CR) {
-                end = pos;
-            } else if (buf[pos] == Constants.LF) {
-                if (end == 0)
-                    end = pos;
-                eol = true;
-            }
-
-            pos++;
-
-        }
-
-        if ((end - start) > 0) {
-            request.protocol().setBytes(buf, start, end - start);
-        } else {
-            request.protocol().setString("");
-        }
-
-        return true;
-
-    }
-
+    // ------------------------------------------------------ Protected Methods
 
-    /**
-     * Parse the HTTP headers.
-     */
     @Override
-    public boolean parseHeaders()
-        throws IOException {
-        if (!parsingHeader) {
-            throw new IllegalStateException(
-                    sm.getString("iib.parseheaders.ise.error"));
-        }
-
-        while (parseHeader()) {
-            // Loop until there are no more headers
-        }
-
-        parsingHeader = false;
-        end = pos;
-        return true;
-    }
-
-
-    /**
-     * Parse an HTTP header.
-     *
-     * @return false after reading a blank line (which indicates that the
-     * HTTP header parsing is done
-     */
-    @SuppressWarnings("null") // headerValue cannot be null
-    private boolean parseHeader()
-        throws IOException {
-
-        //
-        // Check for blank line
-        //
-
-        byte chr = 0;
-        while (true) {
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-
-            chr = buf[pos];
-
-            if (chr == Constants.CR) {
-                // Skip
-            } else if (chr == Constants.LF) {
-                pos++;
-                return false;
-            } else {
-                break;
-            }
-
-            pos++;
-
-        }
-
-        // Mark the current buffer position
-        int start = pos;
-
-        //
-        // Reading the header name
-        // Header name is always US-ASCII
-        //
-
-        boolean colon = false;
-        MessageBytes headerValue = null;
-
-        while (!colon) {
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-
-            if (buf[pos] == Constants.COLON) {
-                colon = true;
-                headerValue = headers.addValue(buf, start, pos - start);
-            } else if (!HTTP_TOKEN_CHAR[buf[pos]]) {
-                // If a non-token header is detected, skip the line and
-                // ignore the header
-                skipLine(start);
-                return true;
-            }
-            chr = buf[pos];
-            if ((chr >= Constants.A) && (chr <= Constants.Z)) {
-                buf[pos] = (byte) (chr - Constants.LC_OFFSET);
-            }
-
-            pos++;
-
-        }
-
-        // Mark the current buffer position
-        start = pos;
-        int realPos = pos;
-
-        //
-        // Reading the header value (which can be spanned over multiple lines)
-        //
-
-        boolean eol = false;
-        boolean validLine = true;
-
-        while (validLine) {
-
-            boolean space = true;
-
-            // Skipping spaces
-            while (space) {
-
-                // Read new bytes if needed
-                if (pos >= lastValid) {
-                    if (!fill(true))
-                        throw new EOFException(sm.getString("iib.eof.error"));
-                }
-
-                if ((buf[pos] == Constants.SP) || (buf[pos] == Constants.HT)) {
-                    pos++;
-                } else {
-                    space = false;
-                }
-
-            }
-
-            int lastSignificantChar = realPos;
-
-            // Reading bytes until the end of the line
-            while (!eol) {
-
-                // Read new bytes if needed
-                if (pos >= lastValid) {
-                    if (!fill(true))
-                        throw new EOFException(sm.getString("iib.eof.error"));
-                }
-
-                if (buf[pos] == Constants.CR) {
-                    // Skip
-                } else if (buf[pos] == Constants.LF) {
-                    eol = true;
-                } else if (buf[pos] == Constants.SP) {
-                    buf[realPos] = buf[pos];
-                    realPos++;
-                } else {
-                    buf[realPos] = buf[pos];
-                    realPos++;
-                    lastSignificantChar = realPos;
-                }
-
-                pos++;
-
-            }
-
-            realPos = lastSignificantChar;
-
-            // Checking the first character of the new line. If the character
-            // is a LWS, then it's a multiline header
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-
-            chr = buf[pos];
-            if ((chr != Constants.SP) && (chr != Constants.HT)) {
-                validLine = false;
-            } else {
-                eol = false;
-                // Copying one extra space in the buffer (since there must
-                // be at least one space inserted between the lines)
-                buf[realPos] = chr;
-                realPos++;
-            }
-
-        }
-
-        // Set the header value
-        headerValue.setBytes(buf, start, realPos - start);
-
-        return true;
-
-    }
-
-
-    private void skipLine(int start) throws IOException {
-        boolean eol = false;
-        int lastRealByte = start;
-        if (pos - 1 > start) {
-            lastRealByte = pos - 1;
-        }
-
-        while (!eol) {
-
-            // Read new bytes if needed
-            if (pos >= lastValid) {
-                if (!fill(true))
-                    throw new EOFException(sm.getString("iib.eof.error"));
-            }
-
-            if (buf[pos] == Constants.CR) {
-                // Skip
-            } else if (buf[pos] == Constants.LF) {
-                eol = true;
-            } else {
-                lastRealByte = pos;
-            }
-            pos++;
-        }
-
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("iib.invalidheader", new String(buf, start,
-                    lastRealByte - start + 1, StandardCharsets.ISO_8859_1)));
-        }
+    protected final Log getLog() {
+        return log;
     }
 
 
-    // ------------------------------------------------------ Protected Methods
-
     @Override
     protected void init(SocketWrapperBase<Long> socketWrapper,
             AbstractEndpoint<Long> endpoint) throws IOException {
 
         socket = socketWrapper.getSocket().longValue();
         wrapper = socketWrapper;
+
+        int bufLength = headerBufferSize + bbuf.capacity();
+        if (buf == null || buf.length < bufLength) {
+            buf = new byte[bufLength];
+        }
+
         Socket.setrbb(this.socket, bbuf);
     }
 
@@ -594,12 +174,6 @@ public class InternalAprInputBuffer exte
     }
 
 
-    @Override
-    protected final Log getLog() {
-        return log;
-    }
-
-
     private int doReadSocket(boolean block) {
 
         Lock readLock = wrapper.getBlockingStatusReadLock();

Modified: tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java?rev=1651386&r1=1651385&r2=1651386&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java Tue 
Jan 13 15:47:50 2015
@@ -65,12 +65,6 @@ public class InternalNioInputBuffer exte
 
     // --------------------------------------------------------- Public Methods
 
-    @Override
-    protected final Log getLog() {
-        return log;
-    }
-
-
     /**
      * Recycle the input buffer. This should be called when closing the
      * connection.
@@ -84,6 +78,12 @@ public class InternalNioInputBuffer exte
     // ------------------------------------------------------ Protected Methods
 
     @Override
+    protected final Log getLog() {
+        return log;
+    }
+
+
+    @Override
     protected void init(SocketWrapperBase<NioChannel> socketWrapper,
             AbstractEndpoint<NioChannel> endpoint) throws IOException {
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to