/** * 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); } }
/** Tests that two simple receives work. */ public void testMultipleSimpleReceives() { int len = 1000; byte[] expected = getByteSequence(len); ByteBuffer buf = ByteBuffer.allocate(len + 4, false); buf.putInt(len); buf.put(expected); buf = buf.asReadOnlyBuffer(); buf.flip(); assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); harness.recv(buf); assertEquals(0, sentMessages.size()); assertEquals(1, receivedMessages.size()); byte[] actual = receivedMessages.get(0); assertTrue("Incorrect recv!", Arrays.equals(actual, expected)); harness.recv(buf.rewind()); assertEquals(0, sentMessages.size()); assertEquals(2, receivedMessages.size()); actual = receivedMessages.get(1); assertTrue("Incorrect recv!", Arrays.equals(actual, expected)); }
/** Tests handling of exceptions during dispatch. */ public void testReceiveHandlingException() { int len = 1000; byte[] expected = getByteSequence(len); ByteBuffer buf = ByteBuffer.allocate(len + 4, false); buf.putInt(len); buf.put(expected); buf = buf.asReadOnlyBuffer(); buf.flip(); assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); RuntimeException expectedEx = new RuntimeException("Dummy exception for testing filter recv"); harness.setExceptionOnNextCompleteMessage(expectedEx); // This recv will fail to process the message harness.recv(buf); assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); // Send a second message, expecting the first to have been dropped. buf.rewind(); harness.recv(buf); assertEquals(0, sentMessages.size()); assertEquals(1, receivedMessages.size()); }
/** * Tests that complete messages are delivered even when the message arrives one byte at a time * from the network. Then tests that a second message can still be received all-at-once. */ public void testPartialOneByteReceives() { int len = 32; byte[] expected = getByteSequence(len); ByteBuffer buf = ByteBuffer.allocate(len + 4, false); buf.putInt(len); buf.put(expected); buf = buf.asReadOnlyBuffer(); buf.flip(); for (; buf.hasRemaining(); buf.skip(1)) { assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); ByteBuffer singleByte = buf.slice().limit(1); harness.recv(singleByte); } assertEquals(0, sentMessages.size()); assertEquals(1, receivedMessages.size()); byte[] actual = receivedMessages.get(0); assertTrue("Incorrect recv!", Arrays.equals(actual, expected)); harness.recv(buf.rewind()); assertEquals(0, sentMessages.size()); assertEquals(2, receivedMessages.size()); actual = receivedMessages.get(1); assertTrue("Incorrect recv!", Arrays.equals(actual, expected)); }
/** Tests handling of exceptions during dispatch. */ public void testReceiveHandlingExceptionPartial() { int len1 = 400; int len2 = 600; int len = len1 + len2; byte[] expected = getByteSequence(len); ByteBuffer buf = ByteBuffer.allocate(len + 4, false); buf.putInt(len); buf.put(expected); buf = buf.asReadOnlyBuffer(); buf.flip(); assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); ByteBuffer part1 = buf.slice().limit(len1 + 4); ByteBuffer part2 = ByteBuffer.allocate(len2 + len2 + 4, false); buf.rewind(); buf.skip(len1 + 4); part2.put(buf); buf.rewind(); buf.skip(len1 + 4); part2.putInt(len2); part2.put(buf); part2.flip(); assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); harness.recv(part1); assertEquals(0, sentMessages.size()); assertEquals(0, receivedMessages.size()); RuntimeException expectedEx = new RuntimeException("Dummy exception for testing filter recv"); harness.setExceptionOnNextCompleteMessage(expectedEx); // This recv should process the second message. harness.recv(part2); assertEquals(0, sentMessages.size()); assertEquals(1, receivedMessages.size()); byte[] actual = receivedMessages.get(0); assertEquals(len2, actual.length); }
@Override public ByteBuffer encodedContent() { ByteBuffer ret = ByteBuffer.allocate(32); ret.setAutoExpand(true); User.writeTo(user, ret); ret.flip(); return ret; }
/** * 转换为字节数组,包括长度 * * @return */ public byte[] getByties() { int size = countSize(); ByteBuffer buffer = ByteBuffer.allocate(size); writeBuffer(buffer); buffer.flip(); byte[] ret = new byte[size]; buffer.get(ret); return ret; }
/** {@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; }
/** * Create tag for metadata event. * * @return Metadata event tag */ private ITag createFileMeta() { // Create tag for onMetaData event ByteBuffer buf = ByteBuffer.allocate(1024); buf.setAutoExpand(true); Output out = new Output(buf); // Duration property out.writeString("onMetaData"); Map<Object, Object> props = new HashMap<Object, Object>(); props.put("duration", duration / 1000.0); if (firstVideoTag != -1) { long old = getCurrentPosition(); setCurrentPosition(firstVideoTag); readTagHeader(); fillBuffer(1); byte frametype = in.get(); // Video codec id props.put("videocodecid", frametype & MASK_VIDEO_CODEC); setCurrentPosition(old); } if (firstAudioTag != -1) { long old = getCurrentPosition(); setCurrentPosition(firstAudioTag); readTagHeader(); fillBuffer(1); byte frametype = in.get(); // Audio codec id props.put("audiocodecid", (frametype & MASK_SOUND_FORMAT) >> 4); setCurrentPosition(old); } props.put("canSeekToEnd", true); out.writeMap(props, new Serializer()); buf.flip(); ITag result = new Tag(IoConstants.TYPE_METADATA, 0, buf.limit(), null, 0); result.setBody(buf); return result; }
/** 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)); }