/* * TeleStax, Open Source Cloud Communications * Copyright 2011-2015, Telestax Inc and individual contributors * by the @authors tag. * * This program is free software: you can redistribute it and/or modify * under the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> */ package org.mobicents.tools.smpp.balancer.core; import java.net.InetSocketAddress; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicLong; import org.apache.log4j.Logger; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelException; import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.channel.socket.oio.OioServerSocketChannelFactory; import org.mobicents.tools.sip.balancer.BalancerRunner; import org.mobicents.tools.smpp.balancer.impl.ServerChannelConnector; import com.cloudhopper.smpp.SmppServerConfiguration; import com.cloudhopper.smpp.channel.SmppChannelConstants; import com.cloudhopper.smpp.impl.DefaultSmppServerCounters; /** * @author Konstantin Nosach (kostyantyn.nosach@telestax.com) */ public class BalancerServer{ private static final Logger logger = Logger.getLogger(BalancerServer.class); private final ChannelGroup channels; private final ServerChannelConnector serverConnector; private SmppServerConfiguration regularConfiguration; private ServerBootstrap regularBootstrap; private ServerChannelConnector securedConnector; private SmppServerConfiguration securedConfiguration; private ServerBootstrap securedBootstrap; private ExecutorService bossThreadPool; private ChannelFactory channelFactory; private final AtomicLong sessionIdSequence; private DefaultSmppServerCounters counters; public BalancerServer (SmppServerConfiguration regularConfiguration,SmppServerConfiguration securedConfiguration,ExecutorService executor, BalancerRunner balancerRunner, BalancerDispatcher lbServerListener, ScheduledExecutorService monitorExecutor) { this.regularConfiguration = regularConfiguration; this.securedConfiguration=securedConfiguration; this.channels = new DefaultChannelGroup(); this.bossThreadPool = Executors.newCachedThreadPool(); if (regularConfiguration.isNonBlockingSocketsEnabled()) this.channelFactory = new NioServerSocketChannelFactory(this.bossThreadPool, executor, regularConfiguration.getMaxConnectionSize()); else this.channelFactory = new OioServerSocketChannelFactory(this.bossThreadPool, executor); this.regularBootstrap = new ServerBootstrap(this.channelFactory); this.regularBootstrap.setOption("reuseAddress", regularConfiguration.isReuseAddress()); this.serverConnector = new ServerChannelConnector(channels, this, regularConfiguration, balancerRunner, lbServerListener, monitorExecutor); this.regularBootstrap.getPipeline().addLast(SmppChannelConstants.PIPELINE_SERVER_CONNECTOR_NAME, this.serverConnector); if(this.securedConfiguration!=null) { this.securedBootstrap = new ServerBootstrap(this.channelFactory); this.securedBootstrap.setOption("reuseAddress", securedConfiguration.isReuseAddress()); this.securedConnector = new ServerChannelConnector(channels, this, securedConfiguration, balancerRunner, lbServerListener, monitorExecutor); this.securedBootstrap.getPipeline().addLast(SmppChannelConstants.PIPELINE_SERVER_CONNECTOR_NAME, this.securedConnector); } this.sessionIdSequence = new AtomicLong(0); this.counters = new DefaultSmppServerCounters(); } public DefaultSmppServerCounters getCounters() { return counters; } /** *Start load balancer server */ public void start() { try { this.regularBootstrap.bind(new InetSocketAddress(regularConfiguration.getHost(), regularConfiguration.getPort())); if(logger.isInfoEnabled()) { logger.info(regularConfiguration.getName() + " started at " + regularConfiguration.getHost() + " : " + regularConfiguration.getPort()); } if(this.securedConfiguration!=null) { this.securedBootstrap.bind(new InetSocketAddress(securedConfiguration.getHost(), securedConfiguration.getPort())); if(logger.isInfoEnabled()) { logger.info(securedConfiguration.getName() + " uses port : " + securedConfiguration.getPort() + " for TLS clients."); } } } catch (ChannelException e) { logger.error("Smpp Channel Exception:", e); } } /** *Generate id for sessions(clients) */ public Long nextSessionId() { this.sessionIdSequence.compareAndSet(Long.MAX_VALUE, 0); return this.sessionIdSequence.getAndIncrement(); } /** *Stop load balancer server */ public void stop() { if (this.channels.size() > 0) { logger.info(regularConfiguration.getName() + " currently has [" + this.channels.size() + "] open child channel(s) that will be closed as part of stop()"); } this.channelFactory.shutdown(); this.channels.close().awaitUninterruptibly(); this.regularBootstrap.shutdown(); if(this.securedBootstrap!=null) this.securedBootstrap.shutdown(); logger.info(regularConfiguration.getName() + " stopped at " + regularConfiguration.getHost()); } }