void (ChannelHandlerContext context, CmdlineRemoteProto.Message message) { SessionData sessionData = context.channel().attr(Holder.SESSION_DATA).get(); final boolean isFirstMessage = sessionData == null; final UUID sessionId; if (isFirstMessage) { // this is the first message for this session, so fill session data with missing info final CmdlineRemoteProto.Message.UUID id = message.getSessionId(); sessionId = new UUID(id.getMostSigBits(), id.getLeastSigBits()); sessionData = mySessionDescriptors.get(sessionId); if (sessionData != null) { sessionData.channel = context.channel(); context.channel().attr(Holder.SESSION_DATA).set(sessionData); } } else { sessionId = sessionData.sessionId; } final BuilderMessageHandler handler = sessionData != null? sessionData.handler : null; try { if (handler == null) { if (!isBuilderEvent(message)) { // do not pollute logs, just silently skip events in case handler is missing LOG.info("No message handler registered for session " + sessionId); } return; } final CmdlineRemoteProto.Message.Type messageType = message.getType(); switch (messageType) { case FAILURE -> handler.handleFailure(sessionId, message.getFailure()); case BUILDER_MESSAGE -> { final CmdlineRemoteProto.Message.BuilderMessage builderMessage = message.getBuilderMessage(); final CmdlineRemoteProto.Message.BuilderMessage.Type msgType = builderMessage.getType(); if (msgType == CmdlineRemoteProto.Message.BuilderMessage.Type.PARAM_REQUEST) { //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (sessionData) { final CmdlineRemoteProto.Message.ControllerMessage params = sessionData.params; if (params != null) { sessionData.state = SessionData.State.RUNNING; handler.buildStarted(sessionId); sessionData.params = null; context.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, params)); } else { if (sessionData.state == SessionData.State.INITIAL) { sessionData.state = SessionData.State.WAITING_PARAMS; } else { // this message is expected to be sent only once. // To be on the safe side, cancel the session cancelSession(sessionId); } } } } else { handler.handleBuildMessage(context.channel(), sessionId, builderMessage); } } default -> LOG.info("Unsupported message type " + messageType); } } finally { if ((isFirstMessage && myCanceledSessions.contains(sessionId)) || (handler == null && !isBuilderEvent(message))) { // handle the case when the session had been cancelled before communication even started // or if message handling is not possible due to missing handler context.channel().writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createCancelCommand())); } } }