/** * Examines the channel buffer and attempts to match the protocol of the request and invoke the * matching {@link ProtocolInitiator}. * * @param ctx The channel handler context * @param channel The channel * @param bufferx The message buffer * @param e The channel event * @return The channel buffer to send upstream, or null if we need more bytes */ protected ChannelBuffer protocolSwitch( ChannelHandlerContext ctx, Channel channel, ChannelBuffer bufferx, ChannelEvent e) { ChannelBuffer cb = preSwitchedBuffer.get(channel); if (cb != null) { cb.writeBytes(bufferx); cb.resetReaderIndex(); } else { cb = bufferx; } // this guy will be set with a matching initiator ProtocolInitiator selectedInitiator = null; // this guy will be set to false if at least 1 initiator had insufficient bytes to match boolean sufficientBytes = true; // ths guy has the total bytes available in the buffer final int bytesAvailable = cb.readableBytes(); for (ProtocolInitiator pi : initiators.values()) { if (pi.requiredBytes() > bytesAvailable) { sufficientBytes = false; } else { if (pi.match(cb)) { selectedInitiator = pi; break; } } } if (selectedInitiator == null) { // we did not get a match if (!sufficientBytes) { // ok, we did not have enough bytes DynamicChannelBuffer dcb = preSwitchedBuffer.get(channel); if (dcb == null) { dcb = new DynamicChannelBuffer(cb.order(), 1024, chanelBufferFactory); preSwitchedBuffer.set(channel, dcb); } dcb.writeBytes(cb); dcb.resetReaderIndex(); return null; } // darn, we have enough bytes for any of the inits, // but none matched throw new RuntimeException("Failed to match any protocol initiator"); } preSwitchedBuffer.remove(channel); // we matched on an initiator, so have it modify the pipeline selectedInitiator.modifyPipeline(ctx, channel, cb); return cb; // if we get here, it means we did not find a protocol match // so pass to the default protocol initiator. }
@Override protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { if (!(msg instanceof ChannelBuffer)) { return msg; } ChannelBuffer body = (ChannelBuffer) msg; ChannelBuffer header = channel.getConfig().getBufferFactory().getBuffer(body.order(), lengthFieldLength); int length = lengthIncludesLengthFieldLength ? body.readableBytes() + lengthFieldLength : body.readableBytes(); switch (lengthFieldLength) { case 1: if (length >= 256) { throw new IllegalArgumentException("length does not fit into a byte: " + length); } header.writeByte((byte) length); break; case 2: if (length >= 65536) { throw new IllegalArgumentException("length does not fit into a short integer: " + length); } header.writeShort((short) length); break; case 3: if (length >= 16777216) { throw new IllegalArgumentException( "length does not fit into a medium integer: " + length); } header.writeMedium(length); break; case 4: header.writeInt(length); break; case 8: header.writeLong(length); break; default: throw new Error("should not reach here"); } return wrappedBuffer(header, body); }