class LocalApiServerHandler extends SimpleChannelInboundHandler<Object> {

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg) {
    	LoggingService.logDebug(MODULE_NAME, "Start channel initializing");
        try {
            if (msg instanceof FullHttpRequest) {
                // full request
                ByteBuf content = null;
                try {
                    FullHttpRequest request = (FullHttpRequest) msg;
                    this.request = request;
                    content = request.content();
                    this.content = new byte[content.readableBytes()];
                    content.readBytes(this.content);
                    handleHttpRequest(ctx);
                } finally {
                    release(content);
                    release(msg);
                }
            } else if (msg instanceof HttpRequest) {
                // chunked request
                if (this.baos == null)
                    this.baos = new ByteArrayOutputStream();
                request = (HttpRequest) msg;
            } else if (msg instanceof WebSocketFrame) {
                try {
                    String mapName = findContextMapName(ctx);
                    if (mapName != null && mapName.equals("control")) {
                        ControlWebsocketHandler controlSocket = new ControlWebsocketHandler();
                        controlSocket.handleWebSocketFrame(ctx, (WebSocketFrame) msg);
                    } else if (mapName != null && mapName.equals("message")) {
                        MessageWebsocketHandler messageSocket = new MessageWebsocketHandler();
                        messageSocket.handleWebSocketFrame(ctx, (WebSocketFrame) msg);
                    } else {
                        LoggingService.logError(MODULE_NAME, "Cannot initiate real-time service: Context not found", 
                        		new AgentSystemException("Cannot initiate real-time service: Context not found"));
                    }
                } finally {
                    release(msg);
                }
            } else if (msg instanceof HttpContent) {
                HttpContent httpContent = (HttpContent) msg;
                ByteBuf content = httpContent.content();
                if (content.isReadable()) {
                    try {
                        content.readBytes(this.baos, content.readableBytes());
                    } catch (IOException e) {
                        String errorMsg = "Out of memory";
                        LoggingService.logError(MODULE_NAME, errorMsg, e);
                        ByteBuf errorMsgBytes = ctx.alloc().buffer();
                        errorMsgBytes.writeBytes(errorMsg.getBytes(UTF_8));
                        sendHttpResponse(ctx, request, new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.NOT_FOUND, errorMsgBytes));
                        return;
                    } finally {
                        release(content);
                    }
                }

                if (msg instanceof LastHttpContent) {        // last chunk
                    this.content = baos.toByteArray();
                    baos = null;
                    try {
                        handleHttpRequest(ctx);
                    } finally {
                        release(request);
                    }
                }
            }
        } catch (Exception e) {
            LoggingService.logError(MODULE_NAME, "Failed to initialize channel for the request", e);
        }
        LoggingService.logDebug(MODULE_NAME, "Finished channel initializing");
    }

    public  LocalApiServerHandler(EventExecutorGroup executor);

}