/*
 *  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.tomcat33;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

import org.apache.ajp.Ajp13;
import org.apache.ajp.NegociationHandler;
import org.apache.ajp.RequestHandler;
import org.apache.tomcat.core.Context;
import org.apache.tomcat.core.ContextManager;
import org.apache.tomcat.core.Request;
import org.apache.tomcat.core.Response;
import org.apache.tomcat.core.TomcatException;
import org.apache.tomcat.modules.server.PoolTcpConnector;
import org.apache.tomcat.util.buf.UDecoder;
import org.apache.tomcat.util.http.BaseRequest;
import org.apache.tomcat.util.http.Cookies;
import org.apache.tomcat.util.http.HttpMessages;
import org.apache.tomcat.util.net.TcpConnection;
import org.apache.tomcat.util.net.TcpConnectionHandler;

/** Note. PoolTcpConnector is a convenience base class used for
    TCP-based connectors in tomcat33. It allows all those modules
    to share the thread pool and listener code.

    In future it's likely other optimizations will be implemented in
    the PoolTcpConnector, so it's better to use it if you don't have
    a good reason not to ( like a connector for J2ME, where you want
    minimal footprint and don't care about high load )
*/

/** Tomcat 33 module implementing the Ajp14 protocol.
 *
 *  The actual protocol implementation is in Ajp14.java, this is just an
 *  adapter to plug it into tomcat.
 */
public class Ajp14Interceptor extends PoolTcpConnector
    implements  TcpConnectionHandler
{
    int ajp14_note=-1;
    String password;
    RequestHandler reqHandler=new RequestHandler();
    NegociationHandler negHandler=new NegociationHandler();
    
    public Ajp14Interceptor()
    {
        super();
 	super.setSoLinger( 100 );
	super.setTcpNoDelay( true );
    }

    // initialization
    public void engineInit(ContextManager cm) throws TomcatException {
	log("engineInit");
    }

    public void engineStart(ContextManager cm) throws TomcatException {
	super.engineInit( cm );
	ajp14_note=cm.getNoteId( ContextManager.REQUEST_NOTE, "ajp14" );
	super.engineStart(cm);
   }

    
    // -------------------- Ajp14 specific parameters --------------------

    public void setPassword( String s ) {
	this.password=s;
    }

    /**
     * Set the original entropy seed
     */
    public void setSeed(String pseed) 
    {
	negHandler.setSeed( pseed );
    }
    
    // -------------------- PoolTcpConnector --------------------

    /** Called by PoolTcpConnector to allow childs to init.
     */
    protected void localInit() throws Exception {
	ep.setConnectionHandler( this );
    }

    // -------------------- Handler implementation --------------------

    /*  The TcpConnectionHandler interface is used by the PoolTcpConnector to
     *  handle incoming connections.
     */

    /** Called by the thread pool when a new thread is added to the pool,
	in order to create the (expensive) objects that will be stored
	as thread data.
	XXX we should use a single object, not array ( several reasons ),
	XXX Ajp14 should be storead as a request note, to be available in
	all modules
    */
    public Object[] init()
    {
	if( debug > 0 ) log("Init ");
        Object thData[]=new Object[1];
	thData[0]=initRequest( null );
	return thData;
    }

    /** Construct the request object, with probably unnecesary
	sanity tests ( should work without thread pool - but that is
	not supported in PoolTcpConnector, maybe in future )
    */
    private Ajp14Request initRequest(Object thData[] ) {
	if( ajp14_note < 0 ) throw new RuntimeException( "assert: ajp14_note>0" );
	Ajp14Request req=null;
	if( thData != null ) {
	    req=(Ajp14Request)thData[0];
	}
	if( req != null ) {
	    Response res=req.getResponse();
	    req.recycle();
	    res.recycle();
	    // make the note available to other modules
	    req.setNote( ajp14_note, req.ajp13);
	    return req;
	}
	// either thData==null or broken ( req==null)
       	Ajp13 ajp13=new Ajp13(reqHandler);
        negHandler.init( ajp13 );

	negHandler.setContainerSignature( ContextManager.TOMCAT_NAME +
                                          " v" + ContextManager.TOMCAT_VERSION);
	if( password!= null ) {
            negHandler.setPassword( password );
            ajp13.setBackward(false); 
        }

	BaseRequest ajpreq=new BaseRequest();

	req=new Ajp14Request(ajp13, ajpreq);
	Ajp14Response res=new Ajp14Response(ajp13);
	cm.initRequest(req, res);
	return  req;
    }
    
    /** Called whenever a new TCP connection is received. The connection
	is reused.
     */
    public void processConnection(TcpConnection connection, Object thData[])
    {
        try {
	    if( debug>0)
		log( "Received ajp14 connection ");
            Socket socket = connection.getSocket();
	    // assert: socket!=null, connection!=null ( checked by PoolTcpEndpoint )
	    
            socket.setSoLinger( true, 100);

            Ajp14Request req=initRequest( thData );
            Ajp14Response res= (Ajp14Response)req.getResponse();
            Ajp13 ajp13=req.ajp13;
	    BaseRequest ajpReq=req.ajpReq;

            ajp13.setSocket(socket);

	    // first request should be the loginit.
	    int status=ajp13.receiveNextRequest( ajpReq );
	    if( status != 304 )  { // XXX use better codes
		log( "Failure in logInit ");
		return;
	    }

	    status=ajp13.receiveNextRequest( ajpReq );
	    if( status != 304 ) { // XXX use better codes
		log( "Failure in login ");
		return;
	    }
	    
            boolean moreRequests = true;
            while(moreRequests) {
		status=ajp13.receiveNextRequest( ajpReq );

		if( status==-2) {
		    // special case - shutdown
		    // XXX need better communication, refactor it
		    if( !doShutdown(socket.getLocalAddress(),
				    socket.getInetAddress())) {
			moreRequests = false;
			continue;
		    }                        
		}
		
		// 999 low level requests are just ignored (ie cping/cpong)
		if( status  == 200)
		    cm.service(req, res);
		else if (status == 500) {
		    log( "Invalid request received " + req );
		    break;
		}
		
		req.recycle();
		res.recycle();
            }
            if( debug > 0 ) log("Closing ajp14 connection");
            ajp13.close();
	    socket.close();
        } catch (Exception e) {
	    log("Processing connection " + connection, e);
        }
    }

    // We don't need to check isSameAddress if we authenticate !!!
    protected boolean doShutdown(InetAddress serverAddr,
                                 InetAddress clientAddr)
    {
        try {
	    // close the socket connection before handling any signal
	    // but get the addresses first so they are not corrupted			
            if(isSameAddress(serverAddr, clientAddr)) {
		cm.stop();
		// same behavior as in past, because it seems that
		// stopping everything doesn't work - need to figure
		// out what happens with the threads ( XXX )

		// XXX It should work now - but will fail if servlets create
		// threads
		System.exit(0);
	    }
	} catch(Exception ignored) {
	    log("Ignored " + ignored);
	}
	log("Shutdown command ignored");
	return false;
    }

    // legacy, should be removed 
    public void setServer(Object contextM)
    {
        this.cm=(ContextManager)contextM;
    }

    public Object getInfo( Context ctx, Request request,
			   int id, String key ) {
	if( ! ( request instanceof Ajp14Request ) ) {
	    return null;
	}
	Ajp14Request ajp14req = (Ajp14Request)request;
	return ajp14req.ajpReq.getAttribute( key );
    }
    public int setInfo( Context ctx, Request request,
			int id, String key, Object obj ) {
	if( ! ( request instanceof Ajp14Request ) ) {
	    return DECLINED;
	}
	Ajp14Request ajp14req = (Ajp14Request)request;
	ajp14req.ajpReq.setAttribute(key, obj);
	return OK;
    }
		


}


//-------------------- Glue code for request/response.
// Probably not needed ( or can be simplified ), but it's
// not that bad.

class Ajp14Request extends Request 
{
    Ajp13 ajp13;
    BaseRequest ajpReq;
    
    public Ajp14Request(Ajp13 ajp13, BaseRequest ajpReq) 
    {
	headers = ajpReq.headers();
	methodMB=ajpReq.method();
	protoMB=ajpReq.protocol();
	uriMB = ajpReq.requestURI();
	queryMB = ajpReq.queryString();
	remoteAddrMB = ajpReq.remoteAddr();
	remoteHostMB = ajpReq.remoteHost();
	serverNameMB = ajpReq.serverName();

	// XXX sync cookies 
	scookies = new Cookies( headers );
	urlDecoder=new UDecoder();

	// XXX sync headers
	
	params.setQuery( queryMB );
	params.setURLDecoder( urlDecoder );
	params.setHeaders( headers );
	initRequest(); 	

        this.ajp13=ajp13;
	this.ajpReq=ajpReq;
    }

    // -------------------- Wrappers for changed method names, and to use the buffers
    // XXX Move BaseRequest into util !!! ( it's just a stuct with some MessageBytes )

    public int getServerPort() {
        return ajpReq.getServerPort();
    }

    public void setServerPort(int i ) {
	ajpReq.setServerPort( i );
    }

    public  void setRemoteUser( String s ) {
	super.setRemoteUser(s);
	ajpReq.remoteUser().setString(s);
    }

    public String getRemoteUser() {
	String s=ajpReq.remoteUser().toString();
	if( s == null )
	    s=super.getRemoteUser();
	return s;
    }

    public String getAuthType() {
	return ajpReq.authType().toString();
    }
    
    public void setAuthType(String s ) {
	ajpReq.authType().setString(s);
    }

    public String getJvmRoute() {
	return ajpReq.jvmRoute().toString();
    }
    
    public void setJvmRoute(String s ) {
	ajpReq.jvmRoute().setString(s);
    }

    // XXX scheme
    
    public boolean isSecure() {
	return ajpReq.getSecure();
    }
    
    public int getContentLength() {
        int i=ajpReq.getContentLength();
	if( i >= 0 ) return i;
	i= super.getContentLength();
	return i;
    }

    public void setContentLength( int i ) {
	super.setContentLength(i); // XXX sync
    }

    // XXX broken
//     public Iterator getAttributeNames() {
//         return attributes.keySet().iterator();
//     }


    // --------------------

    public void recycle() {
	super.recycle();
	ajpReq.recycle();
	if( ajp13!=null) ajp13.recycle();
    }

    public String dumpRequest() {
	return ajpReq.toString();
    }
    
    // -------------------- 
    
    // XXX This should go away if we introduce an InputBuffer.
    // We almost have it as result of encoding fixes, but for now
    // just keep this here, doesn't hurt too much.
    public int doRead() throws IOException 
    {
	if( available <= 0 )
	    return -1;
	available--;
	return ajp13.reqHandler.doRead(ajp13);
    }
    
    public int doRead(byte[] b, int off, int len) throws IOException 
    {
	if( available <= 0 )
	    return -1;
	int rd=ajp13.reqHandler.doRead( ajp13, b,off, len );
	available -= rd;
	return rd;
    }
    
}

class Ajp14Response extends Response 
{
    Ajp13 ajp13;
    boolean finished=false;
    
    public Ajp14Response(Ajp13 ajp13) 
    {
	super();
	this.ajp13=ajp13;
    }

    public void recycle() {
	super.recycle();
	finished=false;
    }

    // XXX if more headers that MAX_SIZE, send 2 packets!
    // XXX Can be implemented using module notification, no need to extend
    public void endHeaders() throws IOException 
    {
        super.endHeaders();
    
        if (request.protocol().isNull()) {
            return;
        }

	ajp13.reqHandler.sendHeaders(ajp13, ajp13.outBuf, getStatus(),
				     HttpMessages.getMessage(status),
				     getMimeHeaders());
    } 

    // XXX Can be implemented using module notification, no need to extend
    public void finish() throws IOException 
    {
	if(!finished) {
	    super.finish();
		finished = true; // Avoid END_OF_RESPONSE sent 2 times
	    ajp13.reqHandler.finish(ajp13, ajp13.outBuf);
	}
    }

    // XXX Can be implemented using the buffers, no need to extend
    public void doWrite(  byte b[], int off, int len) throws IOException 
    {
	ajp13.reqHandler.doWrite(ajp13, ajp13.outBuf, b, off, len );
    }
    
}
