/* * 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.InetSocketAddress; import java.nio.charset.Charset; import java.util.concurrent.ExecutorService; import org.apache.log4j.Logger; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; 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.HeartbeatRequestPacket; import org.mobicents.tools.heartbeat.api.Node; import org.mobicents.tools.heartbeat.api.NodeShutdownRequestPacket; import org.mobicents.tools.heartbeat.api.NodeStopRequestPacket; import org.mobicents.tools.heartbeat.api.Packet; import org.mobicents.tools.heartbeat.api.Protocol; import org.mobicents.tools.heartbeat.api.StartRequestPacket; import org.mobicents.tools.heartbeat.client.ClientPipelineFactory; import org.mobicents.tools.heartbeat.interfaces.IClient; import org.mobicents.tools.heartbeat.interfaces.IClientListener; import org.mobicents.tools.heartbeat.packets.SwitchoverRequestPacket; 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 Client implements IClient{ private static final Logger logger = Logger.getLogger(Client.class.getCanonicalName()); private ExecutorService executor; private ClientBootstrap clientBootstrap; private NioClientSocketChannelFactory nioClientSocketChannelFactory; private ChannelFuture future; private String lbAddress; private int lbPort; private Node node; private Packet packet; private IClientListener clientListener; private InetSocketAddress isa; public Client(IClientListener clientListener, String lbAddress, int lbPort, Node node, ExecutorService executor) { this.clientListener = clientListener; this.lbAddress = lbAddress; this.lbPort = lbPort; this.node = node; this.executor = executor; } public void updateNode(Node node) { this.node=node; } @Override public void start() { this.nioClientSocketChannelFactory = new NioClientSocketChannelFactory(executor, executor); this.clientBootstrap = new ClientBootstrap(nioClientSocketChannelFactory); this.clientBootstrap.setPipelineFactory(new ClientPipelineFactory(clientListener)); this.isa = new InetSocketAddress(lbAddress, lbPort); } @Override public void switchover(String fromJvmRoute, String toJvmRoute) { Packet packet = new SwitchoverRequestPacket(fromJvmRoute, toJvmRoute); ClientBootstrap clientBootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(executor, executor)); clientBootstrap.setPipelineFactory(new ClientPipelineFactory(clientListener)); ChannelFuture future = clientBootstrap.connect(new InetSocketAddress(lbAddress, lbPort)); future.awaitUninterruptibly(); future.getChannel().write(createRequest(Protocol.SWITCHOVER,packet)); } @Override public synchronized void sendPacket(String command) { if(clientBootstrap!=null&&!executor.isShutdown()) { future = clientBootstrap.connect(isa); switch(command) { case Protocol.START: if(packet==null||!(packet instanceof StartRequestPacket)) { node.getProperties().put(Protocol.SESSION_ID, ""+ System.currentTimeMillis()); packet = new StartRequestPacket(node); } break; case Protocol.HEARTBEAT: if(packet!=null&&!(packet instanceof HeartbeatRequestPacket)) packet = new HeartbeatRequestPacket(node); break; case Protocol.SHUTDOWN: packet = new NodeShutdownRequestPacket(node); break; case Protocol.STOP: packet = new NodeStopRequestPacket(node); break; } future.awaitUninterruptibly(); future.getChannel().write(createRequest(command, null)); } } @Override public void stop() { if(executor==null) return; executor.shutdownNow(); if(clientBootstrap!=null) clientBootstrap.shutdown(); nioClientSocketChannelFactory.shutdown(); } private String getStringFromJson(String packetType, Packet packet) { GsonBuilder builder = new GsonBuilder(); Gson gson = builder.setPrettyPrinting().create(); JsonElement je = null; if(packet==null) je = gson.toJsonTree(this.packet); else je = gson.toJsonTree(packet); JsonObject jo = new JsonObject(); jo.add(packetType, je); String output=jo.toString(); logger.debug("Client is sending request : "+ output); return output; } private HttpRequest createRequest(String packetType, Packet packet) { HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); ChannelBuffer buf = ChannelBuffers.copiedBuffer(getStringFromJson(packetType, packet), 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; } }