package network; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Queue; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; import utils.collections.NonBlockingHashMap; public class Client { private SocketAddress address; private Queue<IoBuffer> packetQueue = new LinkedBlockingQueue<IoBuffer>(); private volatile boolean isOutOfOrder = false; private int recieved = 0; private int sent = 0; private Map<Short, IoBuffer> sentPackets = Collections.synchronizedMap(new TreeMap<Short, IoBuffer>()); private Map<Short, IoBuffer> resentPackets = new NonBlockingHashMap<Short, IoBuffer>(); private List<IoBuffer> currentFragmentedPackets = new ArrayList<IoBuffer>(); private int currentFragTotalSize; private int currentFragRemainingSize; private short sequence; private short lastACKSequence; private long outOfOrderTimestamp; private SimpleBufferAllocator bufferPool = new SimpleBufferAllocator(); private int crc; private int connectionId; private NetworkDispatch dispatch; private short nextSequence = 0; private long accountID; private byte[] sessionKey; public Client(SocketAddress address, NetworkDispatch dispatch) { setAddress(address); setDispatch(dispatch); } public void sendPacket(IoBuffer packet) { packetQueue.add(packet); } public SocketAddress getAddress() { return address; } public void setAddress(SocketAddress address) { this.address = address; } public Queue<IoBuffer> getPacketQueue() { return packetQueue; } public void setPacketQueue(Queue<IoBuffer> packetQueue) { this.packetQueue = packetQueue; } public boolean isOutOfOrder() { return isOutOfOrder; } public void setOutOfOrder(boolean isOutOfOrder) { this.isOutOfOrder = isOutOfOrder; } public int getRecieved() { return recieved; } public void setRecieved(int recieved) { this.recieved = recieved; } public int getSent() { return sent; } public void setSent(int sent) { this.sent = sent; } public Map<Short, IoBuffer> getSentPackets() { return sentPackets; } public void setSentPackets(Map<Short, IoBuffer> sentPackets) { this.sentPackets = sentPackets; } public Map<Short, IoBuffer> getResentPackets() { return resentPackets; } public void setResentPackets(Map<Short, IoBuffer> resentPackets) { this.resentPackets = resentPackets; } public void addSentPacket(short sequence, IoBuffer packet) { sentPackets.put(sequence, packet); } public void removeSentPackets(short sequence) { Iterator<Entry<Short, IoBuffer>> it = sentPackets.entrySet().iterator(); synchronized(sentPackets) { while(it.hasNext()) { Entry<Short, IoBuffer> e = it.next(); if(e.getKey() > sequence) return; else it.remove(); } } } public void addResentPacket(short sequence, IoBuffer packet) { resentPackets.put(sequence, packet); } public void removeResentPackets(short sequence) { Iterator<Entry<Short, IoBuffer>> it = resentPackets.entrySet().iterator(); synchronized(resentPackets) { while(it.hasNext()) { Entry<Short, IoBuffer> e = it.next(); if(e.getKey() > sequence) return; else it.remove(); } } } public void incRecieved() { recieved++; } public void incSent() { sent++; } public short getSequence() { return sequence; } public void setSequence(short sequence) { this.sequence = sequence; } public short getLastACKSequence() { return lastACKSequence; } public void setLastACKSequence(short lastACKSequence) { this.lastACKSequence = lastACKSequence; } public long getOutOfOrderTimestamp() { return outOfOrderTimestamp; } public void setOutOfOrderTimestamp(long outOfOrderTimestamp) { this.outOfOrderTimestamp = outOfOrderTimestamp; } public SimpleBufferAllocator getBufferPool() { return bufferPool; } public void setBufferPool(SimpleBufferAllocator bufferPool) { this.bufferPool = bufferPool; } public int getCrc() { return crc; } public void setCrc(int crc) { this.crc = crc; } public NetworkDispatch getDispatch() { return dispatch; } public void setDispatch(NetworkDispatch dispatch) { this.dispatch = dispatch; } public void resendPackets(short sequence2) { Iterator<Short> it = sentPackets.keySet().iterator(); synchronized(sentPackets) { while(it.hasNext()) { Short e = it.next(); if(e == sequence) { it.remove(); continue; } if(e < lastACKSequence) continue; if(resentPackets.containsKey(e)) continue; if(e <= sequence) { dispatch.getServer().sendPacket(this, sentPackets.get(e)); resentPackets.put(e, sentPackets.get(e)); } } } } public List<IoBuffer> getCurrentFragmentedPackets() { return currentFragmentedPackets; } public void setCurrentFragmentedPackets(List<IoBuffer> currentFragmentedPackets) { this.currentFragmentedPackets = currentFragmentedPackets; } public int getCurrentFragTotalSize() { return currentFragTotalSize; } public void setCurrentFragTotalSize(int currentFragTotalSize) { this.currentFragTotalSize = currentFragTotalSize; } public int getCurrentFragRemainingSize() { return currentFragRemainingSize; } public void setCurrentFragRemainingSize(int currentFragRemainingSize) { this.currentFragRemainingSize = currentFragRemainingSize; } public int getConnectionId() { return connectionId; } public void setConnectionId(int connectionId) { this.connectionId = connectionId; } public short getNextSequence() { return nextSequence; } public void setNextSequence(short nextSequence) { this.nextSequence = nextSequence; } public long getAccountID() { return accountID; } public void setAccountID(long accountID) { this.accountID = accountID; } public byte[] getSessionKey() { return sessionKey; } public void setSessionKey(byte[] sessionKey) { this.sessionKey = sessionKey; } }