/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.internal.networking; import com.hazelcast.nio.tcp.MemberChannelInboundHandler; import com.hazelcast.nio.tcp.TcpIpConnection; import java.nio.ByteBuffer; /** * Reads content from a {@link ByteBuffer} and processes it. The ChannelInboundHandler is invoked by the {@link ChannelReader} * after it has read data from the socket. * * A typical example is that Packet instances are created from the buffered data and handing them over the the * {@link com.hazelcast.spi.impl.packetdispatcher.PacketDispatcher}. See {@link MemberChannelInboundHandler} for more information. * * Each {@link ChannelReader} will have its own {@link ChannelInboundHandler} instance. Therefor it doesn't need to be * thread-safe. * * <h1>Pipelining & Encryption</h1> * The ChannelInboundHandler/ChannelOutboundHandler can also form a pipeline. For example for SSL there could be a initial * ChannelInboundHandler that decryption the ByteBuffer and passes the decrypted ByteBuffer to the next ChannelInboundHandler; * which could be a {@link MemberChannelInboundHandler} that reads out any Packet from the decrypted ByteBuffer. Using this * approach encryption can easily be added to any type of communication, not only member 2 member communication. * * Currently security is added by using a {@link Channel}, but this is not needed if the handlers form a pipeline. * Netty follows a similar approach with pipelining and adding encryption. * * There is no explicit support for setting up a 'pipeline' of ChannelInboundHandler/WriterHandlers but t can easily be realized * by setting up the chain and let a handler explicitly forward to the next. Since it isn't a common practice for the handler * so far, isn't needed to add additional complexity to the system; just set up a chain manually. * * pseudo code: * <pre> * public class DecryptingReadHandler implements ChannelInboundHandler { * private final ChannelInboundHandler next; * * public DecryptingReadHandler(ChannelInboundHandler next) { * this.next = next; * } * * public void onRead(ByteBuffer src) { * decrypt(src, decryptedSrc); * next.onRead(decryptedSrc) * } * } * </pre> * The <code>next</code> ChannelInboundHandler is the next item in the pipeline. * * For encryption is similar approach can be followed where the DecryptingWriteHandler is the last ChannelOutboundHandler in * the pipeline. * * @see ChannelOutboundHandler * @see ChannelReader * @see TcpIpConnection * @see EventLoopGroup */ public interface ChannelInboundHandler { /** * A callback to indicate that data is available in the ByteBuffer to be processed. * * @param src the ByteBuffer containing the data to read. The ByteBuffer is already in reading mode and when completed, * should not be converted to write-mode using clear/compact. That is a task of the {@link ChannelReader}. * @throws Exception if something fails while reading data from the ByteBuffer or processing the data * (e.g. when a Packet fails to get processed). When an exception is thrown, the TcpIpConnection * is closed. There is no point continuing with a potentially corrupted stream. */ void onRead(ByteBuffer src) throws Exception; }