/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This 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 2.1 of * the License, or (at your option) any later version. * * This software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.mobicents.tools.sip.balancer; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.sip.SipProvider; import javax.sip.message.Response; import org.apache.log4j.Logger; 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.ChannelFutureListener; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.codec.http.DefaultHttpResponse; import org.jboss.netty.handler.codec.http.HttpHeaders; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import org.jboss.netty.handler.codec.http.HttpVersion; import org.mobicents.tools.heartbeat.api.Node; import org.mobicents.tools.heartbeat.api.Packet; import org.mobicents.tools.heartbeat.api.Protocol; import org.mobicents.tools.heartbeat.impl.ClientController; import org.mobicents.tools.heartbeat.interfaces.IClientListener; import org.mobicents.tools.heartbeat.packets.StopResponsePacket; import org.mobicents.tools.heartbeat.server.ServerPipelineFactory; import com.google.gson.Gson; import com.google.gson.JsonObject; public class AppServer implements IClientListener{ private static final Logger logger = Logger.getLogger(AppServer.class.getCanonicalName()); public ProtocolObjects protocolObjects; public TestSipListener sipListener; int port; String name; Node node; public boolean sendHeartbeat = true; private Gson gson = new Gson(); NioServerSocketChannelFactory nioServerSocketChannelFactory; String lbAddress; int lbRMIport; int lbSIPext; int lbSIPint; String transport; protected String balancers; public SipProvider sipProvider; public String version; boolean isDummy; boolean isMediaFailure; boolean isFirstStart = true; boolean isIpv6 = false; ClientController clientController; ClientController [] clientControllers; int lbPort = 2610; int heartbeatPort = 2222; int heartbeatPeriod = 1000; private ServerBootstrap serverBootstrap; private Channel serverChannel; //private ExecutorService executor = Executors.newCachedThreadPool(); private String heartbeatAddress; public AppServer(String appServer, int port, String lbAddress, int lbRMI, int lbSIPext, int lbSIPint, String version , String transport, int heartbeatPort) { this.port = port; this.name = appServer; this.lbAddress = lbAddress; this.lbRMIport = lbRMI; this.lbSIPext = lbSIPext; this.lbSIPint = lbSIPint; this.version = version; this.transport=transport; this.heartbeatPort = heartbeatPort; } public AppServer(boolean isIpv6,String appServer, int port, String lbAddress, int lbRMI, int lbSIPext, int lbSIPint, String version , String transport) { this(appServer, port, lbAddress, lbRMI, lbSIPext, lbSIPint, version , transport, 2222); this.isIpv6 = true; } public AppServer(String appServer, int port, String lbAddress, int lbRMI, int lbSIPext, int lbSIPint, String version , String transport, boolean isDummy) { this(appServer, port, lbAddress, lbRMI, lbSIPext, lbSIPint, version , transport, 2222); this.isDummy = isDummy; } public AppServer(String appServer, int port, String lbAddress, int lbRMI, int lbSIPext, int lbSIPint, String version , String transport, boolean isDummy, boolean isMediaFailure) { this(appServer, port, lbAddress, lbRMI, lbSIPext, lbSIPint, version , transport, 2222); this.isDummy = isDummy; this.isMediaFailure = isMediaFailure; } public AppServer() { // TODO Auto-generated constructor stub } public void setBalancers(String balancers) { this.balancers = balancers; } public void setEventListener(EventListener listener) { sipListener.eventListener = listener; } public void start() { ExecutorService executor = Executors.newCachedThreadPool(); protocolObjects = new ProtocolObjects(name, "gov.nist", transport, false, false, true); if(!isDummy) { if(!isMediaFailure||!isFirstStart) { sipListener = new TestSipListener(isIpv6,port, lbSIPint, protocolObjects, false); } else { sipListener = new TestSipListener(isIpv6,port, lbSIPint, protocolObjects, false); sipListener.setRespondWithError(Response.SERVICE_UNAVAILABLE); } } else { sipListener = new TestSipListener(isIpv6,port+1, lbSIPint, protocolObjects, false); } sipListener.appServer = this; try { sipProvider = sipListener.createProvider(); sipProvider.addSipListener(sipListener); protocolObjects.start(); } catch (Exception e) { e.printStackTrace(); } //generate node if(!isIpv6) node = new Node(name, "127.0.0.1"); else node = new Node(name, "::1"); node.getProperties().put(transport.toLowerCase() + "Port",""+ port); node.getProperties().put(Protocol.VERSION, version); node.getProperties().put(Protocol.SESSION_ID, ""+System.currentTimeMillis()); node.getProperties().put(Protocol.HEARTBEAT_PORT, ""+heartbeatPort); nioServerSocketChannelFactory = new NioServerSocketChannelFactory(executor, executor); serverBootstrap = new ServerBootstrap(nioServerSocketChannelFactory); serverBootstrap.setPipelineFactory(new ServerPipelineFactory(this)); serverChannel = serverBootstrap.bind(new InetSocketAddress(node.getIp(), heartbeatPort)); logger.info("Heartbeat service listen on " +heartbeatAddress+":"+ heartbeatPort+" (Node's side)"); //start client if(balancers==null) clientController = new ClientController(this, lbAddress, lbPort, node, 5000 ,heartbeatPeriod, executor); else { String [] lbs = balancers.split(","); clientControllers = new ClientController [lbs.length]; for(int i=0; i < lbs.length; i++) { if(!isIpv6) node = new Node(name, "127.0.0.1"); else node = new Node(name, "::1"); node.getProperties().put(transport.toLowerCase() + "Port",""+ port); node.getProperties().put(Protocol.VERSION, version); node.getProperties().put(Protocol.HEARTBEAT_PORT, ""+heartbeatPort); clientControllers[i] = new ClientController(this, lbs[i].split(":")[0], Integer.parseInt(lbs[i].split(":")[1]), node, 5000 , heartbeatPeriod, executor); clientControllers[i].startClient(); } } if(sendHeartbeat) { if(balancers==null) clientController.startClient(); } } public void stop() { if(balancers==null) clientController.stopClient(false); else for(ClientController cc : clientControllers) cc.stopClient(false); serverChannel.unbind(); serverChannel.close(); serverChannel.getCloseFuture().awaitUninterruptibly(); nioServerSocketChannelFactory.shutdown(); isFirstStart = false; if(protocolObjects != null) protocolObjects.sipStack.stop(); protocolObjects=null; } public TestSipListener getTestSipListener() { return this.sipListener; } public Node getNode() { return node; } public void gracefulShutdown() { clientController.stopClient(true); } @Override public void responseReceived(JsonObject json) { } @Override public void stopRequestReceived(MessageEvent e, JsonObject json) { logger.info("stop request received from LB : " + json); if(balancers==null) clientController.restartClient(); else for(ClientController cc : clientControllers) { if(cc.getLbAddress().equals(json.get("ipAddress").toString().replace("\"",""))&&cc.getLbPort()==Integer.parseInt(json.get("port").toString())) { cc.restartClient(); logger.info("client controller connected to LB " +cc.getLbAddress() + ":"+ cc.getLbPort() + " have changed state to initial"); } } writeResponse(e, HttpResponseStatus.OK, Protocol.STOP, Protocol.OK); } private synchronized void writeResponse(MessageEvent e, HttpResponseStatus status, String command, String responceString) { Packet packet = null; switch(command) { case Protocol.STOP: packet = new StopResponsePacket(responceString); break; } ChannelBuffer buf = ChannelBuffers.copiedBuffer(gson.toJson(packet), Charset.forName("UTF-8")); HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status); response.setHeader(HttpHeaders.Names.CONTENT_TYPE, APPLICATION_JSON); response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, buf.readableBytes()); response.setContent(buf); ChannelFuture future = e.getChannel().write(response); future.addListener(ChannelFutureListener.CLOSE); } }