@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (handshakeComplete) { super.messageReceived(ctx, e); } else { if (e.getMessage() instanceof ChannelBuffer) { ChannelBuffer newBuffer = (ChannelBuffer) e.getMessage(); buffered = ChannelBuffers.copiedBuffer(buffered, newBuffer); if (buffered.readableBytes() < 8) { return; } int payloadLength = buffered.getInt(0); int revision = buffered.getInt(4); boolean handshakeSuccessful = false; if (revision == 1 || revision == -1) { if (buffered.readableBytes() < payloadLength + 4) { return; } buffered.skipBytes(8); if (revision == 1) { handshakeSuccessful = handleRevision1Response(ctx, payloadLength); } else { handshakeSuccessful = handleGenericResponse(ctx, payloadLength); } } else { handshakeSuccessful = handleUnknownRevisionResponse(ctx); } if (!handshakeSuccessful) { ctx.getChannel().close(); } if (keepAliveInterval.millis() > 0) { ctx.getPipeline() .addBefore( ctx.getName(), "found-connection-keep-alive", new ConnectionKeepAliveHandler(scheduler, keepAliveInterval)); } handshakeComplete = true; ChannelBuffer remaining = buffered.slice(); if (remaining.readableBytes() > 0) { ctx.sendUpstream( new UpstreamMessageEvent( ctx.getChannel(), remaining, ctx.getChannel().getRemoteAddress())); } ctx.getPipeline().remove(this); } } }
@Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { // wait for prefix if (buffer.readableBytes() < 4) { return null; } int length = buffer.getInt(buffer.readerIndex()); // wait for the complete event if (buffer.readableBytes() < length + 4) { return null; } // skip package length header buffer.skipBytes(4); // decode int typeLength = buffer.readInt(); String type = buffer.toString(buffer.readerIndex(), typeLength, "UTF-8"); int eventLength = length - typeLength; byte[] eventBytes = new byte[eventLength]; buffer.skipBytes(typeLength); buffer.readBytes(eventBytes); return new Event(type, eventBytes); }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { Object m = e.getMessage(); if (!(m instanceof ChannelBuffer)) { ctx.sendUpstream(e); return; } ChannelBuffer buffer = (ChannelBuffer) m; int size = buffer.getInt(buffer.readerIndex() - 4); transportServiceAdapter.received(size + 6); // we have additional bytes to read, outside of the header boolean hasMessageBytesToRead = (size - (NettyHeader.HEADER_SIZE - 6)) != 0; int markedReaderIndex = buffer.readerIndex(); int expectedIndexReader = markedReaderIndex + size; // netty always copies a buffer, either in NioWorker in its read handler, where it copies to a // fresh // buffer, or in the cumlation buffer, which is cleaned each time StreamInput streamIn = ChannelBufferStreamInputFactory.create(buffer, size); long requestId = buffer.readLong(); byte status = buffer.readByte(); Version version = Version.fromId(buffer.readInt()); StreamInput wrappedStream; if (TransportStatus.isCompress(status) && hasMessageBytesToRead && buffer.readable()) { Compressor compressor = CompressorFactory.compressor(buffer); if (compressor == null) { int maxToRead = Math.min(buffer.readableBytes(), 10); int offset = buffer.readerIndex(); StringBuilder sb = new StringBuilder("stream marked as compressed, but no compressor found, first [") .append(maxToRead) .append("] content bytes out of [") .append(buffer.readableBytes()) .append("] readable bytes with message size [") .append(size) .append("] ") .append("] are ["); for (int i = 0; i < maxToRead; i++) { sb.append(buffer.getByte(offset + i)).append(","); } sb.append("]"); throw new ElasticsearchIllegalStateException(sb.toString()); } wrappedStream = CachedStreamInput.cachedHandlesCompressed(compressor, streamIn); } else { wrappedStream = CachedStreamInput.cachedHandles(streamIn); } wrappedStream.setVersion(version); if (TransportStatus.isRequest(status)) { String action = handleRequest(ctx.getChannel(), wrappedStream, requestId, version); if (buffer.readerIndex() != expectedIndexReader) { if (buffer.readerIndex() < expectedIndexReader) { logger.warn( "Message not fully read (request) for [{}] and action [{}], resetting", requestId, action); } else { logger.warn( "Message read past expected size (request) for [{}] and action [{}], resetting", requestId, action); } buffer.readerIndex(expectedIndexReader); } } else { TransportResponseHandler handler = transportServiceAdapter.remove(requestId); // ignore if its null, the adapter logs it if (handler != null) { if (TransportStatus.isError(status)) { handlerResponseError(wrappedStream, handler); } else { handleResponse(ctx.getChannel(), wrappedStream, handler); } } else { // if its null, skip those bytes buffer.readerIndex(markedReaderIndex + size); } if (buffer.readerIndex() != expectedIndexReader) { if (buffer.readerIndex() < expectedIndexReader) { logger.warn( "Message not fully read (response) for [{}] handler {}, error [{}], resetting", requestId, handler, TransportStatus.isError(status)); } else { logger.warn( "Message read past expected size (response) for [{}] handler {}, error [{}], resetting", requestId, handler, TransportStatus.isError(status)); } buffer.readerIndex(expectedIndexReader); } } wrappedStream.close(); }