Example usage for io.netty.buffer ByteBuf isReadable

List of usage examples for io.netty.buffer ByteBuf isReadable

Introduction

In this page you can find the example usage for io.netty.buffer ByteBuf isReadable.

Prototype

public abstract boolean isReadable();

Source Link

Document

Returns true if and only if (this.writerIndex - this.readerIndex) is greater than 0 .

Usage

From source file:io.netlibs.bgp.netty.protocol.open.CapabilityCodec.java

License:Apache License

public static List<Capability> decodeCapabilities(final ByteBuf buffer) {
    final List<Capability> caps = new LinkedList<Capability>();

    while (buffer.isReadable()) {
        caps.add(decodeCapability(buffer));
    }//from w  ww.  ja va 2 s .  c  om

    return caps;
}

From source file:io.reactivex.netty.pipeline.ByteArrayPipelineConfigurator.java

License:Apache License

@Override
public void configureNewPipeline(ChannelPipeline pipeline) {
    pipeline.addLast(new ChannelDuplexHandler() {

        @Override//from  w ww. j a  va 2s  .c  o m
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            boolean handled = false;

            if (ByteBuf.class.isAssignableFrom(msg.getClass())) {
                ByteBuf byteBuf = (ByteBuf) msg;
                if (byteBuf.isReadable()) {
                    int readableBytes = byteBuf.readableBytes();
                    byte[] msgToPass = new byte[readableBytes];
                    byteBuf.readBytes(msgToPass);
                    handled = true;
                    ctx.fireChannelRead(msgToPass);
                }
            }
            if (!handled) {
                super.channelRead(ctx, msg);
            }
        }

        @Override
        public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
            if (msg instanceof byte[]) {
                byte[] msgAsBytes = (byte[]) msg;
                ByteBuf byteBuf = ctx.alloc().buffer(msgAsBytes.length).writeBytes(msgAsBytes);
                super.write(ctx, byteBuf, promise);
            } else {
                super.write(ctx, msg, promise); // pass-through
            }
        }
    });
}

From source file:io.reactivex.netty.protocol.http.client.ClientRequestResponseConverter.java

License:Apache License

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    Class<?> recievedMsgClass = msg.getClass();

    /**/*w w w  .  j  a va2s  . c om*/
     *  Issue: https://github.com/Netflix/RxNetty/issues/129
     *  The contentSubject changes in a different method userEventTriggered() when the connection is reused. If the
     *  connection reuse event is generated as part of execution of this method (for the specific issue, as part of
     *  super.channelRead(ctx, rxResponse); below) it will so happen that we invoke onComplete (below code when the
     *  first response completes) on the new subject as opposed to the old response subject.
     */
    @SuppressWarnings("rawtypes")
    final PublishSubject subjectToUse = contentSubject;

    if (HttpResponse.class.isAssignableFrom(recievedMsgClass)) {
        responseReceiveStartTimeMillis = Clock.newStartTimeMillis();
        eventsSubject.onEvent(HttpClientMetricsEvent.RESPONSE_HEADER_RECEIVED);
        @SuppressWarnings({ "rawtypes", "unchecked" })
        HttpResponse response = (HttpResponse) msg;

        @SuppressWarnings({ "rawtypes", "unchecked" })
        HttpClientResponse rxResponse = new HttpClientResponse(response, subjectToUse);
        Long keepAliveTimeoutSeconds = rxResponse.getKeepAliveTimeoutSeconds();
        if (null != keepAliveTimeoutSeconds) {
            ctx.channel().attr(KEEP_ALIVE_TIMEOUT_MILLIS_ATTR).set(keepAliveTimeoutSeconds * 1000);
        }

        if (!rxResponse.getHeaders().isKeepAlive()) {
            ctx.channel().attr(DISCARD_CONNECTION).set(true);
        }
        super.channelRead(ctx, rxResponse); // For FullHttpResponse, this assumes that after this call returns,
                                            // someone has subscribed to the content observable, if not the content will be lost.
    }

    if (HttpContent.class.isAssignableFrom(recievedMsgClass)) {// This will be executed if the incoming message is a FullHttpResponse or only HttpContent.
        eventsSubject.onEvent(HttpClientMetricsEvent.RESPONSE_CONTENT_RECEIVED);
        ByteBuf content = ((ByteBufHolder) msg).content();
        if (content.isReadable()) {
            invokeContentOnNext(content);
        }
        if (LastHttpContent.class.isAssignableFrom(recievedMsgClass)) {
            eventsSubject.onEvent(HttpClientMetricsEvent.RESPONSE_RECEIVE_COMPLETE,
                    Clock.onEndMillis(responseReceiveStartTimeMillis));
            subjectToUse.onCompleted();
        }
    } else if (!HttpResponse.class.isAssignableFrom(recievedMsgClass)) {
        invokeContentOnNext(msg);
    }
}

From source file:io.reactivex.netty.protocol.http.sse.ServerSentEventDecoder.java

License:Apache License

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

    if (null == sseEncodingCharset) {
        throw new IllegalArgumentException("Can not read SSE data as UTF-8 charset is not available.");
    }/*from w ww  . j a  va  2 s  . co  m*/

    while (in.isReadable()) {

        final int readerIndexAtStart = in.readerIndex();

        switch (state) {
        case SkipColonAndWhiteSpaces:
            if (skipColonAndWhiteSpaces(in)) {
                state = State.ReadFieldValue;
            }
            break;
        case SkipLineDelimitersAndSpaces:
            if (skipLineDelimiters(in)) {
                state = State.ReadFieldName;
            }
            break;
        case DiscardTillEOL:
            if (skipTillEOL(in)) {
                state = State.SkipLineDelimitersAndSpaces;
            }
            break;
        case ReadFieldName:
            final int indexOfColon = scanAndFindColon(in);

            if (-1 == indexOfColon) { // No colon found
                // Accumulate data into the field name buffer.
                if (null == incompleteData) {
                    incompleteData = ctx.alloc().buffer();
                }
                // accumulate into incomplete data buffer to be used when the full data arrives.
                incompleteData.writeBytes(in);
            } else {
                int fieldNameLengthInTheCurrentBuffer = indexOfColon - readerIndexAtStart;

                ByteBuf fieldNameBuffer;
                if (null != incompleteData) {
                    // Read the remaining data into the temporary buffer
                    in.readBytes(incompleteData, fieldNameLengthInTheCurrentBuffer);
                    fieldNameBuffer = incompleteData;
                    incompleteData = null;
                } else {
                    // Consume the data from the input buffer.
                    fieldNameBuffer = ctx.alloc().buffer(fieldNameLengthInTheCurrentBuffer,
                            fieldNameLengthInTheCurrentBuffer);
                    in.readBytes(fieldNameBuffer, fieldNameLengthInTheCurrentBuffer);
                }

                state = State.SkipColonAndWhiteSpaces; // We have read the field name, next we should skip colon & WS.
                try {
                    currentFieldType = readCurrentFieldTypeFromBuffer(fieldNameBuffer);
                } finally {
                    if (null == currentFieldType) {
                        state = State.DiscardTillEOL; // Ignore this event completely.
                    }
                    fieldNameBuffer.release();
                }
            }
            break;
        case ReadFieldValue:

            final int endOfLineStartIndex = scanAndFindEndOfLine(in);

            if (-1 == endOfLineStartIndex) { // End of line not found, accumulate data into a temporary buffer.
                if (null == incompleteData) {
                    incompleteData = ctx.alloc().buffer(in.readableBytes());
                }
                // accumulate into incomplete data buffer to be used when the full data arrives.
                incompleteData.writeBytes(in);
            } else { // Read the data till end of line into the value buffer.
                final int bytesAvailableInThisIteration = endOfLineStartIndex - readerIndexAtStart;
                if (null == incompleteData) {
                    incompleteData = ctx.alloc().buffer(bytesAvailableInThisIteration,
                            bytesAvailableInThisIteration);
                }
                incompleteData.writeBytes(in, bytesAvailableInThisIteration);

                switch (currentFieldType) {
                case Data:
                    if (incompleteData.isReadable()) {
                        out.add(ServerSentEvent.withEventIdAndType(lastEventId, lastEventType, incompleteData));
                    } else {
                        incompleteData.release();
                    }
                    break;
                case Id:
                    if (incompleteData.isReadable()) {
                        lastEventId = incompleteData;
                    } else {
                        incompleteData.release();
                        lastEventId = null;
                    }
                    break;
                case EventType:
                    if (incompleteData.isReadable()) {
                        lastEventType = incompleteData;
                    } else {
                        incompleteData.release();
                        lastEventType = null;
                    }
                    break;
                }
                /**
                 * Since all data is read, reset the incomplete data to null. Release of this buffer happens in
                 * the following ways
                 * 1) If this was a data buffer, it is released when ServerSentEvent is released.
                 * 2) If this was an eventId buffer, it is released when next Id arrives or when the connection
                 *     is closed.
                 * 3) If this was an eventType buffer, it is released when next type arrives or when the connection
                 *     is closed.
                 */
                incompleteData = null;
                state = State.SkipLineDelimitersAndSpaces; // Skip line delimiters after reading a field value completely.
            }
            break;
        }
    }

}

From source file:io.reactivex.netty.protocol.http.sse.ServerSentEventEncoder.java

License:Apache License

@Override
protected void encode(ChannelHandlerContext ctx, ServerSentEvent serverSentEvent, ByteBuf out)
        throws Exception {
    if (serverSentEvent.hasEventType()) { // Write event type, if available
        out.writeBytes(EVENT_PREFIX_BYTES);
        out.writeBytes(serverSentEvent.getEventType());
        out.writeBytes(NEW_LINE_AS_BYTES);
    }/*  w w w.j  a  v a  2s  . c  o m*/

    if (serverSentEvent.hasEventId()) { // Write event id, if available
        out.writeBytes(ID_PREFIX_AS_BYTES);
        out.writeBytes(serverSentEvent.getEventId());
        out.writeBytes(NEW_LINE_AS_BYTES);
    }

    final ByteBuf content = serverSentEvent.content();

    if (splitSseData) {
        while (content.isReadable()) { // Scan the buffer and split on new line into multiple data lines.
            final int readerIndexAtStart = content.readerIndex();
            int newLineIndex = content.forEachByte(new ByteBufProcessor() {
                @Override
                public boolean process(byte value) throws Exception {
                    return (char) value != '\n';
                }
            });
            if (-1 == newLineIndex) { // No new line, write the buffer as is.
                out.writeBytes(DATA_PREFIX_AS_BYTES);
                out.writeBytes(content);
                out.writeBytes(NEW_LINE_AS_BYTES);
            } else { // Write the buffer till the new line and then iterate this loop
                out.writeBytes(DATA_PREFIX_AS_BYTES);
                out.writeBytes(content, newLineIndex - readerIndexAtStart);
                content.readerIndex(content.readerIndex() + 1);
                out.writeBytes(NEW_LINE_AS_BYTES);
            }
        }
    } else { // write the buffer with data prefix and new line post fix.
        out.writeBytes(DATA_PREFIX_AS_BYTES);
        out.writeBytes(content);
        out.writeBytes(NEW_LINE_AS_BYTES);
    }
}

From source file:io.reactivex.netty.RxEventPipelineConfigurator.java

License:Apache License

@Override
public void configureNewPipeline(ChannelPipeline pipeline) {
    pipeline.addLast(new ChannelDuplexHandler() {

        @Override//from  w  w w . ja  va2 s .co m
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            boolean handled = false;
            if (ByteBuf.class.isAssignableFrom(msg.getClass())) {
                ByteBuf byteBuf = (ByteBuf) msg;
                if (byteBuf.isReadable()) {
                    int protocolVersion = byteBuf.readByte();
                    if (protocolVersion != PROTOCOL_VERSION) {
                        throw new RuntimeException("Unsupported protocol version: " + protocolVersion);
                    }
                    int observableNameLength = byteBuf.readByte();
                    String observableName = null;
                    if (observableNameLength > 0) {
                        // read name
                        observableName = new String(byteBuf.readBytes(observableNameLength).array());
                    }
                    int operation = byteBuf.readByte();
                    RemoteRxEvent.Type type = null;
                    Map<String, String> subscribeParams = null;
                    byte[] valueData = null;
                    if (operation == 1) {
                        logger.debug("READ request for RemoteRxEvent: next");
                        type = RemoteRxEvent.Type.next;
                        valueData = new byte[byteBuf.readableBytes()];
                        byteBuf.readBytes(valueData);
                    } else if (operation == 2) {
                        logger.debug("READ request for RemoteRxEvent: error");
                        type = RemoteRxEvent.Type.error;
                        valueData = new byte[byteBuf.readableBytes()];
                        byteBuf.readBytes(valueData);
                    } else if (operation == 3) {
                        logger.debug("READ request for RemoteRxEvent: completed");
                        type = RemoteRxEvent.Type.completed;
                    } else if (operation == 4) {
                        logger.debug("READ request for RemoteRxEvent: subscribed");
                        type = RemoteRxEvent.Type.subscribed;
                        // read subscribe parameters
                        int subscribeParamsLength = byteBuf.readInt();
                        if (subscribeParamsLength > 0) {
                            // read byte into map
                            byte[] subscribeParamsBytes = new byte[subscribeParamsLength];
                            byteBuf.readBytes(subscribeParamsBytes);
                            subscribeParams = fromBytesToMap(subscribeParamsBytes);
                        }
                    } else if (operation == 5) {
                        logger.debug("READ request for RemoteRxEvent: unsubscribed");
                        type = RemoteRxEvent.Type.unsubscribed;
                    } else {
                        throw new RuntimeException("operation: " + operation + " not support.");
                    }
                    handled = true;
                    byteBuf.release();
                    ctx.fireChannelRead(new RemoteRxEvent(observableName, type, valueData, subscribeParams));
                }
            }
            if (!handled) {
                super.channelRead(ctx, msg);
            }
        }

        @Override
        public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
            if (msg instanceof RemoteRxEvent) {
                ByteBuf buf = ctx.alloc().buffer();
                buf.writeByte(PROTOCOL_VERSION);
                RemoteRxEvent event = (RemoteRxEvent) msg;
                String observableName = event.getName();
                if (observableName != null && !observableName.isEmpty()) {
                    // write length
                    int nameLength = observableName.length();
                    if (nameLength < 127) {
                        buf.writeByte(nameLength);
                        buf.writeBytes(observableName.getBytes());
                    } else {
                        throw new RuntimeException(
                                "observableName " + observableName + " exceeds max limit of 127 characters");
                    }
                } else {
                    // no name provided, write 0 bytes for name length
                    buf.writeByte(0);
                }
                if (event.getType() == RemoteRxEvent.Type.next) {
                    logger.debug("WRITE request for RemoteRxEvent: next");
                    buf.writeByte(1);
                    buf.writeBytes(event.getData());
                    super.write(ctx, buf, promise);
                } else if (event.getType() == RemoteRxEvent.Type.error) {
                    logger.debug("WRITE request for RemoteRxEvent: error");
                    buf.writeByte(2);
                    buf.writeBytes(event.getData());
                    super.write(ctx, buf, promise);
                } else if (event.getType() == RemoteRxEvent.Type.completed) {
                    logger.debug("WRITE request for RemoteRxEvent: completed");
                    buf.writeByte(3);
                    super.write(ctx, buf, promise);
                    super.flush(ctx); // TODO why do I need to explicitly call flush for this to work??? empty data??
                } else if (event.getType() == RemoteRxEvent.Type.subscribed) {
                    logger.debug("WRITE request for RemoteRxEvent: subscribed");
                    buf.writeByte(4);
                    Map<String, String> subscribeParameters = event.getSubscribeParameters();
                    if (subscribeParameters != null && !subscribeParameters.isEmpty()) {
                        byte[] subscribeBytes = fromMapToBytes(subscribeParameters);
                        buf.writeInt(subscribeBytes.length); // write int for length
                        buf.writeBytes(subscribeBytes); // write data
                    } else {
                        buf.writeInt(0); // no data
                    }
                    super.write(ctx, buf, promise);
                    super.flush(ctx);
                } else if (event.getType() == RemoteRxEvent.Type.unsubscribed) {
                    logger.debug("WRITE request for RemoteRxEvent: unsubscribed");
                    buf.writeByte(5);
                    super.write(ctx, buf, promise);
                    super.flush(ctx); // TODO why do I need to explicitly call flush for this to work??? empty data??
                }
            } else {
                super.write(ctx, msg, promise);
            }
        }

    });

}

From source file:io.scalecube.socketio.serialization.PacketFramer.java

License:Apache License

public static List<Packet> decodePacketsFrame(final ByteBuf buffer) throws IOException {
    List<Packet> packets = new LinkedList<Packet>();
    int sequenceNumber = 0;
    while (buffer.isReadable()) {
        Packet packet = PacketFramer.decodeNextPacket(buffer);
        packet.setSequenceNumber(sequenceNumber);
        sequenceNumber++;/*from   ww  w .j av a  2  s.com*/
        packets.add(packet);
    }
    return packets;
}

From source file:io.vertx.core.dns.impl.decoder.RecordDecoder.java

License:Open Source License

/**
 * Retrieves a domain name given a buffer containing a DNS packet. If the
 * name contains a pointer, the position of the buffer will be set to
 * directly after the pointer's index after the name has been read.
 *
 * @param buf the byte buffer containing the DNS packet
 * @return the domain name for an entry//www .j  a va  2 s.c  o  m
 */
static String readName(ByteBuf buf) {
    int position = -1;
    StringBuilder name = new StringBuilder();
    for (int len = buf.readUnsignedByte(); buf.isReadable() && len != 0; len = buf.readUnsignedByte()) {
        boolean pointer = (len & 0xc0) == 0xc0;
        if (pointer) {
            if (position == -1) {
                position = buf.readerIndex() + 1;
            }
            buf.readerIndex((len & 0x3f) << 8 | buf.readUnsignedByte());
        } else {
            name.append(buf.toString(buf.readerIndex(), len, CharsetUtil.UTF_8)).append(".");
            buf.skipBytes(len);
        }
    }
    if (position != -1) {
        buf.readerIndex(position);
    }
    if (name.length() == 0) {
        return null;
    }
    return name.substring(0, name.length() - 1);
}

From source file:io.vertx.core.dns.impl.fix.DnsNameResolverContext.java

License:Apache License

/**
 * Retrieves a domain name given a buffer containing a DNS packet. If the
 * name contains a pointer, the position of the buffer will be set to
 * directly after the pointer's index after the name has been read.
 *
 * @param in the byte buffer containing the DNS packet
 * @return the domain name for an entry/*from w  w w.j  a  va2s .c o  m*/
 */
public static String decodeName(ByteBuf in) {
    int position = -1;
    int checked = 0;
    final int end = in.writerIndex();
    final int readable = in.readableBytes();

    // Looking at the spec we should always have at least enough readable bytes to read a byte here but it seems
    // some servers do not respect this for empty names. So just workaround this and return an empty name in this
    // case.
    //
    // See:
    // - https://github.com/netty/netty/issues/5014
    // - https://www.ietf.org/rfc/rfc1035.txt , Section 3.1
    if (readable == 0) {
        return ".";
    }

    final StringBuilder name = new StringBuilder(readable << 1);
    while (in.isReadable()) {
        final int len = in.readUnsignedByte();
        final boolean pointer = (len & 0xc0) == 0xc0;
        if (pointer) {
            if (position == -1) {
                position = in.readerIndex() + 1;
            }

            if (!in.isReadable()) {
                throw new CorruptedFrameException("truncated pointer in a name");
            }

            final int next = (len & 0x3f) << 8 | in.readUnsignedByte();
            if (next >= end) {
                throw new CorruptedFrameException("name has an out-of-range pointer");
            }
            in.readerIndex(next);

            // check for loops
            checked += 2;
            if (checked >= end) {
                throw new CorruptedFrameException("name contains a loop.");
            }
        } else if (len != 0) {
            if (!in.isReadable(len)) {
                throw new CorruptedFrameException("truncated label in a name");
            }
            name.append(in.toString(in.readerIndex(), len, CharsetUtil.UTF_8)).append('.');
            in.skipBytes(len);
        } else { // len == 0
            break;
        }
    }

    if (position != -1) {
        in.readerIndex(position);
    }

    if (name.length() == 0) {
        return ".";
    }

    if (name.charAt(name.length() - 1) != '.') {
        name.append('.');
    }

    return name.toString();
}

From source file:io.vertx.core.http.impl.ClientConnection.java

License:Open Source License

@Override
public void writeBuffer(ByteBuf buff, boolean end) {
    if (end) {/*  ww w  . j  a  va 2  s.c  om*/
        if (buff != null && buff.isReadable()) {
            writeToChannel(new DefaultLastHttpContent(buff, false));
        } else {
            writeToChannel(LastHttpContent.EMPTY_LAST_CONTENT);
        }
    } else if (buff != null) {
        writeToChannel(new DefaultHttpContent(buff));
    }
}