package gdwNet.server; import gdwNet.NETCONSTANTS; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SocketChannel; public abstract class BasicClientConnection { private static final int messagesPerUpdate = 5; private DatagramChannel udpConnection; private SocketChannel tcpConnection; protected final int sharedSecret; protected int id; private long lastHearthbeat; private long pongRequest; private boolean discoFlag; protected final BasicServer ref; public BasicClientConnection(ConnectionInfo info, BasicServer ref) { this.ref = ref; this.id = info.id; this.lastHearthbeat = System.currentTimeMillis(); this.discoFlag = false; this.pongRequest = -1L; this.udpConnection = info.udpConnection; this.tcpConnection = info.tcpConnection; this.sharedSecret = info.sharedSecret; try { this.udpConnection.configureBlocking(false); this.tcpConnection.configureBlocking(false); } catch (IOException e) { e.printStackTrace(); } } public boolean checkForDisconnect(long current) { if ((this.lastHearthbeat + NETCONSTANTS.HEARTBEAT_REQUESTIME) < current) { // check if ping request is needed if (pongRequest > -1L) { if ((pongRequest + NETCONSTANTS.PONG_TIMEOUT) < current) { // not alive this.discoFlag = true; return true; } } else { // send ping sendPing(current); } } return false; } public boolean isDisconnectFlaged() { return discoFlag; } private void sendPing(long currentTimeStamp) { ByteBuffer buf = ByteBuffer.allocate(1); buf.put(NETCONSTANTS.PING); buf.flip(); try { this.udpConnection.write(buf); this.pongRequest = currentTimeStamp; } catch (IOException e) { // somethings wrong shutdown the connection e.printStackTrace(); discoFlag = true; } } private void sendPong() { ByteBuffer buf = ByteBuffer.allocate(1); buf.put(NETCONSTANTS.PONG); buf.flip(); try { this.udpConnection.write(buf); } catch (IOException e) { // somethings wrong shutdown the connection e.printStackTrace(); discoFlag = true; } } public void disconnect() { try { this.tcpConnection.close(); this.udpConnection.close(); } catch (IOException e) { } } public void sendMSG(ByteBuffer msg, boolean reliable) { msg.flip(); try { if (reliable) { this.tcpConnection.write(msg); } else { this.udpConnection.write(msg); } } catch (IOException e) { this.discoFlag = true; } } public boolean pollInput() { int counter = 0; try { for (; counter < messagesPerUpdate; ++counter) { ByteBuffer buf = ByteBuffer .allocate(NETCONSTANTS.PACKAGELENGTH); if (tcpConnection.read(buf) > 0) { this.incommingMsg(buf, true); continue; } if (udpConnection.read(buf) > 0) { this.incommingMsg(buf, false); continue; } break; } } catch (IOException e) { //e.printStackTrace(); this.discoFlag = true; return false; } if (counter > 0) { this.lastHearthbeat = System.currentTimeMillis(); this.pongRequest = -1L; } return true; } private void incommingMsg(ByteBuffer buf, boolean wasReliable) { buf.position(0); switch (buf.get()) { case NETCONSTANTS.PING: sendPong(); break; case NETCONSTANTS.PONG: this.pongRequest = -1L; break; case NETCONSTANTS.MESSAGE: this.incommingMessage(buf, wasReliable); default: break; } } protected void revive(ConnectionInfo info) { this.tcpConnection = info.tcpConnection; this.udpConnection = info.udpConnection; this.discoFlag = false; } protected abstract void incommingMessage(ByteBuffer buf, boolean wasReliable); public int getId() { return id; } }