// --------------------------------------------------------------------------- // jWebSocket - Copyright (c) 2010 Innotrade GmbH, jWebSocket.org // --------------------------------------------------------------------------- // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published by the // Free Software Foundation; either version 3 of the License, or (at your // option) any later version. // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for // more details. // You should have received a copy of the GNU Lesser General Public License along // with this program; if not, see <http://www.gnu.org/licenses/lgpl.html>. // --------------------------------------------------------------------------- package org.jwebsocket.netty.engines; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import org.apache.log4j.Logger; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.ChannelGroupFuture; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jwebsocket.api.EngineConfiguration; import org.jwebsocket.api.WebSocketConnector; import org.jwebsocket.engines.BaseEngine; import org.jwebsocket.kit.CloseReason; import org.jwebsocket.kit.WebSocketException; import org.jwebsocket.logging.Logging; /** * Netty based implementation of {@code WebSocketEngine} engine.It uses the * low-level <tt>ServerBootStrap</tt> to start the server and handles the * incoming/outgoing request/response using {@code NettyEngineHandler} class. * * @author puran * @version $Id: NettyEngine.java 596 2010-06-22 17:09:54Z fivefeetfurther $ * @see NettyEngineHandler */ public class NettyEngine extends BaseEngine { private static Logger log = Logging.getLogger(NettyEngine.class); private volatile boolean isRunning = false; private static final ChannelGroup allChannels = new DefaultChannelGroup("jWebSocket-NettyEngine"); private Channel channel = null; /** * constructor * @param config */ public NettyEngine(EngineConfiguration configuration) { super(configuration); } /** * {@inheritDoc} */ @Override public void startEngine() throws WebSocketException { if (log.isDebugEnabled()) { log.debug("Starting Netty engine '" + getId() + "'..."); } // Configure the server. ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // Set up the event pipeline factory. bootstrap.setPipelineFactory(new NettyEnginePipeLineFactory(this, false)); // Bind and start to accept incoming connections. channel = bootstrap.bind(new InetSocketAddress(getConfiguration().getPort())); //set the timeout value if only it's greater than 0 in configuration if (getConfiguration().getTimeout() > 0) { channel.getConfig().setConnectTimeoutMillis(getConfiguration().getTimeout()); } // fire the engine start event engineStarted(); allChannels.add(channel); isRunning = true; if (log.isInfoEnabled()) { log.info("Netty engine '" + getId() + "' started."); } } /** * {@inheritDoc} */ @Override public void stopEngine(CloseReason aCloseReason) throws WebSocketException { log.debug("Stopping Netty engine '" + getId() + "'..."); isRunning = false; super.stopEngine(aCloseReason); engineStopped(); // Added by Alex 2010-08-09 if (channel != null) { channel.close(); // Moved from last line to here by Alex 2010-11-23 // to prevent exceptions channel.getFactory().releaseExternalResources(); } ChannelGroupFuture future = allChannels.close(); future.awaitUninterruptibly(); } /** * {@inheritDoc} */ @Override public void connectorStarted(WebSocketConnector aConnector) { log.debug("Detected new connector at port " + aConnector.getRemotePort() + "."); super.connectorStarted(aConnector); } /** * {@inheritDoc} */ @Override public void connectorStopped(WebSocketConnector aConnector, CloseReason aCloseReason) { log.debug("Detected stopped connector at port " + aConnector.getRemotePort() + "."); super.connectorStopped(aConnector, aCloseReason); } /** * {@inheritDoc} */ @Override public boolean isAlive() { if (isRunning) { return true; } else { return false; } } }