/*
* 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 gov.nist.javax.sip.ListeningPointExt;
import gov.nist.javax.sip.SipStackImpl;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import javax.sip.ListeningPoint;
import javax.sip.SipProvider;
import javax.sip.address.AddressFactory;
import javax.sip.header.HeaderFactory;
import javax.sip.header.RecordRouteHeader;
import javax.sip.message.MessageFactory;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.mobicents.tools.configuration.LoadBalancerConfiguration;
import org.mobicents.tools.heartbeat.api.Node;
import com.cloudhopper.smpp.SmppConstants;
public class BalancerContext {
/* We will store here all nodes we ever saw because we will need the addresses to determine the
* direction of requests where a dead node is involved. Otherwise if a node has died its address
* will be recognized as client address which is wrong. This only affects config with single port SIP LB.
* If internalPort is set there is no problem because we use other means to determine the direction.
*/
public HashSet<Node> allNodesEver = new HashSet<Node>();
public CopyOnWriteArrayList<Node> aliveNodes = null;
public ConcurrentHashMap<String, Node> jvmRouteToSipNode;
public ConcurrentHashMap<String, KeySip> regexMap;
public String algorithmClassName;
public String smppToNodeAlgorithmClassName;
public String smppToProviderAlgorithmClassName;
public String nodeCommunicationProtocolClassName;
public boolean securityRequired;
public String login;
public String password;
public AtomicInteger numberHttpRequest = new AtomicInteger(0);
public boolean terminateTLSTraffic;
public boolean isSendTrying;
public boolean isSend5xxResponse;
public String isSend5xxResponseReasonHeader;
public int isSend5xxResponseSatusCode;
public boolean isUseWithNexmo;
public String responsesReasonNodeRemoval;
public List<Integer> responsesStatusCodeNodeRemoval;
public String matchingHostnameForRoute;
public boolean isFilterSubdomain;
public String internalTransport;
public int shutdownTimeout;
public Object parameters;
SIPBalancerForwarder forwarder;
public SipProvider externalSipProvider;
public SipProvider externalIpv6SipProvider;
public SipProvider internalSipProvider;
public SipProvider internalIpv6SipProvider;
public String host;
public String ipv6Host;
public String externalHost;
public String externalIpv6Host;
public String internalHost;
public String internalIpv6Host;
public InetAddress ipv6HostAddress;
public InetAddress externalIpv6HostAddress;
public InetAddress internalIpv6HostAddress;
public int [] externalPorts;
public int [] externalIpv6Ports;
public int [] externalIpLoadBalancerPorts;
public int [] externalIpv6LoadBalancerPorts;
public int [] internalPorts;
public int [] internalIpv6Ports;
public int [] internalIpLoadBalancerPorts;
public int [] internalIpv6LoadBalancerPorts;
public String externalViaHost;
public String externalIpv6ViaHost;
public String internalViaHost;
public String internalIpv6ViaHost;
public int [] externalViaPorts;
public int [] externalIpv6ViaPorts;
public int [] internalViaPorts;
public int [] internalIpv6ViaPorts;
public ArrayList <String> internalIpLoadBalancerAddresses;
public ArrayList <String> internalIpv6LoadBalancerAddresses;
public ArrayList <String> externalIpLoadBalancerAddresses;
public ArrayList <String> externalIpv6LoadBalancerAddresses;
public ArrayList <InetAddress> internalIpv6LoadBalancerAddressHosts;
public ArrayList <InetAddress> externalIpv6LoadBalancerAddressHosts;
public String sipHeaderAffinityKey;
public Pattern sipHeaderAffinityKeyExclusionPattern;
public String sipHeaderAffinityFallbackKey;
public String publicIP;
public String publicIPv6;
public InetAddress publicIPv6Host;
public ArrayList<String> blockedList;
public AddressFactory addressFactory;
public HeaderFactory headerFactory;
public MessageFactory messageFactory;
public SipStackImpl sipStack;
public LoadBalancerConfiguration lbConfig;
public RecordRouteHeader[] externalRecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] externalIpv6RecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] externalIpBalancerRecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] externalIpv6BalancerRecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] internalRecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] internalIpv6RecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] internalIpBalancerRecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] internalIpv6BalancerRecordRouteHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] activeExternalHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] activeInternalHeader = new RecordRouteHeader[5];
public RecordRouteHeader[] activeExternalIpv6Header = new RecordRouteHeader[5];
public RecordRouteHeader[] activeInternalIpv6Header = new RecordRouteHeader[5];
//SIP balancer variables for monitoring
public boolean gatherStatistics = true;
public AtomicLong requestsProcessed = new AtomicLong(0);
public AtomicLong responsesProcessed = new AtomicLong(0);
public AtomicLong bytesTransferred = new AtomicLong(0);
private static final String[] METHODS_SUPPORTED =
{"REGISTER", "INVITE", "ACK", "BYE", "CANCEL", "MESSAGE", "INFO", "SUBSCRIBE", "NOTIFY", "UPDATE", "PUBLISH", "REFER", "PRACK", "OPTIONS"};
private static final String[] RESPONSES_PER_CLASS_OF_SC =
{"1XX", "2XX", "3XX", "4XX", "5XX", "6XX", "7XX", "8XX", "9XX"};
final Map<String, AtomicLong> requestsProcessedByMethod = new ConcurrentHashMap<String, AtomicLong>();
final Map<String, AtomicLong> responsesProcessedByStatusCode = new ConcurrentHashMap<String, AtomicLong>();
public boolean isTwoEntrypoints() {
return (internalPorts[0]>0
|| internalPorts[1]>0
|| internalPorts[2]>0
|| internalPorts[3]>0
|| internalPorts[4]>0) && internalHost != null;
}
public BalancerContext() {
for (String method : METHODS_SUPPORTED)
requestsProcessedByMethod.put(method, new AtomicLong(0));
for (String classOfSc : RESPONSES_PER_CLASS_OF_SC)
responsesProcessedByStatusCode.put(classOfSc, new AtomicLong(0));
for(String method : HTTP_METHODS)
httpRequestsProcessedByMethod.put(method, new AtomicLong(0));
for(String statusCode: HTTP_CODE_RESPONSE)
httpResponseProcessedByCode.put(statusCode, new AtomicLong(0));
for(Integer id : SMPP_REQUEST_IDS)
smppRequestsProcessedById.put(id, new AtomicLong(0));
for(Integer id : SMPP_RESPONSE_IDS)
smppResponsesProcessedById.put(id, new AtomicLong(0));
}
//HTTP balancer variables for monitoring
public AtomicLong httpRequests = new AtomicLong(0);
public AtomicLong httpBytesToServer = new AtomicLong(0);
public AtomicLong httpBytesToClient = new AtomicLong(0);
public Map<String, AtomicLong> httpRequestsProcessedByMethod = new ConcurrentHashMap<String, AtomicLong>();
public Map<String, AtomicLong> httpResponseProcessedByCode = new ConcurrentHashMap<String, AtomicLong>();
private static final String[] HTTP_METHODS = {
HttpMethod.CONNECT.getName(),
HttpMethod.DELETE.getName(),
HttpMethod.GET.getName(),
HttpMethod.HEAD.getName(),
HttpMethod.OPTIONS.getName(),
HttpMethod.PATCH.getName(),
HttpMethod.POST.getName(),
HttpMethod.PUT.getName(),
HttpMethod.TRACE.getName()
};
private static final String [] HTTP_CODE_RESPONSE =
{"1XX", "2XX", "3XX", "4XX", "5XX"};
//SMPP balancer variables for monitoring
public AtomicLong smppRequestsToServer = new AtomicLong(0);
public AtomicLong smppRequestsToClient = new AtomicLong(0);
public AtomicLong smppBytesToServer = new AtomicLong(0);
public AtomicLong smppBytesToClient = new AtomicLong(0);
public Map<Integer, AtomicLong> smppRequestsProcessedById = new ConcurrentHashMap<Integer, AtomicLong>();
public Map<Integer, AtomicLong> smppResponsesProcessedById = new ConcurrentHashMap<Integer, AtomicLong>();
private static final Integer[] SMPP_REQUEST_IDS =
{
SmppConstants.CMD_ID_BIND_RECEIVER,
SmppConstants.CMD_ID_BIND_TRANSMITTER,
SmppConstants.CMD_ID_QUERY_SM,
SmppConstants.CMD_ID_SUBMIT_SM,
SmppConstants.CMD_ID_DELIVER_SM,
SmppConstants.CMD_ID_UNBIND,
SmppConstants.CMD_ID_REPLACE_SM,
SmppConstants.CMD_ID_CANCEL_SM,
SmppConstants.CMD_ID_BIND_TRANSCEIVER,
SmppConstants.CMD_ID_OUTBIND,
SmppConstants.CMD_ID_ENQUIRE_LINK,
SmppConstants.CMD_ID_SUBMIT_MULTI,
SmppConstants.CMD_ID_DATA_SM
};
private static final Integer[] SMPP_RESPONSE_IDS =
{
SmppConstants.CMD_ID_GENERIC_NACK,
SmppConstants.CMD_ID_BIND_RECEIVER_RESP,
SmppConstants.CMD_ID_BIND_TRANSMITTER_RESP,
SmppConstants.CMD_ID_QUERY_SM_RESP,
SmppConstants.CMD_ID_SUBMIT_SM_RESP,
SmppConstants.CMD_ID_DELIVER_SM_RESP,
SmppConstants.CMD_ID_UNBIND_RESP,
SmppConstants.CMD_ID_REPLACE_SM_RESP,
SmppConstants.CMD_ID_CANCEL_SM_RESP,
SmppConstants.CMD_ID_BIND_TRANSCEIVER_RESP,
SmppConstants.CMD_ID_ENQUIRE_LINK_RESP,
SmppConstants.CMD_ID_SUBMIT_MULTI_RESP,
SmppConstants.CMD_ID_DATA_SM_RESP
};
public int getExternalPortByTransport(String transport, boolean isIpv6)
{
if(!isIpv6)
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return externalPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return externalPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return externalPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return externalPorts[1];
return externalPorts[0];
}
else
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return externalIpv6Ports[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return externalIpv6Ports[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return externalIpv6Ports[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return externalIpv6Ports[1];
return externalIpv6Ports[0];
}
}
public int getExternalViaPortByTransport(String transport, boolean isIpv6)
{
if(!isIpv6)
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return externalViaPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return externalViaPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return externalViaPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return externalViaPorts[1];
return externalViaPorts[0];
}
else
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return externalIpv6ViaPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return externalIpv6ViaPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return externalIpv6ViaPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return externalIpv6ViaPorts[1];
return externalIpv6ViaPorts[0];
}
}
public int getExternalLoadBalancerPortByTransport(String transport, boolean isIpv6)
{
if(!isIpv6)
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return externalIpLoadBalancerPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return externalIpLoadBalancerPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return externalIpLoadBalancerPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return externalIpLoadBalancerPorts[1];
return externalIpLoadBalancerPorts[0];
}
else
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return externalIpv6LoadBalancerPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return externalIpv6LoadBalancerPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return externalIpv6LoadBalancerPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return externalIpv6LoadBalancerPorts[1];
return externalIpv6LoadBalancerPorts[0];
}
}
public int getInternalPortByTransport(String transport, boolean isIpv6)
{
if(!isIpv6)
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return internalPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return internalPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return internalPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return internalPorts[1];
return internalPorts[0];
}
else
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return internalIpv6Ports[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return internalIpv6Ports[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return internalIpv6Ports[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return internalIpv6Ports[1];
return internalIpv6Ports[0];
}
}
public int getInternalViaPortByTransport(String transport, boolean isIpv6)
{
if(!isIpv6)
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return internalViaPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return internalViaPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return internalViaPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return internalViaPorts[1];
return internalViaPorts[0];
}
else
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return internalIpv6ViaPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return internalIpv6ViaPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return internalIpv6ViaPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return internalIpv6ViaPorts[1];
return internalIpv6ViaPorts[0];
}
}
public int getInternalLoadBalancerPortByTransport(String transport, boolean isIpv6)
{
if(!isIpv6)
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return internalIpLoadBalancerPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return internalIpLoadBalancerPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return internalIpLoadBalancerPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return internalIpLoadBalancerPorts[1];
return internalIpLoadBalancerPorts[0];
}
else
{
if(transport.equalsIgnoreCase(ListeningPointExt.WSS))
return internalIpv6LoadBalancerPorts[4];
if(transport.equalsIgnoreCase(ListeningPointExt.WS))
return internalIpv6LoadBalancerPorts[3];
if(transport.equalsIgnoreCase(ListeningPoint.TLS))
return internalIpv6LoadBalancerPorts[2];
if(transport.equalsIgnoreCase(ListeningPoint.TCP))
return internalIpv6LoadBalancerPorts[1];
return internalIpv6LoadBalancerPorts[0];
}
}
}