package io.eguan.net; /* * #%L * Project eguan * %% * Copyright (C) 2012 - 2017 Oodrive * %% * 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. * #L% */ import io.eguan.proto.Common.ProtocolVersion; import io.eguan.proto.net.MsgWrapper; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; import org.jboss.netty.channel.group.ChannelGroup; import com.google.protobuf.MessageLite; final class MsgServerGenericHandler extends SimpleChannelHandler { private final UUID msgServerId; private final MsgServerHandler msgServerHandler; private final MessageLite prototype; private final ChannelGroup channelGroup; private final AtomicBoolean serverStarted; MsgServerGenericHandler(final UUID msgServerId, final MsgServerHandler msgServerHandler, final MessageLite prototype, final ChannelGroup channelGroup, final AtomicBoolean serverStarted) { this.msgServerId = msgServerId; this.msgServerHandler = msgServerHandler; this.prototype = prototype; this.channelGroup = channelGroup; this.serverStarted = serverStarted; } @Override public final void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) { final MsgWrapper.MsgRequest request = (MsgWrapper.MsgRequest) e.getMessage(); final long msgId = request.getMsgId(); final MessageLite reply; try { // Deserialize the message data which represent a Protobuf message final MessageLite deserializedMsg = prototype.newBuilderForType().mergeFrom(request.getMsgData()).build(); reply = msgServerHandler.handleMessage(deserializedMsg); } catch (final Throwable t) { // Return exception if (request.getSynchronous()) { final MsgWrapper.MsgReply.Builder replyBuilder = MsgWrapper.MsgReply.newBuilder().setVersion(ProtocolVersion.VERSION_1).setMsgId(msgId) .setStatus(false).setException(t.getClass().getName()); ctx.getChannel().write(replyBuilder.build()); } MsgServerEndpoint.LOGGER.error("Msg server [" + msgServerId + "], error while handling the message '" + msgId + "'", t); return; } // Send ACK only if the request is synchronous if (request.getSynchronous()) { final MsgWrapper.MsgReply.Builder replyBuilder = MsgWrapper.MsgReply.newBuilder().setVersion(ProtocolVersion.VERSION_1).setMsgId(msgId) .setStatus(true); // Optional reply if (reply != null) { replyBuilder.setRepData(reply.toByteString()); } ctx.getChannel().write(replyBuilder.build()); } } @Override public final void channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { // If the server is stopped then close all new connected channels in order to be able to release allocated // resources when the server stop. if (!serverStarted.get()) { ctx.getChannel().close(); return; } channelGroup.add(ctx.getChannel()); MsgServerEndpoint.LOGGER.info("Msg server [{}], channel connected to \'{}\'", msgServerId, ctx.getChannel() .getRemoteAddress()); } @Override public final void exceptionCaught(final ChannelHandlerContext ctx, final ExceptionEvent e) throws Exception { MsgServerEndpoint.LOGGER.warn(e.getCause().toString()); } }