hgomez      01/09/14 09:01:21

  Modified:    src/share/org/apache/tomcat/modules/server Ajp13.java
  Log:
  Solid reworks to better handle comm part.
  We don't try to handle partial packet, use
  of readN to ensure having all data in packets
  (even in header which is 4 bytes long)
  
  Revision  Changes    Path
  1.26      +88 -20    
jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13.java
  
  Index: Ajp13.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- Ajp13.java        2001/09/12 21:35:46     1.25
  +++ Ajp13.java        2001/09/14 16:01:21     1.26
  @@ -107,6 +107,14 @@
       public static final byte JK_AJP13_FORWARD_REQUEST   = 2;
       public static final byte JK_AJP13_SHUTDOWN          = 7;
        
  +    // Error code for Ajp13
  +    public static final int  JK_AJP13_BAD_HEADER        = -100;
  +    public static final int  JK_AJP13_NO_HEADER         = -101;
  +    public static final int  JK_AJP13_COMM_CLOSED       = -102;
  +    public static final int  JK_AJP13_COMM_BROKEN       = -103;
  +    public static final int  JK_AJP13_BAD_BODY          = -104;
  +    public static final int  JK_AJP13_INCOMPLETE_BODY   = -105;
  +
       // Prefix codes for message types from container to server
       public static final byte JK_AJP13_SEND_BODY_CHUNK   = 3;
       public static final byte JK_AJP13_SEND_HEADERS      = 4;
  @@ -186,13 +194,14 @@
   
       OutputStream out;
       InputStream in;
  +    int dL=0;
   
       // Buffer used of output body and headers
       OutputBuffer headersWriter=new OutputBuffer(MAX_PACKET_SIZE);
       Ajp13Packet outBuf = new Ajp13Packet( headersWriter );
       // Buffer used for input body
       Ajp13Packet inBuf  = new Ajp13Packet( MAX_PACKET_SIZE );
  -    // Boffer used for request head ( and headers )
  +    // Buffer used for request head ( and headers )
       Ajp13Packet hBuf=new Ajp13Packet( MAX_PACKET_SIZE );
   
       // Holds incoming reads of request body data (*not* header data)
  @@ -254,9 +263,10 @@
        // XXX The return values are awful.
   
        int err = receive(hBuf);
  -     if(err < 0) {
  +
  +    // if any error, just drop the ajp13 connection
  +     if (err < 0) 
            return 500;
  -     }
        
        int type = (int)hBuf.getByte();
        switch(type) {
  @@ -674,6 +684,47 @@
       // ========= Internal Packet-Handling Methods =================
   
       /**
  +     * Read N bytes from the InputStream, and ensure we got them all
  +     * Under heavy load we could experience many fragmented packets
  +     * just read Unix Network Programming to recall that a call to
  +     * read didn't ensure you got all the data you want
  +     *
  +     * from read() Linux manual
  +     *
  +     * On success, the number of bytes read is returned (zero indicates end of 
file), 
  +     * and the file position is advanced by this number.
  +     * It is not an error if this number is smaller than the number of bytes 
requested; 
  +     * this may happen for example because fewer bytes
  +     * are actually available right now (maybe because we were close to 
end-of-file, 
  +     * or because we are reading from a pipe, or  from  a
  +     * terminal),  or  because  read()  was interrupted by a signal.  
  +     * On error, -1 is returned, and errno is set appropriately. In this
  +     * case it is left unspecified whether the file position (if any) changes.
  +     *
  +     **/
  +    private int readN(InputStream in, byte[] b, int offset, int len) throws 
IOException {
  +        int pos = 0;
  +        int got;
  +
  +        while(pos < len) {
  +            got = in.read(b, pos + offset, len - pos);
  +
  +            if (dL > 10) d("read got # " + got);
  +
  +            // connection just closed by remote
  +            if (got == 0)
  +                return JK_AJP13_COMM_CLOSED;
  +
  +            // connection dropped by remote
  +            if (got < 0)
  +                return JK_AJP13_COMM_BROKEN;
  +
  +            pos += got;
  +        }
  +        return pos;
  +     }
  +       
  +    /**
        * Read in a packet from the web server and store it in the passed-in
        * <CODE>Ajp13Packet</CODE> object.
        *
  @@ -690,26 +741,40 @@
        // returned -- should probably return true/false instead.
        byte b[] = msg.getBuff();
        
  -     int rd = in.read( b, 0, H_SIZE );
  -     if(rd <= 0) {
  -         return rd;
  -     }
  -     
  +     int rd = readN(in, b, 0, H_SIZE );
  +
  +    // XXX - connection closed (JK_AJP13_COMM_CLOSED)
  +    //     - connection broken (JK_AJP13_COMM_BROKEN)
  +    //
  +    if(rd < 0) {
  +        // if (rd != JK_AJP13_COMM_CLOSED)
  +        //    d("can't read header: " + rd);
  +         return rd;
  +    }
  +        
        int len = msg.checkIn();
  -     
  +
  +    // XXX - check if we received a non AJP13 packet
  +    if (len < 0) {
  +        return JK_AJP13_BAD_HEADER;
  +    }
  +
        // XXX check if enough space - it's assert()-ed !!!
   
        int total_read = 0;
  -     while (total_read < len) {
  -         rd = in.read( b, 4 + total_read, len - total_read);
  -            if (rd == -1) {
  -             System.out.println( "Incomplete read, deal with it " + len + " " + rd);
  -                break;
  -             // XXX log
  -             // XXX Return an error code?
  -         }
  -                 total_read += rd;
  -     }
  + 
  +    total_read = readN(in, b, H_SIZE, len);
  +
  +    if (total_read < 0) {
  +        d("can't read body, waited #" + len);
  +        return JK_AJP13_BAD_BODY;
  +    }
  +
  +    if (total_read != len) {
  +        d( "incomplete read, waited #" + len + " got only " + total_read);
  +        return JK_AJP13_INCOMPLETE_BODY; 
  +    }
  +
        if( dL>0 ) msg.dump("Ajp13.receive() " + rd + " " + len );
        return total_read;
       }
  @@ -743,8 +808,11 @@
            in.close();
        }
       }
  +
  +    public void setDebug(int i) {
  +        dL = i;
  +    }
   
  -    private static final int dL=0;
       private void d(String s ) {
        System.err.println( "Ajp13: " + s );
       }
  
  
  

Reply via email to