/* * Copyright 2013 The Skfiy Open Association. * * 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 org.skfiy.typhon.net; import java.net.InetSocketAddress; import javax.management.MBeanServer; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandler; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder; import org.jboss.netty.handler.codec.frame.Delimiters; import org.jboss.netty.handler.logging.LoggingHandler; import org.jboss.netty.handler.timeout.IdleStateHandler; import org.jboss.netty.util.ExternalResourceReleasable; import org.jboss.netty.util.HashedWheelTimer; import org.jboss.netty.util.Timer; import org.skfiy.typhon.AbstractMBeanLifecycle; import org.skfiy.typhon.Connector; import org.skfiy.typhon.LifecycleException; import org.skfiy.typhon.LifecycleState; import org.skfiy.typhon.Service; import org.skfiy.typhon.Container; import org.skfiy.typhon.Globals; import org.skfiy.typhon.TyphonException; import org.skfiy.typhon.util.MBeanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Netty3 连接器实现. * * @author Kevin Zou <kevinz@skfiy.org> */ public class NettyConnector extends AbstractMBeanLifecycle implements Connector { private static final Logger CLOG = LoggerFactory.getLogger(Globals.CONSOLE_LOG_NAME); private Service service; private String host; private int port; private boolean logEnabled; private long connectionTimeout; private Channel serverChannel; private ServerBootstrap nettyServer; @Override public Service getService() { return service; } @Override public void setService(Service service) { this.service = service; } @Override public String getHost() { return host; } @Override public void setHost(String host) { this.host = host; } @Override public int getPort() { return port; } @Override public void setPort(int port) { this.port = port; } @Override public boolean isLogEnabled() { return logEnabled; } @Override public void setLogEnabled(boolean enabled) { this.logEnabled = enabled; } @Override public long getConnectionTimeout() { return connectionTimeout; } @Override public void setConnectionTimeout(long connectionTimeout) { this.connectionTimeout = connectionTimeout; } @Override protected void initInternal() throws LifecycleException { nettyServer = new ServerBootstrap(new NioServerSocketChannelFactory()); super.initInternal(); } @Override protected void startInternal() throws LifecycleException { setState(LifecycleState.STARTING); fireLifecycleListener(START_EVENT); NettyEndpointHandler handler = new NettyEndpointHandler(); nettyServer.setPipelineFactory(new MyChannelPipelineFactory(handler)); serverChannel = nettyServer.bind(new InetSocketAddress(host, port)); CLOG.debug("NettyConnector started on port {}", port); MBeanServer mbs = MBeanUtils.REGISTRY.getMBeanServer(); Object obj = null; try { obj = mbs.invoke(Container.OBJECT_NAME, "getInstance", new Object[]{ProtocolHandler.class}, new String[]{Class.class.getName()}); } catch (Exception ex) { CLOG.error("获取ProtocolHandler错误", ex); throw new TyphonException(ex); } handler.setProtocolHandler((ProtocolHandler) obj); } @Override protected void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); fireLifecycleListener(STOP_EVENT); serverChannel.close(); nettyServer.shutdown(); } @Override protected String getMBeanDomain() { return "Connector"; } @Override protected String getObjectNameKeyProperties() { return "name=NettyConnector"; } private class MyChannelPipelineFactory implements ChannelPipelineFactory, ExternalResourceReleasable { private final Timer timer = new HashedWheelTimer(); private final IdleStateHandler idleStateHandler = new IdleStateHandler(timer, 60, 0, 0); private final ChannelHandler handler; MyChannelPipelineFactory(ChannelHandler handler) { this.handler = handler; } @Override public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("IdleState", idleStateHandler); pipeline.addLast("FrameDecoder", new DelimiterBasedFrameDecoder(65535, Delimiters.lineDelimiter())); // pipeline.addLast("FrameEncoder", new LengthFieldPrepender(4, false)); if (isLogEnabled()) { pipeline.addLast("Logging", new LoggingHandler()); } pipeline.addLast("Endpoint-Inbound", handler); return pipeline; } @Override public void releaseExternalResources() { idleStateHandler.releaseExternalResources(); } } }