List of usage examples for io.netty.buffer ByteBuf readableBytes
public abstract int readableBytes();
From source file:com.github.sparkfy.network.protocol.MessageWithHeader.java
License:Apache License
/** * Construct a new MessageWithHeader./* w w w . ja va 2s. c om*/ * * @param managedBuffer the {@link ManagedBuffer} that the message body came from. This needs to * be passed in so that the buffer can be freed when this message is * deallocated. Ownership of the caller's reference to this buffer is * transferred to this class, so if the caller wants to continue to use the * ManagedBuffer in other messages then they will need to call retain() on * it before passing it to this constructor. This may be null if and only if * `body` is a {@link FileRegion}. * @param header the message header. * @param body the message body. Must be either a {@link ByteBuf} or a {@link FileRegion}. * @param bodyLength the length of the message body, in bytes. */ MessageWithHeader(ManagedBuffer managedBuffer, ByteBuf header, Object body, long bodyLength) { Preconditions.checkArgument(body instanceof ByteBuf || body instanceof FileRegion, "Body must be a ByteBuf or a FileRegion."); this.managedBuffer = managedBuffer; this.header = header; this.headerLength = header.readableBytes(); this.body = body; this.bodyLength = bodyLength; }
From source file:com.github.sparkfy.network.protocol.MessageWithHeaderSuite.java
License:Apache License
@Test public void testByteBufBody() throws Exception { ByteBuf header = Unpooled.copyLong(42); ByteBuf bodyPassedToNettyManagedBuffer = Unpooled.copyLong(84); assertEquals(1, header.refCnt());//from w w w .ja v a 2 s.c o m assertEquals(1, bodyPassedToNettyManagedBuffer.refCnt()); ManagedBuffer managedBuf = new NettyManagedBuffer(bodyPassedToNettyManagedBuffer); Object body = managedBuf.convertToNetty(); assertEquals(2, bodyPassedToNettyManagedBuffer.refCnt()); assertEquals(1, header.refCnt()); MessageWithHeader msg = new MessageWithHeader(managedBuf, header, body, managedBuf.size()); ByteBuf result = doWrite(msg, 1); assertEquals(msg.count(), result.readableBytes()); assertEquals(42, result.readLong()); assertEquals(84, result.readLong()); assert (msg.release()); assertEquals(0, bodyPassedToNettyManagedBuffer.refCnt()); assertEquals(0, header.refCnt()); }
From source file:com.github.sparkfy.network.protocol.MessageWithHeaderSuite.java
License:Apache License
private void testFileRegionBody(int totalWrites, int writesPerCall) throws Exception { ByteBuf header = Unpooled.copyLong(42); int headerLength = header.readableBytes(); TestFileRegion region = new TestFileRegion(totalWrites, writesPerCall); MessageWithHeader msg = new MessageWithHeader(null, header, region, region.count()); ByteBuf result = doWrite(msg, totalWrites / writesPerCall); assertEquals(headerLength + region.count(), result.readableBytes()); assertEquals(42, result.readLong()); for (long i = 0; i < 8; i++) { assertEquals(i, result.readLong()); }//from w w w.j av a2 s. c o m assert (msg.release()); }
From source file:com.github.sparkfy.network.protocol.StreamChunkId.java
License:Apache License
public static StreamChunkId decode(ByteBuf buffer) { assert buffer.readableBytes() >= 8 + 4; long streamId = buffer.readLong(); int chunkIndex = buffer.readInt(); return new StreamChunkId(streamId, chunkIndex); }
From source file:com.github.sparkfy.network.util.TransportFrameDecoder.java
License:Apache License
@Override public void channelRead(ChannelHandlerContext ctx, Object data) throws Exception { ByteBuf in = (ByteBuf) data; buffers.add(in);//ww w . j av a 2 s . c o m totalSize += in.readableBytes(); while (!buffers.isEmpty()) { // First, feed the interceptor, and if it's still, active, try again. if (interceptor != null) { ByteBuf first = buffers.getFirst(); int available = first.readableBytes(); if (feedInterceptor(first)) { assert !first.isReadable() : "Interceptor still active but buffer has data."; } int read = available - first.readableBytes(); if (read == available) { buffers.removeFirst().release(); } totalSize -= read; } else { // Interceptor is not active, so try to decode one frame. ByteBuf frame = decodeNext(); if (frame == null) { break; } ctx.fireChannelRead(frame); } } }
From source file:com.github.sparkfy.network.util.TransportFrameDecoder.java
License:Apache License
private long decodeFrameSize() { if (nextFrameSize != UNKNOWN_FRAME_SIZE || totalSize < LENGTH_SIZE) { return nextFrameSize; }//from w w w.ja v a 2 s . c o m // We know there's enough data. If the first buffer contains all the data, great. Otherwise, // hold the bytes for the frame length in a composite buffer until we have enough data to read // the frame size. Normally, it should be rare to need more than one buffer to read the frame // size. ByteBuf first = buffers.getFirst(); if (first.readableBytes() >= LENGTH_SIZE) { nextFrameSize = first.readLong() - LENGTH_SIZE; totalSize -= LENGTH_SIZE; if (!first.isReadable()) { buffers.removeFirst().release(); } return nextFrameSize; } while (frameLenBuf.readableBytes() < LENGTH_SIZE) { ByteBuf next = buffers.getFirst(); int toRead = Math.min(next.readableBytes(), LENGTH_SIZE - frameLenBuf.readableBytes()); frameLenBuf.writeBytes(next, toRead); if (!next.isReadable()) { buffers.removeFirst().release(); } } nextFrameSize = frameLenBuf.readLong() - LENGTH_SIZE; totalSize -= LENGTH_SIZE; frameLenBuf.clear(); return nextFrameSize; }
From source file:com.github.sparkfy.network.util.TransportFrameDecoder.java
License:Apache License
private ByteBuf decodeNext() throws Exception { long frameSize = decodeFrameSize(); if (frameSize == UNKNOWN_FRAME_SIZE || totalSize < frameSize) { return null; }/*from ww w. j av a2s. co m*/ // Reset size for next frame. nextFrameSize = UNKNOWN_FRAME_SIZE; Preconditions.checkArgument(frameSize < MAX_FRAME_SIZE, "Too large frame: %s", frameSize); Preconditions.checkArgument(frameSize > 0, "Frame length should be positive: %s", frameSize); // If the first buffer holds the entire frame, return it. int remaining = (int) frameSize; if (buffers.getFirst().readableBytes() >= remaining) { return nextBufferForFrame(remaining); } // Otherwise, create a composite buffer. CompositeByteBuf frame = buffers.getFirst().alloc().compositeBuffer(); while (remaining > 0) { ByteBuf next = nextBufferForFrame(remaining); remaining -= next.readableBytes(); frame.addComponent(next).writerIndex(frame.writerIndex() + next.readableBytes()); } assert remaining == 0; return frame; }
From source file:com.github.sparkfy.network.util.TransportFrameDecoder.java
License:Apache License
/** * Takes the first buffer in the internal list, and either adjust it to fit in the frame * (by taking a slice out of it) or remove it from the internal list. */// w ww.ja v a2 s.c o m private ByteBuf nextBufferForFrame(int bytesToRead) { ByteBuf buf = buffers.getFirst(); ByteBuf frame; if (buf.readableBytes() > bytesToRead) { frame = buf.retain().readSlice(bytesToRead); totalSize -= bytesToRead; } else { frame = buf; buffers.removeFirst(); totalSize -= frame.readableBytes(); } return frame; }
From source file:com.github.sylvek.wsmqttfwd.decoder.ConnectDecoder.java
License:Open Source License
@Override public ConnectMessage decode(AttributeMap ctx, ByteBuf in) throws UnsupportedEncodingException { in.resetReaderIndex();//from w w w .ja v a2 s. c o m //Common decoding part ConnectMessage message = new ConnectMessage(); if (!decodeCommonHeader(message, 0x00, in)) { in.resetReaderIndex(); return null; } int remainingLength = message.getRemainingLength(); int start = in.readerIndex(); int protocolNameLen = in.readUnsignedShort(); byte[] encProtoName; String protoName; Attribute<Integer> versionAttr = ctx.attr(PROTOCOL_VERSION); switch (protocolNameLen) { case 6: //MQTT version 3.1 "MQIsdp" //ProtocolName 8 bytes or 6 bytes if (in.readableBytes() < 10) { in.resetReaderIndex(); return null; } encProtoName = new byte[6]; in.readBytes(encProtoName); protoName = new String(encProtoName, "UTF-8"); if (!"MQIsdp".equals(protoName)) { in.resetReaderIndex(); throw new CorruptedFrameException("Invalid protoName: " + protoName); } message.setProtocolName(protoName); versionAttr.set((int) Utils.VERSION_3_1); break; case 4: //MQTT version 3.1.1 "MQTT" //ProtocolName 6 bytes if (in.readableBytes() < 8) { in.resetReaderIndex(); return null; } encProtoName = new byte[4]; in.readBytes(encProtoName); protoName = new String(encProtoName, "UTF-8"); if (!"MQTT".equals(protoName)) { in.resetReaderIndex(); throw new CorruptedFrameException("Invalid protoName: " + protoName); } message.setProtocolName(protoName); versionAttr.set((int) Utils.VERSION_3_1_1); break; default: //protocol broken throw new CorruptedFrameException("Invalid protoName size: " + protocolNameLen); } //ProtocolVersion 1 byte (value 0x03 for 3.1, 0x04 for 3.1.1) message.setProtocolVersion(in.readByte()); if (message.getProtocolVersion() == Utils.VERSION_3_1_1) { //if 3.1.1, check the flags (dup, retain and qos == 0) if (message.isDupFlag() || message.isRetainFlag() || message.getQos() != AbstractMessage.QOSType.MOST_ONE) { throw new CorruptedFrameException("Received a CONNECT with fixed header flags != 0"); } //check if this is another connect from the same client on the same session Attribute<Boolean> connectAttr = ctx.attr(ConnectDecoder.CONNECT_STATUS); Boolean alreadyConnected = connectAttr.get(); if (alreadyConnected == null) { //never set connectAttr.set(true); } else if (alreadyConnected) { throw new CorruptedFrameException("Received a second CONNECT on the same network connection"); } } //Connection flag byte connFlags = in.readByte(); if (message.getProtocolVersion() == Utils.VERSION_3_1_1) { if ((connFlags & 0x01) != 0) { //bit(0) of connection flags is != 0 throw new CorruptedFrameException("Received a CONNECT with connectionFlags[0(bit)] != 0"); } } boolean cleanSession = ((connFlags & 0x02) >> 1) == 1; boolean willFlag = ((connFlags & 0x04) >> 2) == 1; byte willQos = (byte) ((connFlags & 0x18) >> 3); if (willQos > 2) { in.resetReaderIndex(); throw new CorruptedFrameException("Expected will QoS in range 0..2 but found: " + willQos); } boolean willRetain = ((connFlags & 0x20) >> 5) == 1; boolean passwordFlag = ((connFlags & 0x40) >> 6) == 1; boolean userFlag = ((connFlags & 0x80) >> 7) == 1; //a password is true iff user is true. if (!userFlag && passwordFlag) { in.resetReaderIndex(); throw new CorruptedFrameException( "Expected password flag to true if the user flag is true but was: " + passwordFlag); } message.setCleanSession(cleanSession); message.setWillFlag(willFlag); message.setWillQos(willQos); message.setWillRetain(willRetain); message.setPasswordFlag(passwordFlag); message.setUserFlag(userFlag); //Keep Alive timer 2 bytes //int keepAlive = Utils.readWord(in); int keepAlive = in.readUnsignedShort(); message.setKeepAlive(keepAlive); if ((remainingLength == 12 && message.getProtocolVersion() == Utils.VERSION_3_1) || (remainingLength == 10 && message.getProtocolVersion() == Utils.VERSION_3_1_1)) { return message; } //Decode the ClientID String clientID = Utils.decodeString(in); if (clientID == null) { in.resetReaderIndex(); return null; } message.setClientID(clientID); //Decode willTopic if (willFlag) { String willTopic = Utils.decodeString(in); if (willTopic == null) { in.resetReaderIndex(); return null; } message.setWillTopic(willTopic); } //Decode willMessage if (willFlag) { byte[] willMessage = Utils.readFixedLengthContent(in); if (willMessage == null) { in.resetReaderIndex(); return null; } message.setWillMessage(willMessage); } //Compatibility check with v3.0, remaining length has precedence over //the user and password flags int readed = in.readerIndex() - start; if (readed == remainingLength) { return message; } //Decode username if (userFlag) { String userName = Utils.decodeString(in); if (userName == null) { in.resetReaderIndex(); return null; } message.setUsername(userName); } readed = in.readerIndex() - start; if (readed == remainingLength) { return message; } //Decode password if (passwordFlag) { byte[] password = Utils.readFixedLengthContent(in); if (password == null) { in.resetReaderIndex(); return null; } message.setPassword(password); } return message; }
From source file:com.github.sylvek.wsmqttfwd.decoder.DemuxDecoder.java
License:Open Source License
private boolean genericDecodeCommonHeader(AbstractMessage message, Integer expectedFlagsOpt, ByteBuf in) { //Common decoding part if (in.readableBytes() < 2) { return false; }/*w w w .j a va 2s . co m*/ byte h1 = in.readByte(); byte messageType = (byte) ((h1 & 0x00F0) >> 4); byte flags = (byte) (h1 & 0x0F); if (expectedFlagsOpt != null) { int expectedFlags = expectedFlagsOpt; if ((byte) expectedFlags != flags) { String hexExpected = Integer.toHexString(expectedFlags); String hexReceived = Integer.toHexString(flags); throw new CorruptedFrameException( String.format("Received a message with fixed header flags (%s) != expected (%s)", hexReceived, hexExpected)); } } boolean dupFlag = ((byte) ((h1 & 0x0008) >> 3) == 1); byte qosLevel = (byte) ((h1 & 0x0006) >> 1); boolean retainFlag = ((byte) (h1 & 0x0001) == 1); int remainingLength = Utils.decodeRemainingLength(in); if (remainingLength == -1) { return false; } message.setMessageType(messageType); message.setDupFlag(dupFlag); try { message.setQos(AbstractMessage.QOSType.valueOf(qosLevel)); } catch (IllegalArgumentException e) { throw new CorruptedFrameException(String.format("Received an invalid QOS: %s", e.getMessage()), e); } message.setRetainFlag(retainFlag); message.setRemainingLength(remainingLength); return true; }