remm        01/12/09 14:10:47

  Modified:    http11/src/java/org/apache/coyote/http11 Constants.java
                        Http11Connector.java InternalOutputBuffer.java
               http11/src/java/org/apache/coyote/http11/filters
                        IdentityInputFilter.java
  Log:
  - Request parsing.
  - The initial code is toString() happy. This can be optimized, but it is unclear at
    the moment if this would have a very significant impact on performance (as there
    are only a few String creations).
  - The connector is almost at the stage where it will be testable.
  
  Revision  Changes    Path
  1.3       +24 -0     
jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Constants.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Constants.java    2001/10/01 01:20:42     1.2
  +++ Constants.java    2001/12/09 22:10:47     1.3
  @@ -143,4 +143,28 @@
       public static final String CRLF = "\r\n";
   
   
  +    /**
  +     * Indetity filters (input and output).
  +     */
  +    public static final int IDENTITY_FILTER = 0;
  +
  +
  +    /**
  +     * Chunked filters (input and output).
  +     */
  +    public static final int CHUNKED_FILTER = 1;
  +
  +
  +    /**
  +     * HTTP/1.0.
  +     */
  +    public static final String HTTP_10 = "HTTP/1.0";
  +
  +
  +    /**
  +     * HTTP/1.1.
  +     */
  +    public static final String HTTP_11 = "HTTP/1.1";
  +
  +
   }
  
  
  
  1.4       +259 -10   
jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Connector.java
  
  Index: Http11Connector.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Connector.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Http11Connector.java      2001/12/03 06:09:30     1.3
  +++ Http11Connector.java      2001/12/09 22:10:47     1.4
  @@ -77,7 +77,11 @@
   import org.apache.coyote.Request;
   import org.apache.coyote.Response;
   
  +import org.apache.coyote.http11.filters.IdentityInputFilter;
  +import org.apache.coyote.http11.filters.IdentityOutputFilter;
  +import org.apache.coyote.http11.filters.VoidOutputFilter;
   
  +
   /**
    * Processes HTTP requests.
    * 
  @@ -103,6 +107,8 @@
           outputBuffer = new InternalOutputBuffer(response);
           response.setOutputBuffer(outputBuffer);
   
  +        initializeFilters();
  +
       }
   
   
  @@ -139,10 +145,93 @@
       protected InternalOutputBuffer outputBuffer = null;
   
   
  +    /**
  +     * Error flag.
  +     */
  +    protected boolean error = false;
  +
  +
  +    /**
  +     * Keep-alive.
  +     */
  +    protected boolean keepAlive = true;
  +
  +
  +    /**
  +     * Content delimitator for the request (if false, the connection will
  +     * be closed at the end of the request).
  +     */
  +    protected boolean contentDelimitation = true;
  +
  +
  +    /**
  +     * List of restricted user agents.
  +     */
  +    protected String[] restrictedUserAgents = null;
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
       /**
  +     * Add input or output filter.
  +     * 
  +     * @param className class name of the filter
  +     */
  +    public void addFilter(String className) {
  +        try {
  +            Class clazz = Class.forName(className);
  +            Object obj = clazz.newInstance();
  +            if (obj instanceof InputFilter) {
  +                inputBuffer.addFilter((InputFilter) obj);
  +            } else if (obj instanceof OutputFilter) {
  +                outputBuffer.addFilter((OutputFilter) obj);
  +            } else {
  +                // Not a valid filter: log and ignore
  +            }
  +        } catch (Exception e) {
  +            // Log and ignore
  +        }
  +    }
  +
  +
  +    /**
  +     * Add restricted user-agent (which will downgrade the connector 
  +     * to HTTP/1.0 mode). The user agent String given will be exactly matched
  +     * to the user-agent header submitted by the client.
  +     * 
  +     * @param userAgent user-agent string
  +     */
  +    public void addRestrictedUserAgent(String userAgent) {
  +        if (restrictedUserAgents == null)
  +            restrictedUserAgents = new String[0];
  +        String[] results = new String[restrictedUserAgents.length + 1];
  +        for (int i = 0; i < restrictedUserAgents.length; i++)
  +            results[i] = restrictedUserAgents[i];
  +        results[restrictedUserAgents.length] = userAgent;
  +        restrictedUserAgents = results;
  +    }
  +
  +
  +    /**
  +     * Set restricted user agent list (this method is best when used with 
  +     * a large number of connectors, where it would be better to have all of 
  +     * them referenced a single array).
  +     */
  +    public void setRestrictedUserAgents(String[] restrictedUserAgents) {
  +        this.restrictedUserAgents = restrictedUserAgents;
  +    }
  +
  +
  +    /**
  +     * Return the list of restricted user agents.
  +     */
  +    public String[] findRestrictedUserAgents() {
  +        return (restrictedUserAgents);
  +    }
  +
  +
  +    /**
        * Process pipelined HTTP requests using the specified input and output
        * streams.
        * 
  @@ -158,12 +247,13 @@
           inputBuffer.setInputStream(input);
           outputBuffer.setOutputStream(output);
   
  -        // Ok flag
  -        boolean ok = true;
  +        // Error flag
  +        error = false;
  +        keepAlive = true;
           // TEMP
           boolean stopped = false;
   
  -        while (!stopped && ok) {
  +        while (!stopped && !error && keepAlive) {
   
               try {
                   inputBuffer.parseRequestLine();
  @@ -171,13 +261,14 @@
                   
                   inputBuffer.parseHeaders();
               } catch (EOFException e) {
  -                ok = false;
  +                error = true;
  +                break;
               } catch (InterruptedIOException e) {
                   //HttpServletResponse.SC_BAD_REQUEST
  -                ok = false;
  +                error = true;
               } catch (Exception e) {
                   //SC_BAD_REQUEST
  -                ok = false;
  +                error = true;
               }
   
               // Setting up filters, and parse some request headers
  @@ -187,20 +278,20 @@
               try {
                   adapter.service(request, response);
               } catch (InterruptedIOException e) {
  -                ok = false;
  +                error = true;
               } catch (Throwable t) {
                   // ISE
  -                ok = false;
  +                error = true;
               }
   
               // Finish the handling of the request
               try {
                   outputBuffer.endRequest();
               } catch (IOException e) {
  -                ok = false;
  +                error = true;
               } catch (Throwable t) {
                   // Problem ...
  -                ok = false;
  +                error = true;
               }
   
               // FIXME: Next request
  @@ -229,6 +320,12 @@
   
               // Validate and write response headers
               prepareResponse();
  +            try {
  +                outputBuffer.commit();
  +            } catch (IOException e) {
  +                // Log the error, and set error flag
  +                error = true;
  +            }
   
           } else if (actionCode == ActionCode.ACTION_ACK) {
   
  @@ -244,6 +341,13 @@
               // End the processing of the current request, and stop any further
               // transactions with the client
   
  +            try {
  +                outputBuffer.endRequest();
  +            } catch (IOException e) {
  +                // Log the error, and set error flag
  +                error = true;
  +            }
  +
           } else if (actionCode == ActionCode.ACTION_RESET) {
   
               // Reset response
  @@ -290,8 +394,99 @@
        */
       protected void prepareRequest() {
   
  +        boolean http11 = true;
  +        contentDelimitation = false;
  +
  +        MessageBytes protocol = request.protocol();
  +        if (protocol.equals(Constants.HTTP_11)) {
  +            http11 = true;
  +        } else if (protocol.equals(Constants.HTTP_10)) {
  +            http11 = false;
  +            keepAlive = false;
  +        } else {
  +            // Unsupported protocol
  +            error = true;
  +            // FIXME: Find right status code
  +        }
  +
  +        // Check connection header
  +        MessageBytes connectionValueMB = 
  +            request.getMimeHeaders().getValue("connection");
  +        String connectionValue = 
  +            connectionValueMB.toString().toLowerCase().trim();
  +        // FIXME: This can be a comma separated list
  +        if (connectionValue.equals("close")) {
  +            keepAlive = false;
  +        } else if (connectionValue.equals("keep-alive")) {
  +            keepAlive = true;
  +        }
  +
  +        // Check user-agent header
  +        MessageBytes userAgentValueMB =  
  +            request.getMimeHeaders().getValue("user-agent");
  +        // Check in the restricted list, and adjust the http11 
  +        // and keepAlive flags accordingly
  +        if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) {
  +            String userAgentValue = userAgentValueMB.toString();
  +            for (int i = 0; i < restrictedUserAgents.length; i++) {
  +                if (restrictedUserAgents[i].equals(userAgentValue)) {
  +                    http11 = false;
  +                    keepAlive = false;
  +                }
  +            }
  +        }
  +
  +        InputFilter[] inputFilters = inputBuffer.getFilters();
  +
  +        // Parse content-length header
  +        int contentLength = request.getContentLength();
  +        if (contentLength != -1) {
  +            inputBuffer.addActiveFilter
  +                (inputFilters[Constants.IDENTITY_FILTER]);
  +            contentDelimitation = true;
  +        }
   
  +        // Parse transfer-encoding header
  +        MessageBytes transferEncodingValueMB = null;
  +        if (http11)
  +            transferEncodingValueMB = 
  +                request.getMimeHeaders().getValue("transfer-encoding");
  +        if (transferEncodingValueMB != null) {
  +            String transferEncodingValue = transferEncodingValueMB.toString();
  +            // Parse the comma separated list. "identity" codings are ignored
  +            int startPos = 0;
  +            int commaPos = transferEncodingValue.indexOf(',');
  +            String encodingName = null;
  +            while (commaPos != -1) {
  +                encodingName = transferEncodingValue.substring
  +                    (startPos, commaPos).toLowerCase().trim();
  +                if (!addInputFilter(inputFilters, encodingName)) {
  +                    // Unsupported transfer encoding
  +                    error = true;
  +                    // FIXME: Find right status code
  +                }
  +                startPos = commaPos + 1;
  +                commaPos = transferEncodingValue.indexOf(',', startPos);
  +            }
  +            encodingName = transferEncodingValue.substring(startPos)
  +                .toLowerCase().trim();
  +            if (!addInputFilter(inputFilters, encodingName)) {
  +                // Unsupported transfer encoding
  +                error = true;
  +                // FIXME: Find right status code
  +            }
  +        }
  +
  +        // Check host header
  +        if (http11 && (request.getMimeHeaders().getValue("host") == null)) {
  +            error = true;
  +            // Send 400: Bad request
  +            response.setStatus(400);
  +        }
   
  +        if (!contentDelimitation)
  +            keepAlive = false;
  +
       }
   
   
  @@ -301,8 +496,62 @@
        */
       protected void prepareResponse() {
   
  +        contentDelimitation = false;
  +
  +
  +
  +        if (!contentDelimitation) {
  +            // Mark as close the connection after the request, and add the 
  +            // connection: close header
  +            keepAlive = false;
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Initialize standard input and output filters.
  +     */
  +    protected void initializeFilters() {
   
  +        // Create and add the identity filters.
  +        inputBuffer.addFilter(new IdentityInputFilter());
  +        outputBuffer.addFilter(new IdentityOutputFilter());
   
  +        // Create and add the chunked filters.
  +        // FIXME
  +
  +        // Create and add the void filter.
  +        outputBuffer.addFilter(new VoidOutputFilter());
  +
  +    }
  +
  +
  +    /**
  +     * Add an input filter to the current request.
  +     * 
  +     * @return false if the encoding was not found (which would mean it is 
  +     * unsupported)
  +     */
  +    protected boolean addInputFilter(InputFilter[] inputFilters, 
  +                                     String encodingName) {
  +        if (encodingName.equals("identity")) {
  +            // Skip
  +        } else if (encodingName.equals("chunked")) {
  +            inputBuffer.addActiveFilter
  +                (inputFilters[Constants.CHUNKED_FILTER]);
  +            contentDelimitation = true;
  +        } else {
  +            for (int i = 2; i < inputFilters.length; i++) {
  +                if (inputFilters[i].getEncodingName()
  +                    .toString().equals(encodingName)) {
  +                    inputBuffer.addActiveFilter(inputFilters[i]);
  +                    return true;
  +                }
  +            }
  +            return false;
  +        }
  +        return true;
       }
   
   
  
  
  
  1.5       +0 -4      
jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/InternalOutputBuffer.java
  
  Index: InternalOutputBuffer.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/InternalOutputBuffer.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- InternalOutputBuffer.java 2001/12/04 06:33:06     1.4
  +++ InternalOutputBuffer.java 2001/12/09 22:10:47     1.5
  @@ -341,8 +341,6 @@
               // set the filters accordingly.
               response.action(ActionCode.ACTION_COMMIT, null);
   
  -            commit();
  -
           }
   
           for (int i = lastActiveFilter; i >= 0; i--) {
  @@ -465,8 +463,6 @@
               // then validate the headers, send them (using sendHeaders) and 
               // set the filters accordingly.
               response.action(ActionCode.ACTION_COMMIT, null);
  -
  -            commit();
   
           }
   
  
  
  
  1.5       +1 -1      
jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters/IdentityInputFilter.java
  
  Index: IdentityInputFilter.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters/IdentityInputFilter.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- IdentityInputFilter.java  2001/12/06 06:46:46     1.4
  +++ IdentityInputFilter.java  2001/12/09 22:10:47     1.5
  @@ -72,7 +72,7 @@
    * 
    * @author Remy Maucherat
    */
  -public class IdentityInputFilter implements InputBuffer {
  +public class IdentityInputFilter implements InputFilter {
   
   
       // -------------------------------------------------------------- Constants
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to