/*
* TeleStax, Open Source Cloud Communications
* Copyright 2011-2017, 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.heartbeat.impl;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.log4j.Logger;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.mobicents.tools.heartbeat.api.IListener;
import org.mobicents.tools.heartbeat.api.Packet;
import org.mobicents.tools.heartbeat.api.Protocol;
import org.mobicents.tools.heartbeat.client.ClientPipelineFactory;
import org.mobicents.tools.heartbeat.interfaces.IServer;
import org.mobicents.tools.heartbeat.packets.LBShutdownRequestPacket;
import org.mobicents.tools.heartbeat.server.ServerPipelineFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/**
* @author Konstantin Nosach (kostyantyn.nosach@telestax.com)
*/
public class Server implements IServer{
private static final Logger logger = Logger.getLogger(Server.class.getCanonicalName());
private ExecutorService executor;
private NioServerSocketChannelFactory nioServerSocketChannelFactory;
private ServerBootstrap serverBootstrap;
private Channel serverChannel;
//client part
private ChannelFuture future;
private NioClientSocketChannelFactory nioClientSocketChannelFactory;
private ClientBootstrap clientBootstrap;
private InetAddress lbAddress;
private int lbPort;
private Packet packet;
IListener serverListener;
public Server(IListener serverListener, InetAddress serverAddress, int httpPort)
{
this.serverListener = serverListener;
this.lbAddress = serverAddress;
this.lbPort = httpPort;
}
@Override
public void start()
{
executor = Executors.newCachedThreadPool();
nioServerSocketChannelFactory = new NioServerSocketChannelFactory(executor, executor);
serverBootstrap = new ServerBootstrap(nioServerSocketChannelFactory);
serverBootstrap.setPipelineFactory(new ServerPipelineFactory(serverListener));
serverChannel = serverBootstrap.bind(new InetSocketAddress(lbAddress,lbPort));
logger.info("Heartbeat service started on " +lbAddress+":"+ lbPort+" (Load balancer's side)");
}
@Override
public void sendPacket(String command, String host,int port) {
this.nioClientSocketChannelFactory = new NioClientSocketChannelFactory(executor, executor);
this.clientBootstrap = new ClientBootstrap(nioClientSocketChannelFactory);
this.clientBootstrap.setPipelineFactory(new ClientPipelineFactory(serverListener));
future = clientBootstrap.connect(new InetSocketAddress(host, port));
switch(command)
{
case Protocol.STOP:
packet = new LBShutdownRequestPacket(lbAddress.getHostAddress(), lbPort);
break;
}
future.awaitUninterruptibly();
future.getChannel().write(createRequest(command));
}
@Override
public void stop()
{
if(serverChannel!=null)
{
serverChannel.unbind();
serverChannel.close();
serverChannel.getCloseFuture().awaitUninterruptibly();
}
if(executor!=null)
executor.shutdownNow();
serverBootstrap.shutdown();
nioServerSocketChannelFactory.shutdown();
if(nioClientSocketChannelFactory!=null)
nioClientSocketChannelFactory.shutdown();
}
private String getStringFromJson(String command)
{
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.setPrettyPrinting().create();
JsonElement je = gson.toJsonTree(packet);
JsonObject jo = new JsonObject();
jo.add(command, je);
String output=jo.toString();
logger.debug("Server is sending request : "+ output);
return output;
}
private HttpRequest createRequest(String command)
{
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/");
ChannelBuffer buf = ChannelBuffers.copiedBuffer(getStringFromJson(command), Charset.forName("UTF-8"));
request.setHeader(HttpHeaders.Names.CONTENT_TYPE, APPLICATION_JSON);
request.setHeader(HttpHeaders.Names.CONTENT_LENGTH, buf.readableBytes());
request.setContent(buf);
return request;
}
}