com.crankuptheamps.client.TCPTransport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of amps-client Show documentation
Show all versions of amps-client Show documentation
AMPS Java client by 60East Technologies, Inc.
////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010-2021 60East Technologies Inc., All Rights Reserved.
//
// This computer software is owned by 60East Technologies Inc. and is
// protected by U.S. copyright laws and other laws and by international
// treaties. This computer software is furnished by 60East Technologies
// Inc. pursuant to a written license agreement and may be used, copied,
// transmitted, and stored only in accordance with the terms of such
// license agreement and with the inclusion of the above copyright notice.
// This computer software or any other copies thereof may not be provided
// or otherwise made available to any other person.
//
// U.S. Government Restricted Rights. This computer software: (a) was
// developed at private expense and is in all respects the proprietary
// information of 60East Technologies Inc.; (b) was not developed with
// government funds; (c) is a trade secret of 60East Technologies Inc.
// for all purposes of the Freedom of Information Act; and (d) is a
// commercial item and thus, pursuant to Section 12.212 of the Federal
// Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
// Government's use, duplication or disclosure of the computer software
// is subject to the restrictions set forth by 60East Technologies Inc..
//
////////////////////////////////////////////////////////////////////////////
package com.crankuptheamps.client;
import java.net.Socket;
import java.net.URI;
import java.nio.ByteBuffer;
import java.beans.ExceptionListener;
import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.crankuptheamps.client.Message.SerializationResult;
import com.crankuptheamps.client.exception.AlreadyConnectedException;
import com.crankuptheamps.client.exception.ConnectionRefusedException;
import com.crankuptheamps.client.exception.DisconnectedException;
import com.crankuptheamps.client.exception.InvalidURIException;
import com.crankuptheamps.client.exception.RetryOperationException;
/**
* Implements an AMPS transport over standard TCP/IP.
* Use this transport by connecting to URIs beginning with tcp://.
*/
public class TCPTransport implements Transport
{
protected TCPTransportImpl _impl = null;
private Protocol _protocol = null;
private final Lock _sendLock = new ReentrantLock();
private ByteBuffer _sendBuffer = ByteBuffer.allocate(4096);
private static int _defaultReadTimeout = 0;
private static int _defaultConnectTimeout = 0;
// Other clients use daemon threads by default, but
// we have customer that depends on non-daemon threads (i.e. they
// want the program to continue running even once main() exits.)
private static boolean _useDaemonThreads = false;
protected TCPTransportImpl constructTransportImpl(Protocol protocol, Properties properties)
{
return new TCPTransportImpl(protocol, properties, new DefaultTransportFilter());
}
public TCPTransport(Protocol protocol, Properties properties)
{
this._protocol = protocol;
this._impl = constructTransportImpl(protocol,properties);
}
public TCPTransport(Protocol msgType)
{
this(msgType, null);
}
public static void setDaemon(boolean daemonThreads)
{
TCPTransport._useDaemonThreads = daemonThreads;
}
public static boolean isDaemon()
{
return TCPTransport._useDaemonThreads;
}
/**
* Sets the default read timeout used for socket reads. This value is
* used for new connections, but not applied to existing connections. A 0
* value means to wait forever for incoming data, or until an error occurs.
*
* @param defaultReadTimeoutMillis_ The default read timeout in milliseconds.
*/
public static void setDefaultReadTimeout(int defaultReadTimeoutMillis_)
{
TCPTransport._defaultReadTimeout = defaultReadTimeoutMillis_;
}
/**
* Returns the default read timeout used for socket reads. A 0 value
* means to wait forever for incoming data, or until an error occurs.
*
* @return The current default read timeout, in milliseconds.
*/
public static int getDefaultReadTimeout()
{
return TCPTransport._defaultReadTimeout;
}
/**
* Returns the default connect timeout used for new connections.
*
* @param defaultConnectTimeoutMillis_ The default connect timeout,
* in milliseconds. A 0 value means no timeout is specified, i.e. wait
* until the OS returns an error.
*/
public static void setDefaultConnectTimeout(int defaultConnectTimeoutMillis_)
{
TCPTransport._defaultConnectTimeout = defaultConnectTimeoutMillis_;
}
/**
* Returns the default connect timeout used for new connections.
*
* @return The default connect timeout in milliseconds. A 0 value means
* no timeout is specified, i.e. wait until the OS returns an error.
*/
public static int getDefaultConnectTimeout()
{
return TCPTransport._defaultConnectTimeout;
}
public static TCPTransport createTransport(Protocol messageType)
{
return new TCPTransport(messageType);
}
public void setMessageHandler(MessageHandler ml)
{
this._impl.setMessageHandler(ml);
}
public void setThreadCreatedHandler(ThreadCreatedHandler tch_)
{
this._impl.setThreadCreatedHandler(tch_);
}
public void setDisconnectHandler(TransportDisconnectHandler dh)
{
this._impl.setDisconnectHandler(dh);
}
public void setExceptionListener(ExceptionListener exceptionListener)
{
this._impl.setExceptionListener(exceptionListener);
}
public void setTransportFilter(TransportFilter filter)
{
_impl.setTransportFilter(filter);
}
public void connect(URI uri) throws ConnectionRefusedException, AlreadyConnectedException, InvalidURIException
{
this._impl.connect(uri);
}
public void close() throws Exception
{
this._impl.disconnect();
}
public void disconnect()
{
this._impl.disconnect();
}
public void handleCloseEvent(int failedVersion_, String message, Exception e) throws DisconnectedException, RetryOperationException
{
this._impl.handleCloseEvent(failedVersion_, message, e);
}
public void sendWithoutRetry(Message message) throws DisconnectedException
{
this._sendLock.lock();
try
{
_sendBuffer.clear();
// Reserve space for a 4-byte int at the
// beginning for the size of the message
_sendBuffer.position(4);
SerializationResult sr = message.serialize(_sendBuffer);
if(sr == Message.SerializationResult.BufferTooSmall)
{
// Buffer was too small, let's resize and retry
_sendBuffer = ByteBuffer.allocate(2 * _sendBuffer.capacity());
sendWithoutRetry(message);
return;
}
else if(sr == SerializationResult.OK)
{
// Write size integer now that we know the size
_sendBuffer.putInt(0, _sendBuffer.position() - 4);
// Flip buffer for reading
_sendBuffer.flip();
// Write buffer to socket
this._impl.send(_sendBuffer);
}
}
finally
{
this._sendLock.unlock();
}
}
public void send(Message message) throws DisconnectedException
{
this._sendLock.lock();
try
{
int currentVersion = getVersion();
try
{
sendWithoutRetry(message);
}
catch(DisconnectedException ex)
{
try
{
this.handleCloseEvent(currentVersion, "Exception occured while sending", ex);
}
catch(RetryOperationException r)
{
; // retry
}
throw ex;
}
}
finally
{
this._sendLock.unlock();
}
}
public Message allocateMessage()
{
return this._protocol.allocateMessage();
}
public long writeQueueSize() throws DisconnectedException
{
try
{
return this._impl.writeQueueSize();
}
catch(NullPointerException e)
{
throw new DisconnectedException("not connected", e);
}
}
public long readQueueSize() throws DisconnectedException
{
try
{
return this._impl.writeQueueSize();
}
catch(NullPointerException e)
{
throw new DisconnectedException("not connected", e);
}
}
public long flush() throws DisconnectedException
{
try
{
return this._impl.flush();
}
catch(NullPointerException e)
{
throw new DisconnectedException("not connected", e);
}
}
public long flush(long timeout) throws DisconnectedException
{
try
{
return this._impl.flush(timeout);
}
catch(NullPointerException e)
{
throw new DisconnectedException("not connected", e);
}
}
public Socket socket()
{
try
{
return this._impl.socket();
}
catch(Exception e)
{
return null;
}
}
public int getVersion()
{
return this._impl._connectionVersion;
}
public void setReadTimeout(int readTimeout_)
{
this._impl.setReadTimeout(readTimeout_);
}
public void setIdleRunnable(AMPSRunnable runnable)
{
this._impl.setIdleRunnable(runnable);
}
}