package edu.washington.cs.oneswarm.f2f.messaging; import java.util.logging.Level; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.gudy.azureus2.core3.util.DirectByteBufferPool; import com.aelitis.azureus.core.peermanager.messaging.Message; import com.aelitis.azureus.core.peermanager.messaging.MessageException; public class OSF2FChannelDataMsg extends OSF2FChannelMsg { public static final int BASE_LENGTH = 4; private String description = null; private final byte version; private final int channelID; private final DirectByteBuffer[] buffer = new DirectByteBuffer[2]; private int messageLength; public OSF2FChannelDataMsg(byte _version, int channelID, DirectByteBuffer data) { super(channelID); this.version = _version; this.channelID = channelID; this.buffer[1] = data; updateMessageLength(); } private void updateMessageLength() { if (buffer[1] != null) { messageLength = BASE_LENGTH + buffer[1].remaining(DirectByteBuffer.SS_MSG); } else { messageLength = BASE_LENGTH; } } public DirectByteBuffer getPayload() { return buffer[1]; } @Override public Message deserialize(DirectByteBuffer data, byte version) throws MessageException { if (data == null) { throw new MessageException("[" + getID() + "] decode error: data == null"); } if (data.remaining(DirectByteBuffer.SS_MSG) < BASE_LENGTH) { throw new MessageException("[" + getID() + "] decode error: payload.remaining[" + data.remaining(DirectByteBuffer.SS_MSG) + "] < " + BASE_LENGTH); } int channelID = data.getInt(DirectByteBuffer.SS_MSG); if (logger.isLoggable(Level.FINEST)) { logger.finest("Deserialized: " + getDescription()); } return new OSF2FChannelDataMsg(version, channelID, data); } @Override public String getID() { return OSF2FMessage.ID_OS_CHANNEL_DATA_MSG; } @Override public byte[] getIDBytes() { return OSF2FMessage.ID_OS_CHANNEL_DATA_MSG_BYTES; } @Override public String getFeatureID() { return OSF2FMessage.OS_FEATURE_ID; } @Override public int getFeatureSubID() { return OSF2FMessage.SUBID_OS_CHANNEL_DATA_MSG; } @Override public int getType() { return Message.TYPE_DATA_PAYLOAD; } @Override public byte getVersion() { return version; }; @Override public String getDescription() { if (description == null) { description = OSF2FMessage.ID_OS_CHANNEL_DATA_MSG + "\tchannel=" + channelID + "\tbytes="; if (buffer[1] != null) description += buffer[1].remaining(DirectByteBuffer.SS_MSG); } return description; } @Override public void destroy() { for (int i = 0; i < buffer.length; i++) { if (buffer[i] != null) { buffer[i].returnToPool(); } } } @Override public DirectByteBuffer[] getData() { if (buffer[0] == null) { buffer[0] = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_MSG, BASE_LENGTH); buffer[0].putInt(DirectByteBuffer.SS_MSG, channelID); buffer[0].flip(DirectByteBuffer.SS_MSG); } if (logger.isLoggable(Level.FINEST)) { logger.finest("Serialized: " + getDescription()); } return buffer; } // used to remove all messages for a given channel from the queue @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (this == obj) return true; if (obj instanceof OSF2FChannelDataMsg) { OSF2FChannelDataMsg other = (OSF2FChannelDataMsg) obj; if (other.getChannelId() == this.getChannelId()) { return true; } } return false; } @Override public int getMessageSize() { return messageLength; } public DirectByteBuffer transferPayload() { DirectByteBuffer payload = buffer[1]; buffer[1] = null; return payload; } public void updatePayload(DirectByteBuffer newPayload) { if (buffer[1] != null) { buffer[1].returnToPool(); } buffer[1] = newPayload; updateMessageLength(); } }