diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index d071129..f1e8943 --- a/.gitignore +++ b/.gitignore @@ -12,12 +12,23 @@ .idea *.iml -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -/.classpath -.classpath + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# Eclipse .project -/.project -target -/target/ -/.settings/ +.classpath +.settings +.checkstyle + +# JBoss +${env.JBOSS_HOME} diff --git a/core/bootstrap-wildfly/pom.xml b/core/bootstrap-wildfly/pom.xml old mode 100644 new mode 100755 diff --git a/core/bootstrap/pom.xml b/core/bootstrap/pom.xml old mode 100644 new mode 100755 diff --git a/core/oam/clismpp/pom.xml b/core/oam/clismpp/pom.xml old mode 100644 new mode 100755 diff --git a/core/pom.xml b/core/pom.xml old mode 100644 new mode 100755 diff --git a/core/smpp-extensions/pom.xml b/core/smpp-extensions/pom.xml old mode 100644 new mode 100755 diff --git a/core/smpp-extensions/src/main/java/org/restcomm/smpp/Esme.java b/core/smpp-extensions/src/main/java/org/restcomm/smpp/Esme.java old mode 100644 new mode 100755 index 848bb9c..222846c --- a/core/smpp-extensions/src/main/java/org/restcomm/smpp/Esme.java +++ b/core/smpp-extensions/src/main/java/org/restcomm/smpp/Esme.java @@ -51,8 +51,10 @@ public class Esme extends SslConfigurationWrapper implements XMLSerializable, Es * */ private static final long serialVersionUID = 1L; - - private static final Logger logger = Logger.getLogger(Esme.class); + + private static final Logger logger = Logger.getLogger(Esme.class); + + private static final String SEPARATOR = ","; private static final String ESME_NAME = "name"; @@ -63,6 +65,7 @@ public class Esme extends SslConfigurationWrapper implements XMLSerializable, Es private static final String REMOTE_HOST_IP = "host"; private static final String REMOTE_HOST_PORT = "port"; private static final String NETWORK_ID = "networkId"; + private static final String NETWORK_IDS = "networkIds"; private static final String SPLIT_LONG_MESSAGES = "splitLongMessages"; private static final String SMPP_BIND_TYPE = "smppBindType"; @@ -118,6 +121,7 @@ public class Esme extends SslConfigurationWrapper implements XMLSerializable, Es private String systemType; private SmppInterfaceVersionType smppVersion = null; private int networkId; + private int[] networkIds; // long messages will be split before sending to this destination private boolean splitLongMessages; @@ -341,7 +345,7 @@ public Esme(String name, String systemId, String password, String host, int port this.routingAddressRangePattern = Pattern.compile(this.routingAddressRange); } - this.networkId = networkId; + this.networkId = networkId; this.splitLongMessages = splitLongMessages; this.rateLimitPerSecond = rateLimitPerSecond; @@ -354,6 +358,7 @@ public Esme(String name, String systemId, String password, String host, int port this.destAddrSendLimit = destAddrSendLimit; this.minMessageLength = minMessageLength; this.maxMessageLength = maxMessageLength; + networkIds = convert(networkId); } /** @@ -1062,6 +1067,7 @@ public void read(javolution.xml.XMLFormat.InputElement xml, Esme esme) throws XM esme.host = xml.getAttribute(REMOTE_HOST_IP, ""); esme.port = xml.getAttribute(REMOTE_HOST_PORT, -1); esme.networkId = xml.getAttribute(NETWORK_ID, 0); + esme.networkIds = convert(xml.getAttribute(NETWORK_IDS, String.valueOf(esme.networkId)), esme.networkId); esme.splitLongMessages = xml.getAttribute(SPLIT_LONG_MESSAGES, false); esme.rateLimitPerSecond = xml.getAttribute(RATE_LIMIT_PER_SECOND, 0L); @@ -1170,6 +1176,7 @@ public void write(Esme esme, javolution.xml.XMLFormat.OutputElement xml) throws xml.setAttribute(REMOTE_HOST_IP, esme.host); xml.setAttribute(REMOTE_HOST_PORT, esme.port); xml.setAttribute(NETWORK_ID, esme.networkId); + xml.setAttribute(NETWORK_IDS, convert(esme.networkIds, esme.networkId)); xml.setAttribute(SPLIT_LONG_MESSAGES, esme.splitLongMessages); xml.setAttribute(RATE_LIMIT_PER_SECOND, esme.rateLimitPerSecond); @@ -1256,8 +1263,9 @@ public void show(StringBuffer sb) { .append(this.systemId).append(SmppOamMessages.SHOW_ESME_STATE).append(this.getStateName()) .append(SmppOamMessages.SHOW_ESME_PASSWORD).append(this.password).append(SmppOamMessages.SHOW_ESME_HOST) .append(this.host).append(SmppOamMessages.SHOW_ESME_PORT).append(this.port) - .append(SmppOamMessages.SHOW_NETWORK_ID).append(this.networkId).append(SmppOamMessages.CHARGING_ENABLED) - .append(this.chargingEnabled).append(SmppOamMessages.SHOW_ESME_BIND_TYPE).append(this.smppBindType) + .append(SmppOamMessages.SHOW_NETWORK_IDS).append(convert(networkIds, networkId)) + .append(SmppOamMessages.CHARGING_ENABLED) .append(this.chargingEnabled) + .append(SmppOamMessages.SHOW_ESME_BIND_TYPE).append(this.smppBindType) .append(SmppOamMessages.SHOW_ESME_SYSTEM_TYPE).append(this.systemType) .append(SmppOamMessages.SHOW_ESME_INTERFACE_VERSION).append(this.smppVersion) .append(SmppOamMessages.SHOW_ADDRESS_TON).append(this.esmeTon).append(SmppOamMessages.SHOW_ADDRESS_NPI) @@ -1792,4 +1800,61 @@ public boolean equals(Object obj) { public void store() { this.esmeManagement.store(); } + + /** + * Gets the network IDs. + * + * @return the network IDs + */ + int[] getNetworkIds() { + return networkIds; + } + + /** + * Sets the network IDs. + * + * @param aNetworkIds the new network IDs + */ + void setNetworkIds(final int[] aNetworkIds) { + networkIds = aNetworkIds; + } + + private static String convert(final int[] anIntArray, final int aSingleValue) { + if (anIntArray == null) { + return String.valueOf(aSingleValue); + } + if (anIntArray.length == 0) { + return String.valueOf(aSingleValue); + } + if (anIntArray.length == 1) { + return String.valueOf(anIntArray[0]); + } + final StringBuilder sb = new StringBuilder().append(anIntArray[0]); + for (int i = 1; i < anIntArray.length; i++) { + sb.append(SEPARATOR).append(anIntArray[i]); + } + return sb.toString(); + } + + private static int[] convert(final String aListOfIntegerValues, final int aSingleValue) { + if (aListOfIntegerValues == null) { + return convert(aSingleValue); + } + if (aListOfIntegerValues.isEmpty()) { + return convert(aSingleValue); + } + final String[] values = aListOfIntegerValues.split(SEPARATOR); + final int[] r = new int[values.length]; + for (int i = 0; i < values.length; i++) { + r[i] = Integer.parseInt(values[i]); + } + return r; + } + + private static int[] convert(final int aSingleNetworkId) { + final int[] r = new int[1]; + r[0] = aSingleNetworkId; + return r; + } + } diff --git a/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeCluster.java b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeCluster.java old mode 100644 new mode 100755 index 5428170..e372464 --- a/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeCluster.java +++ b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeCluster.java @@ -103,4 +103,41 @@ synchronized Esme getNextEsme() { boolean hasMoreEsmes() { return (esmes.size() > 0); } + + /** + * Checks if is OK for given request parameters. + * + * @param aTon the TON + * @param anNpi the NPI + * @param anAddress the address + * @param aName the a name + * @return true, if is OK for give parameters + */ + public boolean isOkFor(final int aTon, final int anNpi, final String anAddress, final String aName) { + for (FastList.Node n = esmesToSendPdu.head(), end = esmesToSendPdu.tail(); (n = n.getNext()) != end;) { + final Esme esme = n.getValue(); + if (esme.getName().equals(aName)) { + continue; + } + if (esme.isRoutingAddressMatching(aTon, anNpi, anAddress)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + final int count = esmes.size(); + final StringBuilder sb = new StringBuilder(); + sb.append(clusterName).append("["); + for (int i = 0; i < count; i++) { + sb.append(esmes.get(i).getName()); + if (i < count - 1) { + sb.append(","); + } + } + sb.append("]"); + return sb.toString(); + } } diff --git a/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagement.java b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagement.java old mode 100644 new mode 100755 index 44eab78..72c7933 --- a/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagement.java +++ b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagement.java @@ -74,6 +74,8 @@ public class EsmeManagement implements EsmeManagementMBean { private static final String CLASS_ATTRIBUTE = "type"; private static final XMLBinding binding = new XMLBinding(); private static final String PERSIST_FILE_NAME = "esme.xml"; + + private static final String ESME_CLUSTERS_SEPARATOR = ","; private final String name; @@ -83,7 +85,8 @@ public class EsmeManagement implements EsmeManagementMBean { protected FastMap esmesServer = new FastMap(); - protected FastMap esmeClusters = new FastMap(); + protected final FastMap esmeClusters = new FastMap(); + protected final FastMap esmeClusterByNetworkId = new FastMap(); private final TextBuilder persistFile = TextBuilder.newInstance(); @@ -213,7 +216,7 @@ public Esme createEsme(String name, String systemId, String password, String hos String smppSessionType, int windowSize, long connectTimeout, long requestExpiryTimeout, long clientBindTimeout, long windowMonitorInterval, long windowWaitTimeout, String clusterName, boolean countersEnabled, int enquireLinkDelay, int enquireLinkDelayServer, long linkDropServer, int sourceTon, int sourceNpi, - String sourceAddressRange, int routingTon, int routingNpi, String routingAddressRange, int networkId, + String sourceAddressRange, int routingTon, int routingNpi, String routingAddressRange, String networkId, boolean splitLongMessages, long rateLimitPerSecond, long rateLimitPerMinute, long rateLimitPerHour, long rateLimitPerDay, int nationalLanguageSingleShift, int nationalLanguageLockingShift, int destAddrSendLimit, int minMessageLength, int maxMessageLength) throws Exception { @@ -280,35 +283,23 @@ public Esme createEsme(String name, String systemId, String password, String hos // host, port, smppBindType)); // } }// for loop - - EsmeCluster esmeCluster = this.esmeClusters.get(clusterName); - if (esmeCluster != null) { - if (esmeCluster.getNetworkId() != networkId) { - throw new Exception(String.format(SmppOamMessages.CREATE_EMSE_FAIL_WRONG_NETWORKID_IN_ESMECLUSTER, esmeCluster.getNetworkId(), networkId)); - } - } - - if (clusterName == null) { - clusterName = name; - } + + final String clusterNames = correctClusterName(clusterName, name).trim(); + final int[] networkIds = validateClustersAndNetworkIds(clusterNames, networkId); Esme esme = new Esme(name, systemId, password, host, port, chargingEnabled, systemType, smppInterfaceVersionTypeObj, ton, npi, address, smppBindTypeOb, smppSessionTypeObj, windowSize, connectTimeout, requestExpiryTimeout, - clientBindTimeout, windowMonitorInterval, windowWaitTimeout, clusterName, countersEnabled, enquireLinkDelay, + clientBindTimeout, windowMonitorInterval, windowWaitTimeout, clusterNames, countersEnabled, enquireLinkDelay, enquireLinkDelayServer, linkDropServer, sourceTon, sourceNpi, sourceAddressRange, routingTon, routingNpi, - routingAddressRange, networkId, splitLongMessages, rateLimitPerSecond, rateLimitPerMinute, rateLimitPerHour, + routingAddressRange, networkIds[0], splitLongMessages, rateLimitPerSecond, rateLimitPerMinute, rateLimitPerHour, rateLimitPerDay, nationalLanguageSingleShift, nationalLanguageLockingShift, destAddrSendLimit, minMessageLength, maxMessageLength); + esme.setNetworkIds(networkIds); esme.esmeManagement = this; esmes.add(esme); - if (esmeCluster == null) { - esmeCluster = new EsmeCluster(clusterName, networkId); - this.esmeClusters.put(clusterName, esmeCluster); - } - - esmeCluster.addEsme(esme); + addEsmeToClusters(esme); this.store(); @@ -316,8 +307,8 @@ public Esme createEsme(String name, String systemId, String password, String hos return esme; } - - public Esme destroyEsme(String esmeName) throws Exception { + + public Esme destroyEsme(String esmeName) throws Exception { Esme esme = this.getEsmeByName(esmeName); if (esme == null) { throw new Exception(String.format(SmppOamMessages.DELETE_ESME_FAILED_NO_ESME_FOUND, esmeName)); @@ -329,11 +320,12 @@ public Esme destroyEsme(String esmeName) throws Exception { esmes.remove(esme); - EsmeCluster esmeCluster = this.esmeClusters.get(esme.getClusterName()); - esmeCluster.removeEsme(esme); - - if (!esmeCluster.hasMoreEsmes()) { - this.esmeClusters.remove(esme.getClusterName()); + for(final EsmeCluster esmeCluster : esmeClusters.values()) { + esmeCluster.removeEsme(esme); + if (!esmeCluster.hasMoreEsmes()) { + esmeClusters.remove(esme.getClusterName()); + esmeClusterByNetworkId.remove(esmeCluster.getNetworkId()); + } } this.store(); @@ -417,7 +409,7 @@ public void start() throws Exception { try { if (this.mbeanServer == null) { - this.mbeanServer = MBeanServerLocator.locateJBoss(); + this.mbeanServer = MBeanServerLocator.locateJBoss(); } } catch (Exception e) { } @@ -535,15 +527,7 @@ public void load() throws FileNotFoundException { esme.esmeManagement = this; - String esmeClusterName = esme.getClusterName(); - EsmeCluster esmeCluster = this.esmeClusters.get(esmeClusterName); - if (esmeCluster == null) { - esmeCluster = new EsmeCluster(esmeClusterName, esme.getNetworkId()); - this.esmeClusters.put(esmeClusterName, esmeCluster); - } else { - esme.setNetworkId(esmeCluster.getNetworkId()); - } - esmeCluster.addEsme(esme); + addEsmeToClusters(esme); } reader.close(); @@ -552,7 +536,17 @@ public void load() throws FileNotFoundException { // "Error while re-creating Linksets from persisted file", ex); } } - + + /** + * Gets the ESME cluster. + * + * @param aNetworkId the network ID + * @return the ESME cluster + */ + public EsmeCluster getEsmeCluster(final int aNetworkId) { + return esmeClusterByNetworkId.get(aNetworkId); + } + private void registerEsmeMbean(Esme esme) { try { ObjectName esmeObjNname = new ObjectName(SmppManagement.JMX_DOMAIN + ":layer=Esme,name=" + esme.getName()); @@ -586,6 +580,72 @@ private void unregisterEsmeMbean(String esmeName) { } } + private void addEsmeToClusters(final Esme anEsme) { + final int[] networkIds = anEsme.getNetworkIds(); + final String[] clusterNames = anEsme.getClusterName().split(ESME_CLUSTERS_SEPARATOR); + for (int i = 0; i < clusterNames.length; i++) { + addEsmeToCluster(anEsme, clusterNames[i].trim(), networkIds[i]); + } + } + + private void addEsmeToCluster(final Esme anEsme, + final String aClusterName, final int aNetworkId) { + getEsmeCluster(aClusterName, aNetworkId).addEsme(anEsme); + } + + private EsmeCluster getEsmeCluster(final String aName, + final int aNetworkId) { + final EsmeCluster ec = esmeClusters.get(aName); + if (ec == null) { + final EsmeCluster nec = new EsmeCluster(aName, aNetworkId); + esmeClusters.put(aName, nec); + esmeClusterByNetworkId.put(aNetworkId, nec); + return nec; + } + return ec; + } + + private static String correctClusterName(final String aClusterName, final String anEsmeName) throws EsmeManagementException { + if (aClusterName == null) { + if (anEsmeName == null) { + throw new EsmeManagementException("EsmeName is not specified."); + } + return anEsmeName; + } + return aClusterName; + } + + private int[] validateClustersAndNetworkIds(final String aClusterName, final String aNetworkId) + throws EsmeManagementException { + if ((aClusterName == null) || aClusterName.isEmpty()) { + throw new EsmeManagementException("Clusters name is not specified."); + } + final String[] clusters = aClusterName.split(ESME_CLUSTERS_SEPARATOR); + final String[] networkIds = aNetworkId.split(ESME_CLUSTERS_SEPARATOR); + if (clusters.length != networkIds.length) { + throw new EsmeManagementException("Clusters count (" + clusters.length + + ") does not match NetworkIds count (" + networkIds.length + ")."); + } + final int r[] = new int[clusters.length]; + for (int i = 0; i < clusters.length; i++) { + try { + r[i] = Integer.parseInt(networkIds[i]); + } catch (NumberFormatException e) { + throw new EsmeManagementException( + "NetworkId for cluster " + clusters[i].trim() + " has non-integer value: " + networkIds[i] + "."); + } + final EsmeCluster c = this.esmeClusters.get(clusters[i].trim()); + if (c == null) { + continue; + } + if (c.getNetworkId() != r[i]) { + throw new EsmeManagementException("NetworkId for cluster " + c + " has invalid value. Expected: " + + c.getNetworkId() + ". Actual: " + networkIds[i] + "."); + } + } + return r; + } + private class MessageCleanerTimerTask extends TimerTask { private int lastDay = -1; diff --git a/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagementException.java b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagementException.java new file mode 100755 index 0000000..d4a4854 --- /dev/null +++ b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagementException.java @@ -0,0 +1,40 @@ +/* + * Telestax, Open Source Cloud Communications Copyright 2011-2017, + * Telestax 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.restcomm.smpp; + +/** + * The Class EsmeManagementException. + */ +public final class EsmeManagementException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Instantiates a new ESME management exception. + * + * @param aMessage the message + */ + public EsmeManagementException(final String aMessage) { + super(aMessage); + } + +} diff --git a/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagementMBean.java b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagementMBean.java old mode 100644 new mode 100755 index 763cb0b..7436021 --- a/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagementMBean.java +++ b/core/smpp-extensions/src/main/java/org/restcomm/smpp/EsmeManagementMBean.java @@ -42,7 +42,7 @@ Esme createEsme(String name, String systemId, String password, String host, int String smppSessionType, int windowSize, long connectTimeout, long requestExpiryTimeout, long clientBindTimeout, long windowMonitorInterval, long windowWaitTimeout, String clusterName, boolean countersEnabled, int enquireLinkDelay, int enquireLinkDelayServer, long linkDropServer, int sourceTon, int sourceNpi, - String sourceAddressRange, int routingTon, int routingNpi, String routingAddressRange, int networkId, + String sourceAddressRange, int routingTon, int routingNpi, String routingAddressRange, String networkId, boolean splitLongMessages, long rateLimitPerSecond, long rateLimitPerMinute, long rateLimitPerHour, long rateLimitPerDay, int nationalLanguageSingleShift, int nationalLanguageLockingShift, int destAddrSendLimit, int minMessageLength, int maxMessageLength) throws Exception; @@ -52,5 +52,5 @@ Esme createEsme(String name, String systemId, String password, String host, int void startEsme(String esmeName) throws Exception; void stopEsme(String esmeName) throws Exception; - + } diff --git a/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppOamMessages.java b/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppOamMessages.java old mode 100644 new mode 100755 index d300406..67c619c --- a/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppOamMessages.java +++ b/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppOamMessages.java @@ -89,6 +89,8 @@ public interface SmppOamMessages { public static final String SHOW_NETWORK_ID = " networkId="; + public static final String SHOW_NETWORK_IDS = " networkIds="; + public static final String SPLIT_LONG_MESSAGES = " split-long-messages="; public static final String CHARGING_ENABLED = " chargingEnabled="; diff --git a/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppShellExecutor.java b/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppShellExecutor.java old mode 100644 new mode 100755 index 70243d4..8367d7d --- a/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppShellExecutor.java +++ b/core/smpp-extensions/src/main/java/org/restcomm/smpp/oam/SmppShellExecutor.java @@ -48,6 +48,7 @@ public class SmppShellExecutor implements ShellExecutor { private static final String LINE_SEPARATOR = System.getProperty("line.separator"); private static final String MAP_CACHE_KEY_VALUE_SEPARATOR = " : "; + private static final String NETWORK_ID_DEFAULT = "0"; public SmppShellExecutor() { @@ -288,7 +289,7 @@ private String createEsme(String[] args) throws Exception { String esmeAddrRange = null; String clusterName = name; String password = null; - int networkId = 0; + String networkId = NETWORK_ID_DEFAULT; boolean splitLongMessages = false; long rateLimitPerSecond = 0; long rateLimitPerMinute = 0; @@ -334,7 +335,7 @@ private String createEsme(String[] args) throws Exception { if (key.equals("password")) { password = args[count++]; } else if (key.equals("networkid")) { - networkId = Integer.parseInt(args[count++]); + networkId = args[count++]; } else if (key.equals("split-long-messages")) { splitLongMessages = Boolean.parseBoolean(args[count++]); } else if (key.equals("system-type")) { diff --git a/management/ui-management/pom.xml b/management/ui-management/pom.xml old mode 100644 new mode 100755 diff --git a/pom.xml b/pom.xml old mode 100644 new mode 100755