/* * Galaxy * Copyright (c) 2012-2014, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.galaxy.netty; import co.paralleluniverse.galaxy.Cluster; import co.paralleluniverse.galaxy.cluster.NodeInfo; import com.google.common.base.Charsets; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.ChannelHandler; 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.SimpleChannelUpstreamHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author pron */ @ChannelHandler.Sharable class ChannelNodeNameReader extends SimpleChannelUpstreamHandler { private static final Logger LOG = LoggerFactory.getLogger(ChannelNodeNameReader.class); private final Cluster cluster; private volatile ChannelStateEvent connectEvent; private volatile String nodeName; private volatile NodeInfo node; public ChannelNodeNameReader(Cluster cluster) { this.cluster = cluster; } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { final ChannelBuffer message = (ChannelBuffer) e.getMessage(); final int size = message.readableBytes(); final byte[] array = new byte[size]; message.readBytes(array); this.nodeName = new String(array, Charsets.UTF_8); LOG.info("Channel {} is node {}.", ctx.getChannel(), nodeName); this.node = cluster.getNodeInfoByName(nodeName); if (node == null) { LOG.error("Node info for {} not found!", ctx.getChannel(), nodeName); throw new RuntimeException("No node info for channel"); } final SocketAddress address = ctx.getChannel().getRemoteAddress(); final InetAddress host = ((InetSocketAddress) address).getAddress(); if (!host.equals((InetAddress) node.get(IpConstants.IP_ADDRESS))) { LOG.error("Channel coming from {} claims to be node {} - host address mismatch!", address, node); throw new RuntimeException("Node identity problem!"); } LOG.info("Channel {} is {}.", ctx.getChannel(), node); ChannelNodeInfo.nodeInfo.set(ctx.getChannel(), node); assert connectEvent != null; ctx.sendUpstream(connectEvent); ctx.getPipeline().remove(this); } @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { this.connectEvent = e; // hold connect event until we get the node's name } @Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { node = null; super.channelClosed(ctx, e); } @Override public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { node = null; super.channelDisconnected(ctx, e); } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { node = null; super.exceptionCaught(ctx, e); } }