/* * 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.rmi; import java.io.IOException; import java.io.Serializable; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.RMISocketFactory; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.mobicents.tools.heartbeat.api.HeartbeatRequestPacket; import org.mobicents.tools.heartbeat.api.IListener; import org.mobicents.tools.heartbeat.api.IServerHeartbeatService; import org.mobicents.tools.heartbeat.api.IServerListener; import org.mobicents.tools.heartbeat.api.NodeShutdownRequestPacket; import org.mobicents.tools.heartbeat.api.NodeStopRequestPacket; import org.mobicents.tools.heartbeat.api.Protocol; import org.mobicents.tools.heartbeat.api.SIPNode; import org.mobicents.tools.heartbeat.api.StartRequestPacket; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonParser; /** * @author Konstantin Nosach (kostyantyn.nosach@telestax.com) */ public class ServerControllerRmi implements IListener,IServerHeartbeatService<HeartbeatConfigRmi> { private static Logger logger = Logger.getLogger(ServerControllerRmi.class.getCanonicalName()); private JsonParser parser = new JsonParser(); private Gson gson = new Gson(); private Registry registry; private int rmiRegistryPort = 2000; private int remoteObjectPort = 2001; private IServerListener listener; private ConcurrentHashMap<String, SIPNode> activeNodes = new ConcurrentHashMap<>(); private ConcurrentHashMap<String, SIPNode> shutdownNodes = new ConcurrentHashMap<>(); @Override public void startServer() { try { registry.bind("SIPBalancer", new RegisterRMIStub(remoteObjectPort)); logger.info("RMI heartbeat server bound to ports rmiRegistryPort " + rmiRegistryPort +" and remoteObjectPort "+ remoteObjectPort); } catch (Exception e) { throw new RuntimeException("Failed to bind due to:", e); } } @Override public void stopServer() { try { registry.unbind("SIPBalancer"); UnicastRemoteObject.unexportObject(registry, false); } catch (RemoteException e) { throw new RuntimeException("Failed to unbind due to", e); } catch (NotBoundException e) { throw new RuntimeException("Failed to unbind due to", e); } } @Override public void init(IServerListener listener, InetAddress serverAddress, HeartbeatConfigRmi config) { this.rmiRegistryPort = config.getRmiRegistryPort(); this.remoteObjectPort = config.getRmiRemoteObjectPort(); this.listener = listener; try { registry = LocateRegistry.createRegistry(rmiRegistryPort, null, new BindingAddressCorrectnessSocketFactory(serverAddress)); } catch (RemoteException e) { logger.info("RMI LocateRegistry creating failed, port " + rmiRegistryPort); } } @Override public void sendPacket(String ip, int parseInt) { } public static class BindingAddressCorrectnessSocketFactory extends RMISocketFactory implements Serializable { private static final long serialVersionUID = 1L; private InetAddress bindingAddress = null; public BindingAddressCorrectnessSocketFactory(InetAddress ipInterface) { this.bindingAddress = ipInterface; } public ServerSocket createServerSocket(int port) { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port, 50, bindingAddress); } catch (Exception e) { throw new RuntimeException(e); } return (serverSocket); } public Socket createSocket(String dummy, int port) throws IOException { return (new Socket(bindingAddress, port)); } public boolean equals(Object other) { return (other != null && other.getClass() == this.getClass()); } } private class RegisterRMIStub extends UnicastRemoteObject implements NodeRegisterRMIStub { /** * */ private static final long serialVersionUID = 1L; protected RegisterRMIStub(int port) throws RemoteException { super(port); } /* * (non-Javadoc) * @see org.mobicents.tools.sip.balancer.NodeRegisterRMIStub#handlePing(java.util.ArrayList) */ public void handlePing(ArrayList<SIPNode> ping) throws RemoteException { for(SIPNode node : ping) { String sessionId = (String)node.getProperties().get(Protocol.SESSION_ID); if(node.getProperties().get("GRACEFUL_SHUTDOWN")!=null&&node.getProperties().get("GRACEFUL_SHUTDOWN").equals("true")) { if(!shutdownNodes.containsKey(sessionId)) { shutdownNodes.put(sessionId, node); JsonObject jsonObject = parser.parse(gson.toJson(new NodeShutdownRequestPacket(node))).getAsJsonObject(); listener.shutdownRequestReceived(null, jsonObject); } continue; } if(!activeNodes.containsKey(sessionId)) { activeNodes.put(sessionId, node); JsonObject jsonObject = parser.parse(gson.toJson(new StartRequestPacket(node))).getAsJsonObject(); listener.startRequestReceived(null, jsonObject); } else { JsonObject jsonObject = parser.parse(gson.toJson(new HeartbeatRequestPacket(node))).getAsJsonObject(); listener.heartbeatRequestReceived(null, jsonObject); } } } /* * (non-Javadoc) * @see org.mobicents.tools.sip.balancer.NodeRegisterRMIStub#forceRemoval(java.util.ArrayList) */ public void forceRemoval(ArrayList<SIPNode> ping) throws RemoteException { for(SIPNode node : ping) { String sessionId = (String)node.getProperties().get(Protocol.SESSION_ID); activeNodes.remove(sessionId); JsonObject jsonObject = parser.parse(gson.toJson(new NodeStopRequestPacket(node))).getAsJsonObject(); listener.stopRequestReceived(null, jsonObject); } } public void switchover(String fromJvmRoute, String toJvmRoute) throws RemoteException { //listener.jvmRouteSwitchover(fromJvmRoute, toJvmRoute); } } // private boolean deregister(InetAddress serverAddress) { // // // } }