/* UnicastConnection.java --
   Copyright (c) 1996, 1997, 1998, 1999, 2002, 2004
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.rmi.server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.rmi.RemoteException;

public class UnicastConnection 
	implements Runnable, ProtocolConstants {

UnicastConnectionManager manager;
Socket sock;
DataInputStream din;
DataOutputStream dout;
ObjectInputStream oin;
ObjectOutputStream oout;

// reviveTime and expireTime make UnicastConnection pool-able
long reviveTime = 0;
long expireTime = Long.MAX_VALUE;

UnicastConnection(UnicastConnectionManager man, Socket sock) {
	this.manager = man;
	this.sock = sock;
}

void acceptConnection() throws IOException {
//System.out.println("Accepting connection on " + sock);
    //Use BufferedXXXStream would be more efficient
	din = new DataInputStream(new BufferedInputStream(sock.getInputStream()));
	dout = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));

	int sig = din.readInt();
	if (sig != PROTOCOL_HEADER) {
		throw new IOException("bad protocol header");
	}
	short ver = din.readShort();
	if (ver != PROTOCOL_VERSION) {
		throw new IOException("bad protocol version");
	}
	int protocol = din.readUnsignedByte();
	if (protocol != SINGLE_OP_PROTOCOL) {
		// Send an ACK
		dout.writeByte(PROTOCOL_ACK);

		// Send my hostname and port
		dout.writeUTF(manager.serverName);
		dout.writeInt(manager.serverPort);
		dout.flush();

		// Read their hostname and port
		String rhost = din.readUTF();
		int rport = din.readInt();
	}
	// Okay, ready to roll ...
}

void makeConnection(int protocol) throws IOException {
    //Use BufferedXXXStream would be more efficient
	din = new DataInputStream(new BufferedInputStream(sock.getInputStream()));

	dout = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));

	// Send header
	dout.writeInt(PROTOCOL_HEADER);
	dout.writeShort(PROTOCOL_VERSION);
	dout.writeByte(protocol);
    dout.flush();
    
	if (protocol != SINGLE_OP_PROTOCOL) {
		// Get back ack.
		int ack = din.readUnsignedByte();
		if (ack != PROTOCOL_ACK) {
			throw new RemoteException("Unsupported protocol");
		}

		// Read in host and port
		String dicard_rhost = din.readUTF();
		int discard_rport = din.readInt();

		// Send them my endpoint
		dout.writeUTF(manager.serverName);
		dout.writeInt(manager.serverPort);
		dout.flush();
	}
	// Okay, ready to roll ...
}

DataInputStream getDataInputStream() throws IOException {
	return (din);
}

DataOutputStream getDataOutputStream() throws IOException {
	return (dout);
}

/*
*
* get ObjectInputStream for reading more objects
*
*/
ObjectInputStream getObjectInputStream() throws IOException {
	if (oin == null) {
		throw new IOException("no ObjectInputtream for reading more objects");
	}
	return (oin);
}

/**
*
* starts ObjectInputStream.
*
*/
ObjectInputStream startObjectInputStream() throws IOException {
	return (oin = new RMIObjectInputStream(din));
}

/**
*
* get ObjectOutputStream for sending more objects
*
*/
ObjectOutputStream getObjectOutputStream() throws IOException {
	if (oout == null) {
		throw new IOException("no ObjectOutputStream for sending more objects");
	} 
	return (oout);
}

/**
*
* starts ObjectOutputStream.
*
*/
ObjectOutputStream startObjectOutputStream() throws IOException {
	return (oout = new RMIObjectOutputStream(dout));
} 

void disconnect() {
	try {
	    if(oout != null)
	        oout.close();
        sock.close();
	}
	catch (IOException _) {
    }

	oin = null;
    oout = null;
	din = null;
	dout = null;
	sock = null;
}

public static final long CONNECTION_TIMEOUT = 10000L;

static boolean isExpired(UnicastConnection conn, long l){
    if (l <= conn.expireTime )
        return false;
    return true;
}

static void resetTime(UnicastConnection conn){
    long l = System.currentTimeMillis();
    conn.reviveTime = l;
    conn.expireTime = l + CONNECTION_TIMEOUT;
}

/**
 * We run connects on the server. Dispatch it then discard it.
 */
public void run() {
    do{
	try {
		UnicastServer.dispatch(this);
            //don't discardConnection explicitly, only when
            //  exception happens or the connection's expireTime 
            //  comes
        } catch (Exception e ){
		manager.discardConnection(this);
            break;
	}
    }while(true);
}


}
