package protocol.soe; import java.nio.ByteBuffer; import java.util.Vector; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; import protocol.swg.SWGMessage; public class DataChannelA extends SOEMessage implements ISequenced, ICombinable { private Vector<IoBuffer> messages; private short sequence; public DataChannelA(SimpleBufferAllocator bufferPool) { this.bufferPool = bufferPool; } public DataChannelA(IoBuffer data, SimpleBufferAllocator bufferPool) { super(data); sequence = data.getShort(2); this.bufferPool = bufferPool; } public boolean addMessage(SWGMessage message) { return addMessage(message.serialize()); } public boolean addMessage(IoBuffer buffer) { byte[] messageData = buffer.array(); int messageLength = messageData.length; //System.out.println(messageLength); if(messageLength > 487) return false; if (messages == null) messages = new Vector<IoBuffer>(); if (messages.size() == 1) { if (messageLength + (messageLength > 254 ? 3 : 1) + 2 > getRemainingSize()) return false; } else if(messages.size() > 1) { if (messageLength + (messageLength > 254 ? 3 : 1) > getRemainingSize()) return false; } messages.add(buffer); if(getRemainingSize() < 1) { messages.remove(buffer); return false; } return true; } @Override public void deserialize(IoBuffer data) { } @Override public IoBuffer serialize() { IoBuffer message = bufferPool.allocate(496, false); message.putShort((short)9); message.putShort((short)sequence); if (messages.size() > 1) { message.putShort((short)0x0019); for (int i = 0; i < messages.size(); i++) { message.put(getMessageSize(i)); message.put(messages.get(i).array()); } } else { if(message.remaining() >= messages.get(0).array().length) message.put(messages.get(0).array()); } int size = message.position(); message = IoBuffer.allocate(size).put(message.array(), 0, size); return message.flip(); } public IoBuffer[] getMessages() { messages = new Vector<IoBuffer>(); IoBuffer buffer = data; buffer.position(4); if (buffer.getShort() == 0x19) { while (buffer.position() < data.array().length && buffer.hasRemaining()) { short length = (short)(buffer.get() & 0xFF); if (length == 255) length = buffer.getShort(); //if (length > Utilities.getActiveLengthOfBuffer(buffer) - buffer.position()) // break; if (length > buffer.remaining() || !buffer.hasArray() || length < 0) break; messages.add(bufferPool.allocate(length, false).put(buffer.array(), buffer.position(), length)); buffer.position(buffer.position() + length); } } else { int length = data.array().length - 4; messages.add(bufferPool.allocate(length, false).put(buffer.array(), 4, length)); } IoBuffer [] tmp = new IoBuffer[messages.size()]; messages.toArray(tmp); return tmp; } private byte[] getMessageSize(int index) { int messageLength = messages.get(index).array().length; ByteBuffer result = ByteBuffer.allocate(3); if (messageLength > 254) result.put((byte)0xff).putShort((short)messageLength); else result.put((byte)messageLength); int size = result.position(); return ByteBuffer.allocate(size).put(result.array(), 0, size).array(); } public int getSize() { int size = 4; // header int currentLength; if (messages.size() > 1) { size += 2; for (int i = 0; i < messages.size(); i++) { currentLength = messages.get(i).array().length; size += currentLength + (currentLength > 254 ? 3 : 1); } } else { size += messages.get(0).array().length; } return size; } public short getSequence() { return data.getShort(2); } public void setSequence(short sequence) { this.sequence = sequence; } private int getRemainingSize() { return 493 - getSize(); } public boolean hasMessages() { return messages != null && messages.size() > 0; } }