/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.ajp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import org.apache.tomcat.util.http.BaseRequest;
import org.apache.tomcat.util.http.HttpMessages;
import org.apache.tomcat.util.http.MimeHeaders;

/**
 * Represents a single, persistent connection between the web server and
 * the servlet container.  Uses the Apache JServ Protocol version 1.3 for
 * communication.  Because this protocal does not multiplex requests, this
 * connection can only be associated with a single request-handling cycle
 * at a time.<P>
 *
 * This class contains knowledge about how an individual packet is laid out
 * (via the <CODE>Ajp13Packet</CODE> class), and also about the
 * stages of communicaton between the server and the servlet container.  It
 * translates from Tomcat's internal servlet support methods
 * (e.g. doWrite) to the correct packets to send to the web server.
 *
 * @author Dan Milstein [danmil@shore.net]
 * @author Keith Wannamaker [Keith@Wannamaker.org]
 * @author Kevin Seguin [seguin@apache.org]
 * @author Henri Gomez [hgomez@apache.org]
 * @author Costin Manolache
 */
public class Ajp13 {

    public static final int MAX_PACKET_SIZE=8192;
    public static final int H_SIZE=4;  // Size of basic packet header

    public static final int  MAX_READ_SIZE = MAX_PACKET_SIZE - H_SIZE - 2;
    public static final int  MAX_SEND_SIZE = MAX_PACKET_SIZE - H_SIZE - 4;

    // 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;

    // ============ Instance Properties ====================

    OutputStream out;
    InputStream in;

    // Buffer used of output body and headers
    public Ajp13Packet outBuf = new Ajp13Packet( MAX_PACKET_SIZE );
    // Buffer used for input body
    Ajp13Packet inBuf  = new Ajp13Packet( MAX_PACKET_SIZE );
    // Buffer used for request head ( and headers )
    Ajp13Packet hBuf=new Ajp13Packet( MAX_PACKET_SIZE );

    // Holds incoming reads of request body data (*not* header data)
    byte []bodyBuff = new byte[MAX_READ_SIZE];
    
    int blen;  // Length of current chunk of body data in buffer
    int pos;   // Current read position within that buffer

    boolean end_of_stream;  // true if we've received an empty packet
    
    // Required handler - essential request processing
    public RequestHandler reqHandler;
    // AJP14 - detect protocol,set communication parameters, login
    // If no password is set, use only Ajp13 messaging
    boolean backwardCompat=true;
    boolean logged=false;
    String secret=null;
    
    public Ajp13() {
	super();
	initBuf();
        reqHandler=new RequestHandler();
	reqHandler.init( this );
    }

    public Ajp13(RequestHandler reqHandler ) {
	super();
	initBuf();
        this.reqHandler=reqHandler;
	reqHandler.init( this );
    }

    /** Will be overriden
     */
    public void initBuf() {
	outBuf = new Ajp13Packet( MAX_PACKET_SIZE );
	inBuf  = new Ajp13Packet( MAX_PACKET_SIZE );
	hBuf=new Ajp13Packet( MAX_PACKET_SIZE );
    }
    
    public void recycle() {
        if (debug > 0) {
            logger.log("recycle()");
        }

        // This is a touch cargo-cultish, but I think wise.
        blen = 0; 
        pos = 0;
        end_of_stream = false;
        logged=false;
    }
    
    /**
     * Associate an open socket with this instance.
     */
    public void setSocket( Socket socket ) throws IOException {
        if (debug > 0) {
            logger.log("setSocket()");
        }
        
	socket.setSoLinger( true, 100);
	out = socket.getOutputStream();
	in  = socket.getInputStream();
	pos = 0;
    }

    /**
     * Backward compat mode, no login  needed
     */
    public void setBackward(boolean b) 
    {
        backwardCompat=b;
    }

    public boolean isLogged() {
	return logged;
    }

    void setLogged( boolean b ) {
        logged=b;
    }

    public void setSecret( String s ) {
        secret=s;
    }

    public String getSecret() {
        return secret;
    }
    
    // -------------------- Handlers registry --------------------

    static final int MAX_HANDLERS=32;
    static final int RESERVED=16;  // reserved names, backward compat

    // Note that we don't make distinction between in and out
    // messages ( i.e. one id is used only in one direction )
    AjpHandler handlers[]=new AjpHandler[MAX_HANDLERS];
    String handlerName[]=new String[MAX_HANDLERS];
    int currentId=RESERVED;

    public int registerMessageType( int id, String name, AjpHandler h,
				    String sig[] )
    {
	if( id < 0 ) {
	    // try to find it by name
	    for( int i=0; i< handlerName.length; i++ )
		if( name.equals( handlerName[i] ) ) return i;
	    handlerName[currentId]=name;
	    handlers[currentId]=h;
	    currentId++;
	    return currentId;
	}
	// fixed id
	handlerName[id]=name;
	handlers[id]=h;
	return id;
    }
    
    // -------------------- Main dispatch --------------------
    
    /**
     * Read a new packet from the web server and decode it.  If it's a
     * forwarded request, store its properties in the passed-in AjpRequest
     * object.
     *
     * @param req An empty (newly-recycled) request object.
     * 
     * @return 200 in case of a successful read of a forwarded request, 500
     * if there were errors in the reading of the request, and -2 if the
     * server is asking the container to shut itself down.  
     */
    public int receiveNextRequest(BaseRequest req) throws IOException {
        if (debug > 0) {
            logger.log("receiveNextRequest()");
        }
        
        // XXX The return values are awful.

        int err = 0;

        // if we receive an IOException here, it must be because
        // the remote just closed the ajp13 connection, and it's not
        // an error, we just need to close the AJP13 connection
        try {
            err = receive(hBuf);
        } catch (IOException ioe) {
            if(debug >0 ) logger.log( "IOException receiving message ");
            return -1;  // Indicate it's a disconnection from the remote end
        }
        
	if(err < 0) {
	    if(debug >0 ) logger.log( "Error receiving message ");
	    return 500;
	}
	
	int type = (int)hBuf.getByte();
        //        System.out.println("XXX " + this );
        return handleMessage( type, hBuf, req );
    }

    /** Override for ajp14, temporary
     */
    public int handleMessage( int type, Ajp13Packet hBuf, BaseRequest req )
        throws IOException
    {
        if( type > handlers.length ) {
	    logger.log( "Invalid handler " + type );
	    return 500;
	}

        if( debug > 0 )
            logger.log( "Received " + type + " " + handlerName[type]);
        
        // Ajp14, unlogged
	if( ! backwardCompat && ! isLogged() ) {
	    if( type != NegociationHandler.JK_AJP14_LOGINIT_CMD &&
		type != NegociationHandler.JK_AJP14_LOGCOMP_CMD ) {

                logger.log( "Ajp14 error: not logged " +
                            type + " " + handlerName[type]);

		return 300;
	    }
	    // else continue
	}

        // Ajp13 messages
	switch(type) {
	case RequestHandler.JK_AJP13_FORWARD_REQUEST:
	    return reqHandler.decodeRequest(this, hBuf, req);
	    
	case RequestHandler.JK_AJP13_CPING_REQUEST:
		return reqHandler.sendCPong(this, outBuf);
		
	case RequestHandler.JK_AJP13_SHUTDOWN:
	    return -2;
	}

	// logged || loging message
	AjpHandler handler=handlers[type];
	if( handler==null ) {
	    logger.log( "Unknown message " + type + handlerName[type] );
	    return 200;
	}

        if( debug > 0 )
            logger.log( "Ajp14 handler " + handler );
	return handler.handleAjpMessage( type, this, hBuf, req );
    }

    // ==================== Servlet Input Support =================

    /** @deprecated -- Will use reqHandler, make sure nobody else
     calls this */

    
    public int available() throws IOException {
        return reqHandler.available(this);
    }

    public int doRead() throws IOException 
    {
        return reqHandler.doRead( this );
    }
    
    public int doRead(byte[] b, int off, int len) throws IOException 
    {
        return reqHandler.doRead( this, b, off, len );
    }
    
    private boolean refillReadBuffer() throws IOException 
    {
        return reqHandler.refillReadBuffer(this);
    }    

    public void beginSendHeaders(int status,
                                 String statusMessage,
                                 int numHeaders) throws IOException {
        reqHandler.beginSendHeaders( this, outBuf,
                                         status, statusMessage,
                                         numHeaders);
    }        

	public void sendHeader(String name, String value) throws IOException {
		reqHandler.sendHeader(  outBuf, name, value );
	}


    public void endSendHeaders() throws IOException {
        reqHandler.endSendHeaders(this, outBuf);
    }

    public void sendHeaders(int status, MimeHeaders headers)
        throws IOException
    {
        reqHandler.sendHeaders(this, outBuf, status,
                                   HttpMessages.getMessage(status),
                                   headers);
    }

    public void sendHeaders(int status, String statusMessage,
                            MimeHeaders headers)
        throws IOException
    {
        reqHandler.sendHeaders( this, outBuf, status,
                                    statusMessage, headers );
    }

    public void finish() throws IOException {
        reqHandler.finish(this, outBuf );
    }

    public void doWrite(byte b[], int off, int len) throws IOException {
        reqHandler.doWrite( this, outBuf, b, off, len );
    }
    

    // ========= 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 (debug > 10) {
                logger.log("read got # " + got);
            }

            // connection just closed by remote. 
            if (got <= 0) {
                // This happens periodically, as apache restarts
                // periodically.
                // It should be more gracefull ! - another feature for Ajp14 
                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.
     *
     * @param msg The object into which to store the incoming packet -- any
     * current contents will be overwritten.
     *
     * @return The number of bytes read on a successful read or -1 if there 
     * was an error.
     **/
    public int receive(Ajp13Packet msg) throws IOException {
        if (debug > 0) {
            logger.log("receive()");
        }

	// XXX If the length in the packet header doesn't agree with the
	// actual number of bytes read, it should probably return an error
	// value.  Also, callers of this method never use the length
	// returned -- should probably return true/false instead.
	byte b[] = msg.getBuff();
	
        int rd = readN(in, b, 0, H_SIZE );
        
        // XXX - connection closed (JK_AJP13_COMM_CLOSED)
        //     - connection broken (JK_AJP13_COMM_BROKEN)
        //
        if(rd < 0) {
            // Most likely normal apache restart.
            return rd;
        }
        
	int len = msg.checkIn();
	if( debug > 5 )
            logger.log( "Received " + rd + " " + len + " " + b[0] );
        
	// XXX check if enough space - it's assert()-ed !!!
        
 	int total_read = 0;
        
        total_read = readN(in, b, H_SIZE, len);

        // it's ok to have read 0 bytes when len=0 -- this means
        // the end of the stream has been reached.
        if (total_read < 0) {
            logger.log("can't read body, waited #" + len);
            return JK_AJP13_BAD_BODY;
        }
        
        if (total_read != len) {
            logger.log( "incomplete read, waited #" + len +
                        " got only " + total_read);
            return JK_AJP13_INCOMPLETE_BODY;
        }
        
        if (debug > 0)
            logger.log("receive:  total read = " + total_read);
	return total_read;
    }
    
    /**
     * Send a packet to the web server.  Works for any type of message.
     *
     * @param msg A packet with accumulated data to send to the server --
     * this method will write out the length in the header.  
     */
    public void send( Ajp13Packet msg ) throws IOException {
        if (debug > 0) {
            logger.log("send()");
        }

	msg.end(); // Write the packet header
	byte b[] = msg.getBuff();
	int len  = msg.getLen();

        if (debug > 5 )
            logger.log("send() " + len + " " + b[0] );

	out.write( b, 0, len );
    }
	
    /**
     * Close the socket connection to the web server.  In general, sockets
     * are maintained across many requests, so this will not be called
     * after finish().  
     */
    public void close() throws IOException {
        if (debug > 0) {
            logger.log("close()");
        }

	if(null != out) {        
	    out.close();
	}
	if(null !=in) {
	    in.close();
	}
        setLogged( false );	// no more logged now 
    }

    // -------------------- Debug --------------------
    protected int debug = 0;
    
    public void setDebug(int debug) {
        this.debug = debug;
        this.reqHandler.setDebug(debug);
    }

    public void setLogger(Logger l) {
        this.logger = l;
        this.reqHandler.setLogger(l);
    }

    /**
     * XXX place holder...
     */
    Logger logger = new Logger();
}
