forked from MagicBane/Server
Project cleanup pre merge.
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.net.client;
|
||||
|
||||
import engine.Enum;
|
||||
@@ -35,320 +34,317 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ClientConnection extends AbstractConnection {
|
||||
|
||||
// Enumeration of a message's origin for logging purposes
|
||||
private enum MessageSource {
|
||||
private final ClientAuthenticator crypto;
|
||||
private final String clientIpAddress;
|
||||
public String machineID;
|
||||
public long guildtreespam = 0;
|
||||
public long ordernpcspam = 0;
|
||||
public ReentrantLock trainLock = new ReentrantLock();
|
||||
public ReentrantLock sellLock = new ReentrantLock();
|
||||
public ReentrantLock buyLock = new ReentrantLock();
|
||||
public boolean desyncDebug = false;
|
||||
public byte[] lastByteBuffer;
|
||||
protected SessionID sessionID = null;
|
||||
private byte cryptoInitTries = 0;
|
||||
|
||||
SOURCE_CLIENT,
|
||||
SOURCE_SERVER
|
||||
}
|
||||
public ClientConnection(ClientConnectionManager connMan,
|
||||
SocketChannel sockChan) {
|
||||
super(connMan, sockChan, true);
|
||||
this.crypto = new ClientAuthenticator(this);
|
||||
|
||||
private byte cryptoInitTries = 0;
|
||||
protected SessionID sessionID = null;
|
||||
private final ClientAuthenticator crypto;
|
||||
private final String clientIpAddress;
|
||||
public String machineID;
|
||||
public long guildtreespam = 0;
|
||||
public long ordernpcspam = 0;
|
||||
public ReentrantLock trainLock = new ReentrantLock();
|
||||
public ReentrantLock sellLock = new ReentrantLock();
|
||||
public ReentrantLock buyLock = new ReentrantLock();
|
||||
this.clientIpAddress = sockChan.socket().getRemoteSocketAddress()
|
||||
.toString().replace("/", "").split(":")[0];
|
||||
}
|
||||
|
||||
public boolean desyncDebug = false;
|
||||
|
||||
public byte[] lastByteBuffer;
|
||||
@Override
|
||||
protected boolean _sendMsg(AbstractNetMsg msg) {
|
||||
try {
|
||||
msg.setOrigin(this);
|
||||
ByteBuffer bb = msg.serialize();
|
||||
|
||||
public ClientConnection(ClientConnectionManager connMan,
|
||||
SocketChannel sockChan) {
|
||||
super(connMan, sockChan, true);
|
||||
this.crypto = new ClientAuthenticator(this);
|
||||
// Application protocol logging toggled via
|
||||
// DevCmd: netdebug on|off
|
||||
|
||||
this.clientIpAddress = sockChan.socket().getRemoteSocketAddress()
|
||||
.toString().replace("/", "").split(":")[0];
|
||||
}
|
||||
if (MBServerStatics.DEBUG_PROTOCOL)
|
||||
applicationProtocolLogger(msg, MessageSource.SOURCE_SERVER);
|
||||
|
||||
@Override
|
||||
protected boolean _sendMsg(AbstractNetMsg msg) {
|
||||
try {
|
||||
msg.setOrigin(this);
|
||||
ByteBuffer bb = msg.serialize();
|
||||
boolean retval = this.sendBB(bb);
|
||||
Network.byteBufferPool.putBuffer(bb);//return here.
|
||||
|
||||
// Application protocol logging toggled via
|
||||
// DevCmd: netdebug on|off
|
||||
return retval;
|
||||
|
||||
if (MBServerStatics.DEBUG_PROTOCOL)
|
||||
applicationProtocolLogger(msg, MessageSource.SOURCE_SERVER);
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean retval = this.sendBB(bb);
|
||||
Network.byteBufferPool.putBuffer(bb);//return here.
|
||||
/**
|
||||
* Sending a NetMsg to the client involves NOT including a dataLen parameter
|
||||
* and also involves encrypting the data.
|
||||
*/
|
||||
@Override
|
||||
protected boolean _sendBB(ByteBuffer bb) {
|
||||
boolean useCrypto = this.crypto.initialized();
|
||||
boolean retVal;
|
||||
|
||||
return retval;
|
||||
// Logger.debug("useCrypto: " + useCrypto + ". bb.cap(): " +
|
||||
// bb.capacity());
|
||||
if (useCrypto == false)
|
||||
retVal = super._sendBB(bb);
|
||||
else {
|
||||
if (bb == null)
|
||||
Logger.error("Incoming bb is null");
|
||||
ByteBuffer encrypted = Network.byteBufferPool.getBufferToFit(bb.capacity());
|
||||
if (encrypted == null)
|
||||
Logger.error("Encrypted bb is null");
|
||||
this.crypto.encrypt(bb, encrypted);
|
||||
retVal = super._sendBB(encrypted);
|
||||
}
|
||||
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sending a NetMsg to the client involves NOT including a dataLen parameter
|
||||
* and also involves encrypting the data.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected boolean _sendBB(ByteBuffer bb) {
|
||||
boolean useCrypto = this.crypto.initialized();
|
||||
boolean retVal;
|
||||
/**
|
||||
* Receiving data from a client involves the initial Crypto Key Exchange,
|
||||
* waiting for a complete NetMsg to arrive using an accumulation factory and
|
||||
* decrypting the data.
|
||||
*/
|
||||
//FIXME the int return value on this means nothing! Clean it up!
|
||||
@Override
|
||||
protected int read() {
|
||||
|
||||
// Logger.debug("useCrypto: " + useCrypto + ". bb.cap(): " +
|
||||
// bb.capacity());
|
||||
if (useCrypto == false)
|
||||
retVal = super._sendBB(bb);
|
||||
else {
|
||||
if (bb == null)
|
||||
Logger.error("Incoming bb is null");
|
||||
ByteBuffer encrypted = Network.byteBufferPool.getBufferToFit(bb.capacity());
|
||||
if (encrypted == null)
|
||||
Logger.error("Encrypted bb is null");
|
||||
this.crypto.encrypt(bb, encrypted);
|
||||
retVal = super._sendBB(encrypted);
|
||||
}
|
||||
if (readLock.tryLock())
|
||||
try {
|
||||
|
||||
return retVal;
|
||||
}
|
||||
// First and foremost, check to see if we the Crypto is initted yet
|
||||
if (!this.crypto.initialized())
|
||||
this.crypto.initialize(this);
|
||||
|
||||
/**
|
||||
* Receiving data from a client involves the initial Crypto Key Exchange,
|
||||
* waiting for a complete NetMsg to arrive using an accumulation factory and
|
||||
* decrypting the data.
|
||||
*/
|
||||
//FIXME the int return value on this means nothing! Clean it up!
|
||||
@Override
|
||||
protected int read() {
|
||||
if (!this.crypto.initialized()) {
|
||||
++this.cryptoInitTries;
|
||||
if (this.cryptoInitTries >= MBServerStatics.MAX_CRYPTO_INIT_TRIES) {
|
||||
Logger.info("Failed to initialize after "
|
||||
+ MBServerStatics.MAX_CRYPTO_INIT_TRIES
|
||||
+ " tries. Disconnecting.");
|
||||
this.disconnect();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (readLock.tryLock())
|
||||
try {
|
||||
// check to see if SessionID == null;
|
||||
if (this.sessionID == null)
|
||||
this.sessionID = new SessionID(this.crypto.getSecretKeyBytes());
|
||||
|
||||
// First and foremost, check to see if we the Crypto is initted yet
|
||||
if (!this.crypto.initialized())
|
||||
this.crypto.initialize(this);
|
||||
// Get ByteBuffers out of pool.
|
||||
ByteBuffer bb = Network.byteBufferPool.getBuffer(16);
|
||||
ByteBuffer decrypted = Network.byteBufferPool.getBuffer(16);
|
||||
// ByteBuffer bb = ByteBuffer.allocate(1024 * 4);
|
||||
|
||||
if (!this.crypto.initialized()) {
|
||||
++this.cryptoInitTries;
|
||||
if (this.cryptoInitTries >= MBServerStatics.MAX_CRYPTO_INIT_TRIES) {
|
||||
Logger.info("Failed to initialize after "
|
||||
+ MBServerStatics.MAX_CRYPTO_INIT_TRIES
|
||||
+ " tries. Disconnecting.");
|
||||
this.disconnect();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int totalBytesRead = 0;
|
||||
int lastRead = 0;
|
||||
do {
|
||||
try {
|
||||
bb.clear();
|
||||
decrypted.clear();
|
||||
lastRead = this.sockChan.read(bb);
|
||||
// On EOF on the SocketChannel, disconnect.
|
||||
if (lastRead <= -1) {
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
// check to see if SessionID == null;
|
||||
if (this.sessionID == null)
|
||||
this.sessionID = new SessionID(this.crypto.getSecretKeyBytes());
|
||||
if (lastRead == 0)
|
||||
continue;
|
||||
|
||||
// Get ByteBuffers out of pool.
|
||||
ByteBuffer bb = Network.byteBufferPool.getBuffer(16);
|
||||
ByteBuffer decrypted = Network.byteBufferPool.getBuffer(16);
|
||||
// ByteBuffer bb = ByteBuffer.allocate(1024 * 4);
|
||||
// ByteBuffer decrypted = ByteBuffer.allocate(lastRead);
|
||||
this.crypto.decrypt(bb, decrypted);
|
||||
this.factory.addData(decrypted);
|
||||
|
||||
int totalBytesRead = 0;
|
||||
int lastRead = 0;
|
||||
do {
|
||||
try {
|
||||
bb.clear();
|
||||
decrypted.clear();
|
||||
lastRead = this.sockChan.read(bb);
|
||||
// On EOF on the SocketChannel, disconnect.
|
||||
if (lastRead <= -1) {
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastRead == 0)
|
||||
continue;
|
||||
this.checkInternalFactory();
|
||||
|
||||
// ByteBuffer decrypted = ByteBuffer.allocate(lastRead);
|
||||
this.crypto.decrypt(bb, decrypted);
|
||||
this.factory.addData(decrypted);
|
||||
|
||||
|
||||
this.checkInternalFactory();
|
||||
totalBytesRead += lastRead;
|
||||
|
||||
totalBytesRead += lastRead;
|
||||
|
||||
|
||||
} catch (NotYetConnectedException e) {
|
||||
Logger.error(e.getLocalizedMessage());
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
} catch (NotYetConnectedException e) {
|
||||
Logger.error(e.getLocalizedMessage());
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
// TODO Should a closed channel be logged or just cleaned up?
|
||||
// this.logEXCEPTION(e);
|
||||
this.disconnect();
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
} catch (ClosedChannelException e) {
|
||||
// TODO Should a closed channel be logged or just cleaned up?
|
||||
// this.logEXCEPTION(e);
|
||||
this.disconnect();
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
|
||||
} catch (IOException e) {
|
||||
if ( e.getLocalizedMessage() != null && (!e.getLocalizedMessage().equals(MBServerStatics.EXISTING_CONNECTION_CLOSED) && !e.getLocalizedMessage().equals(MBServerStatics.RESET_BY_PEER))){
|
||||
Logger.info("Error Reading message opcode " + this.lastOpcode);
|
||||
Logger.error(e);
|
||||
}
|
||||
this.disconnect();
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
if (e.getLocalizedMessage() != null && (!e.getLocalizedMessage().equals(MBServerStatics.EXISTING_CONNECTION_CLOSED) && !e.getLocalizedMessage().equals(MBServerStatics.RESET_BY_PEER))) {
|
||||
Logger.info("Error Reading message opcode " + this.lastOpcode);
|
||||
Logger.error(e);
|
||||
}
|
||||
this.disconnect();
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
|
||||
} catch (Exception e){
|
||||
Logger.info("Error Reading message opcode " + this.lastOpcode);
|
||||
Logger.error(e);
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.info("Error Reading message opcode " + this.lastOpcode);
|
||||
Logger.error(e);
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (lastRead > 0);
|
||||
while (lastRead > 0);
|
||||
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
Network.byteBufferPool.putBuffer(decrypted);
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
Network.byteBufferPool.putBuffer(decrypted);
|
||||
|
||||
return totalBytesRead;
|
||||
return totalBytesRead;
|
||||
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a read lock! Skipping.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a read lock! Skipping.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
super.disconnect();
|
||||
try {
|
||||
@Override
|
||||
public void disconnect() {
|
||||
super.disconnect();
|
||||
try {
|
||||
|
||||
if (ConfigManager.serverType.equals(Enum.ServerType.WORLDSERVER))
|
||||
ConfigManager.worldServer.removeClient(this);
|
||||
else
|
||||
ConfigManager.loginServer.removeClient(this);
|
||||
if (ConfigManager.serverType.equals(Enum.ServerType.WORLDSERVER))
|
||||
ConfigManager.worldServer.removeClient(this);
|
||||
else
|
||||
ConfigManager.loginServer.removeClient(this);
|
||||
|
||||
// TODO There has to be a more direct way to do this...
|
||||
SessionManager.remSession(
|
||||
SessionManager.getSession(sessionID));
|
||||
} catch (NullPointerException e) {
|
||||
Logger
|
||||
.error(
|
||||
"Tried to remove improperly initialized session. Skipping." +
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
public void forceDisconnect() {
|
||||
super.disconnect();
|
||||
}
|
||||
// TODO There has to be a more direct way to do this...
|
||||
SessionManager.remSession(
|
||||
SessionManager.getSession(sessionID));
|
||||
} catch (NullPointerException e) {
|
||||
Logger
|
||||
.error(
|
||||
"Tried to remove improperly initialized session. Skipping." +
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters n setters
|
||||
*/
|
||||
public void forceDisconnect() {
|
||||
super.disconnect();
|
||||
}
|
||||
|
||||
public SessionID getSessionID() {
|
||||
return sessionID;
|
||||
}
|
||||
public SessionID getSessionID() {
|
||||
return sessionID;
|
||||
}
|
||||
|
||||
public byte[] getSecretKeyBytes() {
|
||||
return this.crypto.getSecretKeyBytes();
|
||||
}
|
||||
/*
|
||||
* Getters n setters
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convenience getters for SessionManager
|
||||
*/
|
||||
public Account getAccount() {
|
||||
return SessionManager.getAccount(this);
|
||||
}
|
||||
public byte[] getSecretKeyBytes() {
|
||||
return this.crypto.getSecretKeyBytes();
|
||||
}
|
||||
|
||||
public PlayerCharacter getPlayerCharacter() {
|
||||
return SessionManager.getPlayerCharacter(this);
|
||||
}
|
||||
/*
|
||||
* Convenience getters for SessionManager
|
||||
*/
|
||||
public Account getAccount() {
|
||||
return SessionManager.getAccount(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClientMsg(ClientNetMsg msg) {
|
||||
public PlayerCharacter getPlayerCharacter() {
|
||||
return SessionManager.getPlayerCharacter(this);
|
||||
}
|
||||
|
||||
Protocol protocolMsg = msg.getProtocolMsg();
|
||||
@Override
|
||||
public boolean handleClientMsg(ClientNetMsg msg) {
|
||||
|
||||
switch (protocolMsg) {
|
||||
case KEEPALIVESERVERCLIENT:
|
||||
this.setLastKeepAliveTime();
|
||||
break;
|
||||
// case ClientOpcodes.OpenVault:
|
||||
// case ClientOpcodes.Random:
|
||||
// case ClientOpcodes.DoorTryOpen:
|
||||
// case ClientOpcodes.SetSelectedObect:
|
||||
// case ClientOpcodes.MoveObjectToContainer:
|
||||
// case ClientOpcodes.ToggleSitStand:
|
||||
// case ClientOpcodes.SocialChannel:
|
||||
// case ClientOpcodes.OpenFriendsCondemnList:
|
||||
case SELLOBJECT:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
case MOVETOPOINT:
|
||||
case ARCCOMBATMODEATTACKING:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
default:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
}
|
||||
Protocol protocolMsg = msg.getProtocolMsg();
|
||||
|
||||
// Application protocol logging toggled via
|
||||
// DevCmd: netdebug on|off
|
||||
switch (protocolMsg) {
|
||||
case KEEPALIVESERVERCLIENT:
|
||||
this.setLastKeepAliveTime();
|
||||
break;
|
||||
// case ClientOpcodes.OpenVault:
|
||||
// case ClientOpcodes.Random:
|
||||
// case ClientOpcodes.DoorTryOpen:
|
||||
// case ClientOpcodes.SetSelectedObect:
|
||||
// case ClientOpcodes.MoveObjectToContainer:
|
||||
// case ClientOpcodes.ToggleSitStand:
|
||||
// case ClientOpcodes.SocialChannel:
|
||||
// case ClientOpcodes.OpenFriendsCondemnList:
|
||||
case SELLOBJECT:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
case MOVETOPOINT:
|
||||
case ARCCOMBATMODEATTACKING:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
default:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
}
|
||||
|
||||
if (MBServerStatics.DEBUG_PROTOCOL)
|
||||
applicationProtocolLogger(msg, MessageSource.SOURCE_CLIENT);
|
||||
// Application protocol logging toggled via
|
||||
// DevCmd: netdebug on|off
|
||||
|
||||
return ConfigManager.handler.handleClientMsg(msg); // *** Refactor : Null check then call
|
||||
}
|
||||
// Method logs detailed information about application
|
||||
// protocol traffic. Toggled at runtime via the
|
||||
// DevCmd netdebug on|off
|
||||
if (MBServerStatics.DEBUG_PROTOCOL)
|
||||
applicationProtocolLogger(msg, MessageSource.SOURCE_CLIENT);
|
||||
|
||||
private void applicationProtocolLogger(AbstractNetMsg msg, MessageSource origin) {
|
||||
return ConfigManager.handler.handleClientMsg(msg); // *** Refactor : Null check then call
|
||||
}
|
||||
|
||||
String outString = "";
|
||||
PlayerCharacter tempPlayer = null;
|
||||
private void applicationProtocolLogger(AbstractNetMsg msg, MessageSource origin) {
|
||||
|
||||
// Log the protocolMsg
|
||||
if (origin == MessageSource.SOURCE_CLIENT)
|
||||
outString = " Incoming protocolMsg: ";
|
||||
else
|
||||
outString = " Outgoing protocolMsg: ";
|
||||
String outString = "";
|
||||
PlayerCharacter tempPlayer = null;
|
||||
|
||||
Logger.info(outString
|
||||
+ Integer.toHexString(msg.getProtocolMsg().opcode)
|
||||
+ '/' + msg.getProtocolMsg());
|
||||
// Log the protocolMsg
|
||||
if (origin == MessageSource.SOURCE_CLIENT)
|
||||
outString = " Incoming protocolMsg: ";
|
||||
else
|
||||
outString = " Outgoing protocolMsg: ";
|
||||
|
||||
// Dump message contents using reflection
|
||||
tempPlayer = this.getPlayerCharacter();
|
||||
outString = "";
|
||||
outString += (tempPlayer == null) ? "PlayerUnknown" : tempPlayer.getFirstName() + ' '
|
||||
+ msg.toString();
|
||||
Logger.info(outString);
|
||||
}
|
||||
Logger.info(outString
|
||||
+ Integer.toHexString(msg.getProtocolMsg().opcode)
|
||||
+ '/' + msg.getProtocolMsg());
|
||||
|
||||
public void kickToLogin(int errCode, String message) {
|
||||
// Dump message contents using reflection
|
||||
tempPlayer = this.getPlayerCharacter();
|
||||
outString = "";
|
||||
outString += (tempPlayer == null) ? "PlayerUnknown" : tempPlayer.getFirstName() + ' '
|
||||
+ msg.toString();
|
||||
Logger.info(outString);
|
||||
}
|
||||
// Method logs detailed information about application
|
||||
// protocol traffic. Toggled at runtime via the
|
||||
// DevCmd netdebug on|off
|
||||
|
||||
LoginErrorMsg lom = new LoginErrorMsg(errCode, message);
|
||||
public void kickToLogin(int errCode, String message) {
|
||||
|
||||
if (!sendMsg(lom))
|
||||
Logger.error("Failed to send message"); // TODO Do we just accept this failure to send Msg?
|
||||
LoginErrorMsg lom = new LoginErrorMsg(errCode, message);
|
||||
|
||||
DisconnectJob dj = new DisconnectJob(this);
|
||||
JobScheduler.getInstance().scheduleJob(dj, 250);
|
||||
if (!sendMsg(lom))
|
||||
Logger.error("Failed to send message"); // TODO Do we just accept this failure to send Msg?
|
||||
|
||||
}
|
||||
DisconnectJob dj = new DisconnectJob(this);
|
||||
JobScheduler.getInstance().scheduleJob(dj, 250);
|
||||
|
||||
public final String getClientIpAddress() {
|
||||
return this.clientIpAddress;
|
||||
}
|
||||
}
|
||||
|
||||
public final String getClientIpAddress() {
|
||||
return this.clientIpAddress;
|
||||
}
|
||||
|
||||
// Enumeration of a message's origin for logging purposes
|
||||
private enum MessageSource {
|
||||
|
||||
SOURCE_CLIENT,
|
||||
SOURCE_SERVER
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user