@Override public IMessage recognize(ByteBuffer buf) throws MessageParseException { // 长度尚不足,确保可读长度超过4字节 if (buf.remaining() < IMessage.MIN_MESSAGE_LENGTH) { return null; } // 读取前4字节 int len = buf.getShort(); // 预期长度 short type = buf.getShort(); if (type == MessageType.FLASH_POLICY) { // Policy请求 boolean finished = false; // 找到结束的'\0'标志 while (buf.remaining() > 0) { byte b = buf.get(); if (b == 0) { finished = true; break; } } if (finished) { // Policy请求全部接收完毕 } else { // 不足,下次继续 return null; } } else { // 普通消息,检查长度是否满足 if (buf.remaining() < len - IMessage.HEADER_SIZE) { return null; } } return createMessage(type); }
/** * Get the remaining bytes that could be read from a file or ByteBuffer. * * @return Number of remaining bytes */ private long getRemainingBytes() { if (!useLoadBuf) { return in.remaining(); } try { return channelSize - channel.position() + in.remaining(); } catch (Exception e) { log.error("Error getRemainingBytes", e); return 0; } }
void check() throws JMSException, AMQFrameDecodingException { for (Object m : received) { ByteBuffer buffer = ((JMSBytesMessage) m).getData(); FieldTable actual = FieldTableFactory.newFieldTable(buffer, buffer.remaining()); for (String key : _expected.keys()) { assertEquals( "Values for " + key + " did not match", _expected.getObject(key), actual.getObject(key)); } } }
@Override protected boolean doDecode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception { final int origonPos = in.position(); if (in.remaining() < 16) { in.position(origonPos); return false; } int magic = in.getInt(); if (magic != Const.MAGIC) throw new IOException("flag error, except: " + Const.MAGIC + ", but get " + magic); int request = in.getInt(); int pcode = in.getInt(); int len = in.getInt(); if (in.remaining() < len) { in.position(origonPos); return false; } byte[] data = new byte[len]; in.get(data); BaseResponsePacket packet = PacketCode.createPacket(pcode, request, data); out.write(packet); return true; }
/** * Load enough bytes from channel to buffer. After the loading process, the caller can make sure * the amount in buffer is of size 'amount' if we haven't reached the end of channel. * * @param amount The amount of bytes in buffer after returning, no larger than bufferSize * @param reload Whether to reload or append */ private void fillBuffer(long amount, boolean reload) { try { if (amount > bufferSize) { amount = bufferSize; } // Read all remaining bytes if the requested amount reach the end // of channel. if (channelSize - channel.position() < amount) { amount = channelSize - channel.position(); } if (in == null) { switch (bufferType) { case HEAP: in = ByteBuffer.allocate(bufferSize, false); break; case DIRECT: in = ByteBuffer.allocate(bufferSize, true); break; case AUTO: in = ByteBuffer.allocate(bufferSize); break; default: in = ByteBuffer.allocate(bufferSize); } channel.read(in.buf()); in.flip(); useLoadBuf = true; } if (!useLoadBuf) { return; } if (reload || in.remaining() < amount) { if (!reload) { in.compact(); } else { in.clear(); } channel.read(in.buf()); in.flip(); } } catch (Exception e) { log.error("Error fillBuffer", e); } }
/** * Get the current position in a file or ByteBuffer. * * @return Current position in a file */ private long getCurrentPosition() { long pos; if (!useLoadBuf) { return in.position(); } try { if (in != null) { pos = (channel.position() - in.remaining()); } else { pos = channel.position(); } return pos; } catch (Exception e) { log.error("Error getCurrentPosition", e); return 0; } }
/** {@inheritDoc} */ public synchronized ITag readTag() { long oldPos = getCurrentPosition(); ITag tag = readTagHeader(); if (tagPosition == 0 && tag.getDataType() != TYPE_METADATA && generateMetadata) { // Generate initial metadata automatically setCurrentPosition(oldPos); KeyFrameMeta meta = analyzeKeyFrames(); tagPosition++; if (meta != null) { return createFileMeta(); } } ByteBuffer body = ByteBuffer.allocate(tag.getBodySize(), false); // XXX Paul: this assists in 'properly' handling damaged FLV files long newPosition = getCurrentPosition() + tag.getBodySize(); if (newPosition <= getTotalBytes()) { int limit; while (getCurrentPosition() < newPosition) { fillBuffer(newPosition - getCurrentPosition()); if (getCurrentPosition() + in.remaining() > newPosition) { limit = in.limit(); in.limit((int) (newPosition - getCurrentPosition()) + in.position()); body.put(in); in.limit(limit); } else { body.put(in); } } body.flip(); tag.setBody(body); tagPosition++; } return tag; }
/** Tests that the send filter correctly prepends the message length. */ public void testSend() { int len = 1000; byte[] sendData = getByteSequence(len); ByteBuffer buf = ByteBuffer.allocate(len + 4, false); buf.putInt(len); buf.put(sendData); buf = buf.asReadOnlyBuffer(); buf.flip(); byte[] expected = new byte[buf.remaining()]; buf.get(expected); assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); harness.send(sendData); assertEquals(1, sentMessages.size()); assertEquals(0, receivedMessages.size()); byte[] actual = sentMessages.get(0); assertTrue("Incorrect send!", Arrays.equals(actual, expected)); }
private void addToList(List<byte[]> list, ByteBuffer buf) { byte[] bytes = new byte[buf.remaining()]; buf.get(bytes); list.add(bytes); }