/* * $Author: rahul_kumar $ * $Id: ProxyServer.java,v 1.5 2003/10/12 12:28:55 rahul_kumar Exp $ */ package raining.core; import java.util.*; import java.nio.channels.*; import java.nio.*; /** * A pipelining client. Maintains one socket internally for any * server+port combination (multiple threads requesting a connection * with one server+port will go through this one socket. * Sends data back using the setSendData of the caller. * Uses the terminator to delimit reads on the client socket. * XXX - IN PROGRESS, TO TEST * what is difff in recvr and sendHandler * TODO: since this extends NIO and not PipelinedScoket make sure that * we break the input as in handle_input. * */ public class PipelinedClient extends NioSocket { /** map of socket + port combination */ static protected Hashtable map = new Hashtable(); /** each caller gives his write-handler, write back using this handler. * A linked list would be more efficient. */ static Vector /**/ pipes = new Vector(); /** the handler to write back on, passed by the caller */ protected NioSocket sendHandler; /** get an instance of a nb socket for a host port combination, * passing the instance of the caller, for writing back. */ public PipelinedClient getInstance(NioSocket nio, String host, int port) throws java.lang.Exception { PipelinedClient pipe; //sendHandler = nio; if ((pipe = (PipelinedClient) map.get(host+port)) == null){ pipe = new PipelinedClient(nio, host, port); map.put(host+port, pipe); } else { return pipe; } return pipe; } /** the caller uses this to push data. */ public void setSendData (String path){ pipes.add(rcvr); super.setSendData(path); } //ProxyReceiver rcvr; NioSocket rcvr; /** constructor taking the write/send handler on which to write * back, as well as host and port to connect to. */ private PipelinedClient ( NioSocket rcvr, String host, int port) throws Exception { super(); this.rcvr = rcvr; //this.setTerminator(null); // ??? this.create_client_socket(host, port); ((SocketChannel)this.sc).socket().setKeepAlive(true); //this.setTerminator(ProxyServer.TERMINATOR); } //public void handle_terminator(String mdata) // System.err.println( "ProxySender: handle_terminator .."); /** handle for what to do, when data has come in from client socket. * this writes back to the given handler using its setSendData. */ public void handle_read_complete(String mdata){ System.err.println( P+": handle_read_complete .."); System.err.println( "==> " + this.id + " " + mdata.length()); clear_read_buffer(); // ?? XXX // a 1.1 server will always return in the same order so we pick // the top most handler and write back. NioSocket send = (NioSocket) pipes.remove(0); send.setSendData( mdata + TERMINATOR ); } /** close socket/s. * call this carefully, i would rather that the caller closes his * own socket. */ public void handle_close(){ System.err.println( P+": closing .. CAREFUL"); //this.rcvr.nio_close(); // caller shd close this.nio_close(); } public void handle_connect(){ System.err.println( P+": connect .."); } public void handle_write_complete(){ System.err.println( P+":please override handle_write_complete if required"); //handle_close(); } /** method that tells the framework how to determine when one * response is over. */ public boolean is_read_complete(){ return (rsb.indexOf(TERMINATOR) > -1); } public static final String TERMINATOR = "\r\n\r\n"; public static final String P = "PipelinedClient"; } // end of class ProxySender