diff options
Diffstat (limited to 'src/share/classes/sun/rmi/transport/tcp/TCPConnection.java')
-rw-r--r-- | src/share/classes/sun/rmi/transport/tcp/TCPConnection.java | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/src/share/classes/sun/rmi/transport/tcp/TCPConnection.java b/src/share/classes/sun/rmi/transport/tcp/TCPConnection.java new file mode 100644 index 000000000..ac1971590 --- /dev/null +++ b/src/share/classes/sun/rmi/transport/tcp/TCPConnection.java @@ -0,0 +1,236 @@ +/* + * Copyright 1996-2001 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.rmi.transport.tcp; + +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketException; +import java.rmi.*; +import java.rmi.server.RMISocketFactory; +import sun.rmi.runtime.Log; +import sun.rmi.transport.*; +import sun.rmi.transport.proxy.*; + +public class TCPConnection implements Connection { + + private Socket socket; + private Channel channel; + private InputStream in = null; + private OutputStream out = null; + private long expiration = Long.MAX_VALUE; + private long lastuse = Long.MIN_VALUE; + private long roundtrip = 5; // round-trip time for ping + + /** + * Constructor used for creating a connection to accept call + * (an input connection) + */ + TCPConnection(TCPChannel ch, Socket s, InputStream in, OutputStream out) + { + socket = s; + channel = ch; + this.in = in; + this.out = out; + } + + /** + * Constructor used by subclass when underlying input and output streams + * are already available. + */ + TCPConnection(TCPChannel ch, InputStream in, OutputStream out) + { + this(ch, null, in, out); + } + + /** + * Constructor used when socket is available, but not underlying + * streams. + */ + TCPConnection(TCPChannel ch, Socket s) + { + this(ch, s, null, null); + } + + /** + * Gets the output stream for this connection + */ + public OutputStream getOutputStream() throws IOException + { + if (out == null) + out = new BufferedOutputStream(socket.getOutputStream()); + return out; + } + + /** + * Release the output stream for this connection. + */ + public void releaseOutputStream() throws IOException + { + if (out != null) + out.flush(); + } + + /** + * Gets the input stream for this connection. + */ + public InputStream getInputStream() throws IOException + { + if (in == null) + in = new BufferedInputStream(socket.getInputStream()); + return in; + } + + + /** + * Release the input stream for this connection. + */ + public void releaseInputStream() + { + } + + /** + * Determine if this connection can be used for multiple operations. + * If the socket implements RMISocketInfo, then we can query it about + * this; otherwise, assume that it does provide a full-duplex + * persistent connection like java.net.Socket. + */ + public boolean isReusable() + { + if ((socket != null) && (socket instanceof RMISocketInfo)) + return ((RMISocketInfo) socket).isReusable(); + else + return true; + } + + /** + * Set the expiration time of this connection. + * @param time The time at which the time out expires. + */ + void setExpiration(long time) + { + expiration = time; + } + + /** + * Set the timestamp at which this connection was last used successfully. + * The connection will be pinged for liveness if reused long after + * this time. + * @param time The time at which the connection was last active. + */ + void setLastUseTime(long time) + { + lastuse = time; + } + + /** + * Returns true if the timeout has expired on this connection; + * otherwise returns false. + * @param time The current time. + */ + boolean expired(long time) + { + return expiration <= time; + } + + /** + * Probes the connection to see if it still alive and connected to + * a responsive server. If the connection has been idle for too + * long, the server is pinged. ``Too long'' means ``longer than the + * last ping round-trip time''. + * <P> + * This method may misdiagnose a dead connection as live, but it + * will never misdiagnose a live connection as dead. + * @return true if the connection and server are recently alive + */ + public boolean isDead() + { + InputStream i; + OutputStream o; + + // skip ping if recently used within 1 RTT + long start = System.currentTimeMillis(); + if ((roundtrip > 0) && (start < lastuse + roundtrip)) + return (false); // still alive and warm + + // Get the streams + try { + i = getInputStream(); + o = getOutputStream(); + } catch (IOException e) { + return (true); // can't even get a stream, must be very dead + } + + // Write the ping byte and read the reply byte + int response = 0; + try { + o.write(TransportConstants.Ping); + o.flush(); + response = i.read(); + } catch (IOException ex) { + TCPTransport.tcpLog.log(Log.VERBOSE, "exception: ", ex); + TCPTransport.tcpLog.log(Log.BRIEF, "server ping failed"); + + return (true); // server failed the ping test + } + + if (response == TransportConstants.PingAck) { + // save most recent RTT for future use + roundtrip = (System.currentTimeMillis() - start) * 2; + // clock-correction may make roundtrip < 0; doesn't matter + return (false); // it's alive and 5-by-5 + } + + if (TCPTransport.tcpLog.isLoggable(Log.BRIEF)) { + TCPTransport.tcpLog.log(Log.BRIEF, + (response == -1 ? "server has been deactivated" : + "server protocol error: ping response = " + response)); + } + return (true); + } + + /** + * Close the connection. */ + public void close() throws IOException + { + TCPTransport.tcpLog.log(Log.BRIEF, "close connection"); + + if (socket != null) + socket.close(); + else { + in.close(); + out.close(); + } + } + + /** + * Returns the channel for this connection. + */ + public Channel getChannel() + { + return channel; + } +} |