public OOOProtocolMessage parseMessage(TCByteBuffer[] data) throws TCProtocolException { int hdrLength = OOOProtocolMessageHeader.HEADER_LENGTH; if (hdrLength > data[0].limit()) { throw new TCProtocolException( "header not contained in first buffer: " + hdrLength + " > " + data[0].limit()); } OOOProtocolMessageHeader header = new OOOProtocolMessageHeader( data[0].duplicate().limit(OOOProtocolMessageHeader.HEADER_LENGTH)); header.validate(); TCByteBuffer msgData[]; if (header.getHeaderByteLength() < data[0].limit()) { msgData = new TCByteBuffer[data.length]; System.arraycopy(data, 0, msgData, 0, msgData.length); TCByteBuffer firstPayloadBuffer = msgData[0].duplicate(); firstPayloadBuffer.position(header.getHeaderByteLength()); msgData[0] = firstPayloadBuffer.slice(); } else { Assert.eval(data.length >= 1); msgData = new TCByteBuffer[data.length - 1]; System.arraycopy(data, 1, msgData, 0, msgData.length); } return messageFactory.createNewMessage(header, msgData); }
public void testGoodHeader() { byte[] data = getGoodHeader(); TCByteBuffer buffer = TCByteBufferFactory.getInstance(false, WireProtocolHeader.MAX_LENGTH); buffer.put(data); buffer.flip(); WireProtocolHeader header = new WireProtocolHeader(buffer); System.out.println(header); assertTrue(header.isChecksumValid()); assertTrue(header.getVersion() == WireProtocolHeader.VERSION_2); assertTrue(header.getHeaderLength() == 8); assertTrue(header.getTypeOfService() == 2); assertTrue(header.getTimeToLive() == 3); assertTrue(header.getTotalPacketLength() == 255); assertTrue(header.getChecksum() == 2744585179L); assertTrue( Arrays.equals( header.getSourceAddress(), new byte[] {(byte) 0xFF, (byte) 1, (byte) 0xFF, (byte) 1})); assertTrue( Arrays.equals( header.getDestinationAddress(), new byte[] {(byte) 1, (byte) 0xFF, (byte) 1, (byte) 0xFF})); assertTrue(header.getSourcePort() == 43605); assertTrue(header.getDestinationPort() == 21930); assertTrue(header.getMessageCount() == 5); assertTrue(header.getOptions().length == 0); try { header.validate(); } catch (WireProtocolHeaderFormatException e) { fail(e.getMessage()); } // changing data in the header should cause the checksum to need to be recomputed header.setVersion((byte) (header.getVersion() + 1)); assertFalse(header.isChecksumValid()); // Fix and validate the checksum header.computeChecksum(); assertTrue(header.isChecksumValid()); }
private TCNetworkMessage processPayloadData(TCConnection source, TCByteBuffer[] data) throws TCProtocolException { for (int i = 0; i < data.length; i++) { final TCByteBuffer buffer = data[i]; if (!buffer.hasRemaining()) { buffer.flip(); dataBytesNeeded -= buffer.limit(); bufferIndex++; if (dataBytesNeeded < 0) { throw new TCProtocolException("More data in buffers than expected"); } } else { break; } } if (0 == dataBytesNeeded) { if (bufferIndex != dataBuffers.length) { throw new TCProtocolException("Not all buffers consumed"); } // message is complete! TCNetworkMessage msg = createMessage(source, header, dataBuffers); if (logger.isDebugEnabled()) { logger.debug("Message complete on connection " + source + ": " + msg.toString()); } return msg; } Assert.eval(dataBytesNeeded > 0); // data portion not done, try again later return null; }
private TCNetworkMessage processHeaderData(TCConnection source, TCByteBuffer[] data) throws TCProtocolException { Assert.eval(data.length == 1); Assert.eval(data[0] == this.header.getDataBuffer()); if (!this.header.isHeaderLengthAvail()) { return null; } final TCByteBuffer buf = data[0]; final int headerLength = this.header.getHeaderByteLength(); final int bufferLength = buf.limit(); if (headerLength == AbstractTCNetworkHeader.LENGTH_NOT_AVAIL) { return null; } if ((headerLength < header.minLength) || (headerLength > header.maxLength) || (headerLength < bufferLength)) { // header data is screwed throw new TCProtocolException( "Invalid Header Length: " + headerLength + ", min: " + header.minLength + ", max: " + header.maxLength + ", bufLen: " + bufferLength); } if (bufferLength != headerLength) { // maybe we should support a way to swap out the header buffer for a larger sized one // instead of always mandating that the backing buffer behind a header have // enough capacity for the largest possible header for the given protocol. Just a thought // protocol header is bigger than min length, adjust buffer limit and continue buf.limit(headerLength); return null; } else { Assert.eval(bufferLength == headerLength); if (buf.position() == headerLength) { this.header.validate(); this.mode = MODE_DATA; this.dataBytesNeeded = computeDataLength(this.header); this.dataBuffers = null; if (this.dataBytesNeeded < 0) { throw new TCProtocolException("Negative data size detected: " + this.dataBytesNeeded); } // allow for message types with zero length data payload if (0 == this.dataBytesNeeded) { return createMessage(source, this.header, null); } return null; } else { // protocol header not completely read yet, do nothing return null; } } }