forked from MagicBane/Server
Project cleanup pre merge.
This commit is contained in:
@@ -26,400 +26,387 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public abstract class AbstractConnection implements
|
||||
NetMsgHandler {
|
||||
|
||||
private static final String error01 = "A byte buffer is being free()ed that is not of the size stored in ByteBufferPool. Size: %1%";
|
||||
private static final String error02 = "(IP=%1%): Socket has reached the maximum outbound buffer length of %2%. Moving on while we wait for data to be sent.";
|
||||
|
||||
protected final SocketChannel sockChan;
|
||||
protected final AbstractConnectionManager connMan;
|
||||
protected final NetMsgFactory factory;
|
||||
|
||||
protected long lastMsgTime = System.currentTimeMillis();
|
||||
protected long lastKeepAliveTime = System.currentTimeMillis();
|
||||
protected long lastOpcode = -1;
|
||||
|
||||
protected ConcurrentLinkedQueue<ByteBuffer> outbox = new ConcurrentLinkedQueue<>();
|
||||
protected ByteBuffer outBuf = null;
|
||||
|
||||
protected final AtomicBoolean execTask = new AtomicBoolean(false);
|
||||
|
||||
protected ConcurrentHashMap<Long, Byte> cacheList;
|
||||
|
||||
protected final ReentrantLock writeLock = new ReentrantLock();
|
||||
protected final ReentrantLock readLock = new ReentrantLock();
|
||||
protected long nextWriteTime = 0L;
|
||||
protected Protocol lastProtocol = Protocol.NONE;
|
||||
protected static final long SOCKET_FULL_WRITE_DELAY = 50L; //wait one second to write on full socket
|
||||
|
||||
//Opcode tracking
|
||||
|
||||
private static final int OPCODEHASH = 1016; //Opcodes are unique modulo this number as of 11/21/10
|
||||
|
||||
public AbstractConnection(AbstractConnectionManager connMan,
|
||||
SocketChannel sockChan, boolean clientMode) {
|
||||
this.connMan = connMan;
|
||||
this.sockChan = sockChan;
|
||||
this.factory = new NetMsgFactory(this);
|
||||
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
try {
|
||||
this.sockChan.close();
|
||||
} catch (IOException e) {
|
||||
Logger.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes AbstractNetMsg <i>msg</i> into a ByteBuffer, then queues that
|
||||
* ByteBuffer for sending on this AbstractConnection's SocketChannel.
|
||||
*
|
||||
* @param msg
|
||||
* - AbstractNetMsg to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
public final boolean sendMsg(AbstractNetMsg msg) {
|
||||
// Logger.info("Send: " + msg.getSimpleClassName());
|
||||
try {
|
||||
return this._sendMsg(msg);
|
||||
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes AbstractNetMsg <i>msg</i> into a ByteBuffer, then queues that
|
||||
* ByteBuffer for sending on this AbstractConnection's SocketChannel. This
|
||||
* internal function is <b>required</b> to be overridden by subclasses.
|
||||
*
|
||||
* @param msg
|
||||
* - AbstractNetMsg to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
protected abstract boolean _sendMsg(AbstractNetMsg msg);
|
||||
|
||||
/**
|
||||
* Queues ByteBuffer <i>bb</i> for sending on this AbstractConnection's
|
||||
* SocketChannel.
|
||||
*
|
||||
* @param bb
|
||||
* - ByteBuffer to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
public final boolean sendBB(ByteBuffer bb) {
|
||||
|
||||
if (bb == null)
|
||||
return false;
|
||||
try {
|
||||
return this._sendBB(bb);
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues ByteBuffer <i>bb</i> for sending on this AbstractConnection's
|
||||
* SocketChannel. This internal function is designed to be overrideable by
|
||||
* subclasses if needed.
|
||||
*
|
||||
* @param bb
|
||||
* - ByteBuffer to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
protected boolean _sendBB(ByteBuffer bb) {
|
||||
this.outbox.add(bb);
|
||||
this.connMan.sendStart(this.sockChan);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move data off the socketChannel's buffer and into the Connection's
|
||||
* internal NetMsgFactory.
|
||||
*/
|
||||
// FIXME the int return value on this means nothing! Clean it up!
|
||||
protected int read() {
|
||||
|
||||
if (readLock.tryLock())
|
||||
try {
|
||||
|
||||
if (this.sockChan.isOpen() == false) {
|
||||
Logger.info("Sock channel closed. Disconnecting " + this.getRemoteAddressAndPortAsString());
|
||||
this.disconnect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get socket buffer sized buffer from multipool
|
||||
ByteBuffer bb = Network.byteBufferPool.getBuffer(16);
|
||||
|
||||
int totalBytesRead = 0;
|
||||
int lastRead;
|
||||
do {
|
||||
try {
|
||||
bb.clear();
|
||||
lastRead = this.sockChan.read(bb);
|
||||
|
||||
// On EOF on the SocketChannel, disconnect.
|
||||
if (lastRead <= -1) {
|
||||
Logger.info(" EOF on Socket Channel " + this.getRemoteAddressAndPortAsString());
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastRead == 0)
|
||||
continue;
|
||||
|
||||
synchronized (this.factory) {
|
||||
this.factory.addData(bb);
|
||||
}
|
||||
this.checkInternalFactory();
|
||||
|
||||
totalBytesRead += lastRead;
|
||||
|
||||
} catch (NotYetConnectedException e) {
|
||||
Logger.error(e.toString());
|
||||
break;
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
Logger.error(e.toString());
|
||||
this.disconnect();
|
||||
break;
|
||||
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith(
|
||||
"An existing connection was forcibly closed"))
|
||||
Logger.error(e.toString());
|
||||
this.disconnect();
|
||||
break;
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.toString());
|
||||
break;
|
||||
}
|
||||
} while (lastRead > 0);
|
||||
|
||||
// put buffer back into multipool
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
|
||||
this.checkInternalFactory();
|
||||
return totalBytesRead;
|
||||
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a read lock! Skipping.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move data off the Connection's buffer and into the SocketChannel's
|
||||
* Buffer.
|
||||
*/
|
||||
protected boolean writeAll() {
|
||||
|
||||
//intentional delay if socket is full. Give the socket a chance to clear out.
|
||||
if (System.currentTimeMillis() < this.nextWriteTime)
|
||||
return false;
|
||||
|
||||
if (writeLock.tryLock())
|
||||
try {
|
||||
String s = "";
|
||||
int written = 0;
|
||||
|
||||
boolean allSentOK = true, bufferDoubled = false;
|
||||
|
||||
while (this.outbox.peek() != null) {
|
||||
ByteBuffer bb = this.outbox.peek();
|
||||
|
||||
int toSend = bb.position();
|
||||
|
||||
try {
|
||||
bb.flip();
|
||||
written = this.sockChan.write(bb);
|
||||
|
||||
// Logger.debug("Using a BB with cap of: " + bb.capacity()
|
||||
// + ". toSend: " + toSend + ", written: " + written);
|
||||
if (written != toSend)
|
||||
bb.compact(); // Clean up in case not all gets sent
|
||||
|
||||
if (toSend == written) {
|
||||
// Actually remove it from the queue
|
||||
this.outbox.poll();
|
||||
|
||||
// Pool it
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
continue;
|
||||
|
||||
} else
|
||||
if (written == 0) {
|
||||
//Socket full, let's delay the next write on socket.
|
||||
this.nextWriteTime = System.currentTimeMillis() + AbstractConnection.SOCKET_FULL_WRITE_DELAY;
|
||||
|
||||
int currentBufferSize = this.sockChan.socket()
|
||||
.getSendBufferSize();
|
||||
|
||||
if (!bufferDoubled && currentBufferSize <= Network.INITIAL_SOCKET_BUFFER_SIZE) {
|
||||
this.doubleSocketSendBufferSize();
|
||||
bufferDoubled = true;
|
||||
} else {
|
||||
|
||||
// s = error02;
|
||||
// s = s.replaceAll("%1%", this
|
||||
// .getRemoteAddressAndPortAsString() + ":" +
|
||||
// this.printLastOpcodes());
|
||||
// s = s.replaceAll("%2%", currentBufferSize + "");
|
||||
// this.warn(s);
|
||||
|
||||
allSentOK = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
// Catches AsynchronousCloseException,
|
||||
// and ClosedByInterruptException
|
||||
Logger.error(e);
|
||||
break;
|
||||
|
||||
} catch (Exception e) {
|
||||
// Catches NotYetConnectedException
|
||||
// and IOException
|
||||
Logger.error(e);
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return allSentOK;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a write lock! Skipping.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doubleSocketSendBufferSize() {
|
||||
String s;
|
||||
try {
|
||||
int currentSize = this.sockChan.socket().getSendBufferSize();
|
||||
int newSize = currentSize << 1;
|
||||
|
||||
this.sockChan.socket().setSendBufferSize(newSize);
|
||||
|
||||
// s = "(IP=" + this.getRemoteAddressAndPortAsString() + "): ";
|
||||
// s += this.printLastOpcodes();
|
||||
// s += "Socket has reached the maximum outbound buffer length of ";
|
||||
// s += currentSize + ". Attempting to double the outbound buffer size.";
|
||||
//
|
||||
// this.warn(s);
|
||||
return true;
|
||||
} catch (SocketException e) {
|
||||
Logger.error( e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return this.sockChan.isConnected();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return this.sockChan.isOpen();
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters n Setters
|
||||
*/
|
||||
public SocketChannel getSocketChannel() {
|
||||
return this.sockChan;
|
||||
}
|
||||
|
||||
public final void checkInternalFactory() {
|
||||
CheckNetMsgFactoryJob j = new CheckNetMsgFactoryJob(this);
|
||||
JobManager.getInstance().submitJob(j);
|
||||
}
|
||||
|
||||
public NetMsgFactory getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
public String getRemoteAddressAndPortAsString() {
|
||||
String out = "";
|
||||
|
||||
if (this.sockChan == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket() == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket().getRemoteSocketAddress() == null)
|
||||
out += "NotConnected";
|
||||
else
|
||||
out += this.sockChan.socket().getRemoteSocketAddress().toString();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getLocalAddressAndPortAsString() {
|
||||
String out = "";
|
||||
|
||||
if (this.sockChan == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket() == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket().getRemoteSocketAddress() == null)
|
||||
out += "NotConnected";
|
||||
else {
|
||||
out += this.sockChan.socket().getLocalSocketAddress().toString();
|
||||
out += ":";
|
||||
out += this.sockChan.socket().getLocalPort();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the Connection a chance to act on a msg prior to sending it to the
|
||||
* provided NetMsgHandler
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public abstract boolean handleClientMsg(ClientNetMsg msg);
|
||||
|
||||
protected long getLastMsgTime() {
|
||||
return this.lastMsgTime;
|
||||
}
|
||||
|
||||
protected void setLastMsgTime() {
|
||||
// TODO Consider making this a static to latest system time
|
||||
this.lastMsgTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected long getLastKeepAliveTime() {
|
||||
return this.lastKeepAliveTime;
|
||||
}
|
||||
|
||||
protected void setLastKeepAliveTime() {
|
||||
this.lastKeepAliveTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public long getLastOpcode() {
|
||||
return lastOpcode;
|
||||
}
|
||||
|
||||
public void setLastOpcode(long lastOpcode) {
|
||||
this.lastOpcode = lastOpcode;
|
||||
}
|
||||
NetMsgHandler {
|
||||
|
||||
protected static final long SOCKET_FULL_WRITE_DELAY = 50L; //wait one second to write on full socket
|
||||
private static final String error01 = "A byte buffer is being free()ed that is not of the size stored in ByteBufferPool. Size: %1%";
|
||||
private static final String error02 = "(IP=%1%): Socket has reached the maximum outbound buffer length of %2%. Moving on while we wait for data to be sent.";
|
||||
private static final int OPCODEHASH = 1016; //Opcodes are unique modulo this number as of 11/21/10
|
||||
protected final SocketChannel sockChan;
|
||||
protected final AbstractConnectionManager connMan;
|
||||
protected final NetMsgFactory factory;
|
||||
protected final AtomicBoolean execTask = new AtomicBoolean(false);
|
||||
protected final ReentrantLock writeLock = new ReentrantLock();
|
||||
protected final ReentrantLock readLock = new ReentrantLock();
|
||||
protected long lastMsgTime = System.currentTimeMillis();
|
||||
protected long lastKeepAliveTime = System.currentTimeMillis();
|
||||
protected long lastOpcode = -1;
|
||||
protected ConcurrentLinkedQueue<ByteBuffer> outbox = new ConcurrentLinkedQueue<>();
|
||||
protected ByteBuffer outBuf = null;
|
||||
protected ConcurrentHashMap<Long, Byte> cacheList;
|
||||
protected long nextWriteTime = 0L;
|
||||
|
||||
//Opcode tracking
|
||||
protected Protocol lastProtocol = Protocol.NONE;
|
||||
|
||||
public AbstractConnection(AbstractConnectionManager connMan,
|
||||
SocketChannel sockChan, boolean clientMode) {
|
||||
this.connMan = connMan;
|
||||
this.sockChan = sockChan;
|
||||
this.factory = new NetMsgFactory(this);
|
||||
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
try {
|
||||
this.sockChan.close();
|
||||
} catch (IOException e) {
|
||||
Logger.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes AbstractNetMsg <i>msg</i> into a ByteBuffer, then queues that
|
||||
* ByteBuffer for sending on this AbstractConnection's SocketChannel.
|
||||
*
|
||||
* @param msg - AbstractNetMsg to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
public final boolean sendMsg(AbstractNetMsg msg) {
|
||||
// Logger.info("Send: " + msg.getSimpleClassName());
|
||||
try {
|
||||
return this._sendMsg(msg);
|
||||
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes AbstractNetMsg <i>msg</i> into a ByteBuffer, then queues that
|
||||
* ByteBuffer for sending on this AbstractConnection's SocketChannel. This
|
||||
* internal function is <b>required</b> to be overridden by subclasses.
|
||||
*
|
||||
* @param msg - AbstractNetMsg to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
protected abstract boolean _sendMsg(AbstractNetMsg msg);
|
||||
|
||||
/**
|
||||
* Queues ByteBuffer <i>bb</i> for sending on this AbstractConnection's
|
||||
* SocketChannel.
|
||||
*
|
||||
* @param bb - ByteBuffer to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
public final boolean sendBB(ByteBuffer bb) {
|
||||
|
||||
if (bb == null)
|
||||
return false;
|
||||
try {
|
||||
return this._sendBB(bb);
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues ByteBuffer <i>bb</i> for sending on this AbstractConnection's
|
||||
* SocketChannel. This internal function is designed to be overrideable by
|
||||
* subclasses if needed.
|
||||
*
|
||||
* @param bb - ByteBuffer to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
protected boolean _sendBB(ByteBuffer bb) {
|
||||
this.outbox.add(bb);
|
||||
this.connMan.sendStart(this.sockChan);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move data off the socketChannel's buffer and into the Connection's
|
||||
* internal NetMsgFactory.
|
||||
*/
|
||||
// FIXME the int return value on this means nothing! Clean it up!
|
||||
protected int read() {
|
||||
|
||||
if (readLock.tryLock())
|
||||
try {
|
||||
|
||||
if (this.sockChan.isOpen() == false) {
|
||||
Logger.info("Sock channel closed. Disconnecting " + this.getRemoteAddressAndPortAsString());
|
||||
this.disconnect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get socket buffer sized buffer from multipool
|
||||
ByteBuffer bb = Network.byteBufferPool.getBuffer(16);
|
||||
|
||||
int totalBytesRead = 0;
|
||||
int lastRead;
|
||||
do {
|
||||
try {
|
||||
bb.clear();
|
||||
lastRead = this.sockChan.read(bb);
|
||||
|
||||
// On EOF on the SocketChannel, disconnect.
|
||||
if (lastRead <= -1) {
|
||||
Logger.info(" EOF on Socket Channel " + this.getRemoteAddressAndPortAsString());
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastRead == 0)
|
||||
continue;
|
||||
|
||||
synchronized (this.factory) {
|
||||
this.factory.addData(bb);
|
||||
}
|
||||
this.checkInternalFactory();
|
||||
|
||||
totalBytesRead += lastRead;
|
||||
|
||||
} catch (NotYetConnectedException e) {
|
||||
Logger.error(e.toString());
|
||||
break;
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
Logger.error(e.toString());
|
||||
this.disconnect();
|
||||
break;
|
||||
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith(
|
||||
"An existing connection was forcibly closed"))
|
||||
Logger.error(e.toString());
|
||||
this.disconnect();
|
||||
break;
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.toString());
|
||||
break;
|
||||
}
|
||||
} while (lastRead > 0);
|
||||
|
||||
// put buffer back into multipool
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
|
||||
this.checkInternalFactory();
|
||||
return totalBytesRead;
|
||||
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a read lock! Skipping.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move data off the Connection's buffer and into the SocketChannel's
|
||||
* Buffer.
|
||||
*/
|
||||
protected boolean writeAll() {
|
||||
|
||||
//intentional delay if socket is full. Give the socket a chance to clear out.
|
||||
if (System.currentTimeMillis() < this.nextWriteTime)
|
||||
return false;
|
||||
|
||||
if (writeLock.tryLock())
|
||||
try {
|
||||
String s = "";
|
||||
int written = 0;
|
||||
|
||||
boolean allSentOK = true, bufferDoubled = false;
|
||||
|
||||
while (this.outbox.peek() != null) {
|
||||
ByteBuffer bb = this.outbox.peek();
|
||||
|
||||
int toSend = bb.position();
|
||||
|
||||
try {
|
||||
bb.flip();
|
||||
written = this.sockChan.write(bb);
|
||||
|
||||
// Logger.debug("Using a BB with cap of: " + bb.capacity()
|
||||
// + ". toSend: " + toSend + ", written: " + written);
|
||||
if (written != toSend)
|
||||
bb.compact(); // Clean up in case not all gets sent
|
||||
|
||||
if (toSend == written) {
|
||||
// Actually remove it from the queue
|
||||
this.outbox.poll();
|
||||
|
||||
// Pool it
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
continue;
|
||||
|
||||
} else if (written == 0) {
|
||||
//Socket full, let's delay the next write on socket.
|
||||
this.nextWriteTime = System.currentTimeMillis() + AbstractConnection.SOCKET_FULL_WRITE_DELAY;
|
||||
|
||||
int currentBufferSize = this.sockChan.socket()
|
||||
.getSendBufferSize();
|
||||
|
||||
if (!bufferDoubled && currentBufferSize <= Network.INITIAL_SOCKET_BUFFER_SIZE) {
|
||||
this.doubleSocketSendBufferSize();
|
||||
bufferDoubled = true;
|
||||
} else {
|
||||
|
||||
// s = error02;
|
||||
// s = s.replaceAll("%1%", this
|
||||
// .getRemoteAddressAndPortAsString() + ":" +
|
||||
// this.printLastOpcodes());
|
||||
// s = s.replaceAll("%2%", currentBufferSize + "");
|
||||
// this.warn(s);
|
||||
|
||||
allSentOK = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
// Catches AsynchronousCloseException,
|
||||
// and ClosedByInterruptException
|
||||
Logger.error(e);
|
||||
break;
|
||||
|
||||
} catch (Exception e) {
|
||||
// Catches NotYetConnectedException
|
||||
// and IOException
|
||||
Logger.error(e);
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return allSentOK;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a write lock! Skipping.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doubleSocketSendBufferSize() {
|
||||
String s;
|
||||
try {
|
||||
int currentSize = this.sockChan.socket().getSendBufferSize();
|
||||
int newSize = currentSize << 1;
|
||||
|
||||
this.sockChan.socket().setSendBufferSize(newSize);
|
||||
|
||||
// s = "(IP=" + this.getRemoteAddressAndPortAsString() + "): ";
|
||||
// s += this.printLastOpcodes();
|
||||
// s += "Socket has reached the maximum outbound buffer length of ";
|
||||
// s += currentSize + ". Attempting to double the outbound buffer size.";
|
||||
//
|
||||
// this.warn(s);
|
||||
return true;
|
||||
} catch (SocketException e) {
|
||||
Logger.error(e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return this.sockChan.isConnected();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return this.sockChan.isOpen();
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters n Setters
|
||||
*/
|
||||
public SocketChannel getSocketChannel() {
|
||||
return this.sockChan;
|
||||
}
|
||||
|
||||
public final void checkInternalFactory() {
|
||||
CheckNetMsgFactoryJob j = new CheckNetMsgFactoryJob(this);
|
||||
JobManager.getInstance().submitJob(j);
|
||||
}
|
||||
|
||||
public NetMsgFactory getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
public String getRemoteAddressAndPortAsString() {
|
||||
String out = "";
|
||||
|
||||
if (this.sockChan == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket() == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket().getRemoteSocketAddress() == null)
|
||||
out += "NotConnected";
|
||||
else
|
||||
out += this.sockChan.socket().getRemoteSocketAddress().toString();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getLocalAddressAndPortAsString() {
|
||||
String out = "";
|
||||
|
||||
if (this.sockChan == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket() == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket().getRemoteSocketAddress() == null)
|
||||
out += "NotConnected";
|
||||
else {
|
||||
out += this.sockChan.socket().getLocalSocketAddress().toString();
|
||||
out += ":";
|
||||
out += this.sockChan.socket().getLocalPort();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the Connection a chance to act on a msg prior to sending it to the
|
||||
* provided NetMsgHandler
|
||||
*/
|
||||
@Override
|
||||
public abstract boolean handleClientMsg(ClientNetMsg msg);
|
||||
|
||||
protected long getLastMsgTime() {
|
||||
return this.lastMsgTime;
|
||||
}
|
||||
|
||||
protected void setLastMsgTime() {
|
||||
// TODO Consider making this a static to latest system time
|
||||
this.lastMsgTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected long getLastKeepAliveTime() {
|
||||
return this.lastKeepAliveTime;
|
||||
}
|
||||
|
||||
protected void setLastKeepAliveTime() {
|
||||
this.lastKeepAliveTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public long getLastOpcode() {
|
||||
return lastOpcode;
|
||||
}
|
||||
|
||||
public void setLastOpcode(long lastOpcode) {
|
||||
this.lastOpcode = lastOpcode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user