org.mobicents.slee.resources.smpp.SmppResourceAdaptor Maven / Gradle / Ivy
/*
* 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.slee.resources.smpp;
import java.io.IOException;
import java.io.Serializable;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import javax.slee.Address;
import javax.slee.AddressPlan;
import javax.slee.SLEEException;
import javax.slee.facilities.AlarmFacility;
import javax.slee.facilities.AlarmLevel;
import javax.slee.facilities.EventLookupFacility;
import javax.slee.facilities.Tracer;
import javax.slee.resource.ActivityAlreadyExistsException;
import javax.slee.resource.ActivityFlags;
import javax.slee.resource.ActivityHandle;
import javax.slee.resource.ConfigProperties;
import javax.slee.resource.FailureReason;
import javax.slee.resource.FireableEventType;
import javax.slee.resource.InvalidConfigurationException;
import javax.slee.resource.Marshaler;
import javax.slee.resource.ReceivableService;
import javax.slee.resource.ResourceAdaptorContext;
import javax.slee.resource.SleeEndpoint;
import javax.slee.resource.StartActivityException;
import net.java.slee.resources.smpp.SmppTransaction;
import org.mobicents.protocols.smpp.BadCommandIDException;
import org.mobicents.protocols.smpp.NotBoundException;
import org.mobicents.protocols.smpp.Session;
import org.mobicents.protocols.smpp.message.Bind;
import org.mobicents.protocols.smpp.message.BindReceiver;
import org.mobicents.protocols.smpp.message.BindTransceiver;
import org.mobicents.protocols.smpp.message.BindTransmitter;
import org.mobicents.protocols.smpp.message.CommandId;
import org.mobicents.protocols.smpp.message.EnquireLink;
import org.mobicents.protocols.smpp.version.SMPPVersion;
import org.mobicents.protocols.smpp.version.VersionException;
import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor;
import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext;
import org.mobicents.slee.resource.cluster.MemberAddress;
import org.mobicents.slee.resources.smpp.pdu.AlertNotificationImpl;
import org.mobicents.slee.resources.smpp.pdu.BroadcastSMImpl;
import org.mobicents.slee.resources.smpp.pdu.BroadcastSMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.CancelBroadcastSMImpl;
import org.mobicents.slee.resources.smpp.pdu.CancelBroadcastSMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.CancelSMImpl;
import org.mobicents.slee.resources.smpp.pdu.CancelSMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.DataSMImpl;
import org.mobicents.slee.resources.smpp.pdu.DataSMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.DeliverSMImpl;
import org.mobicents.slee.resources.smpp.pdu.DeliverSMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.GenericNackImpl;
import org.mobicents.slee.resources.smpp.pdu.QueryBroadcastSMImpl;
import org.mobicents.slee.resources.smpp.pdu.QueryBroadcastSMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.QuerySMImpl;
import org.mobicents.slee.resources.smpp.pdu.QuerySMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.ReplaceSMImpl;
import org.mobicents.slee.resources.smpp.pdu.ReplaceSMRespImpl;
import org.mobicents.slee.resources.smpp.pdu.SubmitMultiImpl;
import org.mobicents.slee.resources.smpp.pdu.SubmitMultiRespImpl;
import org.mobicents.slee.resources.smpp.pdu.SubmitSMImpl;
import org.mobicents.slee.resources.smpp.pdu.SubmitSMRespImpl;
/**
*
* @author amit bhayani
*
*/
@SuppressWarnings("rawtypes")
public class SmppResourceAdaptor implements FaultTolerantResourceAdaptor, org.mobicents.protocols.smpp.event.SessionObserver {
private transient Tracer tracer;
private transient ResourceAdaptorContext raContext;
private transient SleeEndpoint sleeEndpoint = null;
private transient EventLookupFacility eventLookup = null;
private transient SmppSessionImpl smppSession = null;
private transient FireableEventTypeCache eventTypeCache;
private transient FireableEventTypeFilter eventTypeFilter;
private transient FaultTolerantResourceAdaptorContext ftRAContext;
private SmppResourceAdaptorUsageParameters usageParams;
private Utils utils;
private Thread linkMonitorThread;
public String smscAlarm;
/**
* Configuration Properties
*/
private String host = "localhost";
private int port = 2727;
private String systemID = "1";
private String systemType = "ESME";
private String password = "1";
private int addressTON = 0;
private int addressNPI = 1;
private String addressRange = "50";
private int enquireLinkTimeout = 1000 * 30;
private String bindType = BindType.TRANSMITTER.toString();
private boolean statsOn;
private int smppResponseReceivedTimeout = 5000;
private int smppResponseSentTimeout = 5000;
/**
* SMPP API related variables
*/
protected org.mobicents.protocols.smpp.Session protoSmppSession = null;
protected org.mobicents.protocols.smpp.util.SequenceNumberScheme seq = null;;
private Semaphore semaphore = new Semaphore(0);
private int bindStatus;
private volatile boolean isRAStoped = false;
private Bind bind = null;
private long lastMessagesExchanged = 0l;
private long lastStatsUpdatedTime = 0l;
/**
* ActivityHandle holder
*/
private ConcurrentHashMap handleVsActivityMap = new ConcurrentHashMap();
public SmppResourceAdaptor() {
// TODO Auto-generated constructor stub
}
public void setHost(String host) {
this.host = host;
}
public String getHost() {
return host;
}
public void setPort(Integer port) {
this.port = port.intValue();
}
public Integer getPort() {
return new Integer(port);
}
public String getSystemId() {
return systemID;
}
public void setSystemId(String systemID) {
this.systemID = systemID;
}
public String getSystemType() {
return systemType;
}
public void setSystemType(String systemType) {
this.systemType = systemType;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAddressTon() {
return addressTON;
}
public void setAddressTon(Integer addressTON) {
this.addressTON = addressTON.intValue();
}
public Integer getAddressNpi() {
return new Integer(addressNPI);
}
public void setAddressNpi(Integer addressNPI) {
this.addressNPI = addressNPI.intValue();
}
public String getAddressRange() {
return addressRange;
}
public void setAddressRange(String addressRange) {
this.addressRange = addressRange;
}
public Integer getEnquireLinkTimeout() {
return this.enquireLinkTimeout;
}
public void setEnquireLinkTimeout(Integer enquireLinkTimeout) {
this.enquireLinkTimeout = enquireLinkTimeout.intValue() * 1000;
}
public String getBindType() {
return bindType;
}
public void setBindType(String bindTypeArg) {
bindType = bindTypeArg;
}
public int getSmppResponseReceivedTimeout() {
return smppResponseReceivedTimeout;
}
public void setSmppResponseReceivedTimeout(int smppResponseReceivedTimeout) {
if (smppResponseReceivedTimeout < 100) {
smppResponseReceivedTimeout = 5000;
}
this.smppResponseReceivedTimeout = smppResponseReceivedTimeout;
}
public int getSmppResponseSentTimeout() {
return smppResponseSentTimeout;
}
public void setSmppResponseSentTimeout(int smppResponseSentTimeout) {
if (smppResponseSentTimeout < 100) {
smppResponseSentTimeout = 5000;
}
this.smppResponseSentTimeout = smppResponseSentTimeout;
}
public void dataRemoved(Serializable arg0) {
// TODO Auto-generated method stub
}
public void failOver(Serializable arg0) {
if (this.tracer.isInfoEnabled()) {
this.tracer.info("Failed over the SMPP. Available memebers now ");
for (MemberAddress memAdd : this.ftRAContext.getMembers()) {
this.tracer.info(memAdd.toString());
}
}
}
public void setFaultTolerantResourceAdaptorContext(FaultTolerantResourceAdaptorContext arg0) {
tracer.info("setFaultTolerantResourceAdaptorContext(FaultTolerantResourceAdaptorContext arg0)");
this.ftRAContext = arg0;
}
public void unsetFaultTolerantResourceAdaptorContext() {
tracer.info("unsetFaultTolerantResourceAdaptorContext()");
this.ftRAContext = null;
}
public void activityEnded(ActivityHandle activityHandle) {
this.handleVsActivityMap.remove(activityHandle);
}
public void activityUnreferenced(ActivityHandle arg0) {
// TODO Auto-generated method stub
}
public void administrativeRemove(ActivityHandle arg0) {
// TODO Auto-generated method stub
}
public void eventProcessingFailed(ActivityHandle arg0, FireableEventType arg1, Object arg2, Address arg3, ReceivableService arg4, int arg5,
FailureReason arg6) {
// TODO Auto-generated method stub
}
public void eventProcessingSuccessful(ActivityHandle arg0, FireableEventType arg1, Object arg2, Address arg3, ReceivableService arg4, int arg5) {
// TODO Auto-generated method stub
}
public void eventUnreferenced(ActivityHandle arg0, FireableEventType arg1, Object arg2, Address arg3, ReceivableService arg4, int arg5) {
// TODO Auto-generated method stub
}
public Object getActivity(ActivityHandle activityHandle) {
return this.handleVsActivityMap.get(activityHandle);
}
public ActivityHandle getActivityHandle(Object obj) {
return ((SmppTransactionImpl) obj).getHandle();
}
public Marshaler getMarshaler() {
// TODO Auto-generated method stub
return null;
}
public Object getResourceAdaptorInterface(String arg0) {
return this.smppSession;
}
public void queryLiveness(ActivityHandle activityHandle) {
if (getActivity(activityHandle) == null) {
this.tracer.warning("The queryLiveness failed for activity " + activityHandle + " Ending this activity");
this.sleeEndpoint.endActivity(activityHandle);
}
}
public void raActive() {
if (this.tracer.isInfoEnabled()) {
tracer.info("Activation RA " + this.raContext.getEntityName());
}
this.lastMessagesExchanged = 0;
this.lastStatsUpdatedTime = System.currentTimeMillis();
try {
bindSMSC();
} catch (IOException e) {
this.tracer.severe("Binding to SMSC Failed ", e);
}
this.isRAStoped = false;
// Start the ENQUIRE Link Thread in any case
linkMonitorThread = new Thread(new LinkMonitor());
linkMonitorThread.start();
}
public void raConfigurationUpdate(ConfigProperties properties) {
raConfigure(properties);
}
public void raConfigure(ConfigProperties properties) {
if (tracer.isFineEnabled()) {
tracer.fine("Configuring RA Entity " + this.raContext.getEntityName());
}
setAddressNpi((Integer) properties.getProperty("addressNpi").getValue());
setAddressRange((String) properties.getProperty("addressRange").getValue());
setAddressTon((Integer) properties.getProperty("addressTon").getValue());
setEnquireLinkTimeout((Integer) properties.getProperty("enquireLinkTimeout").getValue());
setHost((String) properties.getProperty("host").getValue());
setPassword((String) properties.getProperty("password").getValue());
setPort((Integer) properties.getProperty("port").getValue());
setSystemId((String) properties.getProperty("systemId").getValue());
setSystemType((String) properties.getProperty("systemType").getValue());
setBindType((String) properties.getProperty("bindType").getValue());
setSmppResponseReceivedTimeout((Integer) properties.getProperty("smppResponseReceivedTimeout").getValue());
setSmppResponseSentTimeout((Integer) properties.getProperty("smppResponseSentTimeout").getValue());
statsOn = (Boolean) properties.getProperty("statsOn").getValue();
if (tracer.isFineEnabled()) {
StringBuffer sb = new StringBuffer();
sb.append("addressNpi = ").append(getAddressNpi()).append("\n").append("addressTon = ").append(getAddressTon()).append("\n")
.append("addressRange = ").append(getAddressRange()).append("\n").append("host = ").append(getHost()).append("\n").append("port = ")
.append(getPort()).append("\n").append("systemId = ").append(getSystemId()).append("\n").append("systemType = ").append(getSystemType())
.append("\n").append("password = ").append(getPassword()).append("\n").append("bindType = ").append(getBindType()).append("\n");
tracer.fine(sb.toString());
}
}
public void raInactive() {
this.unbindSMSC();
}
public void raStopping() {
isRAStoped = true;
this.smppSession.setIsAlive(false);
if (linkMonitorThread != null) {
linkMonitorThread.interrupt();
}
}
public void raUnconfigure() {
setAddressNpi(-1);
setAddressRange(null);
setAddressTon(-1);
setEnquireLinkTimeout(-1);
setHost(null);
setPassword(null);
setPort(-1);
setSystemId(null);
setSystemType(null);
setBindType(null);
}
public void raVerifyConfiguration(ConfigProperties properties) throws InvalidConfigurationException {
String addressRange = null;
String host = null;
String password = null;
String systemId = null;
String systemType = null;
BindType binidType = null;
try {
addressRange = (String) properties.getProperty("addressRange").getValue();
host = (String) properties.getProperty("host").getValue();
password = (String) properties.getProperty("password").getValue();
systemId = (String) properties.getProperty("systemId").getValue();
systemType = (String) properties.getProperty("systemType").getValue();
binidType = BindType.getBindType((String) properties.getProperty("bindType").getValue());
} catch (Throwable e) {
throw new InvalidConfigurationException(e.getMessage(), e);
}
if (addressRange == null) {
throw new InvalidConfigurationException("Address Range cannot be null");
} else if (host == null) {
throw new InvalidConfigurationException("Host (of SMSC) cannot be null");
} else if (password == null) {
throw new InvalidConfigurationException("Password cannot be null");
} else if (systemId == null) {
throw new InvalidConfigurationException("System ID cannot be null");
} else if (systemType == null) {
throw new InvalidConfigurationException("System Type cannot be null");
} else if (binidType == null) {
throw new InvalidConfigurationException("Bind Type cannot be null");
}
}
public void serviceActive(ReceivableService receivableService) {
this.eventTypeFilter.serviceActive(receivableService);
}
public void serviceInactive(ReceivableService receivableService) {
this.eventTypeFilter.serviceInactive(receivableService);
}
public void serviceStopping(ReceivableService receivableService) {
this.eventTypeFilter.serviceStopping(receivableService);
}
public void setResourceAdaptorContext(ResourceAdaptorContext raContext) {
this.tracer = raContext.getTracer(getClass().getSimpleName());
this.raContext = raContext;
this.sleeEndpoint = raContext.getSleeEndpoint();
this.eventLookup = raContext.getEventLookupFacility();
this.smppSession = new SmppSessionImpl(this);
this.eventTypeCache = new FireableEventTypeCache(tracer);
this.eventTypeFilter = new FireableEventTypeFilter();
this.usageParams = (SmppResourceAdaptorUsageParameters) raContext.getDefaultUsageParameterSet();
this.utils = new Utils(this);
}
public void unsetResourceAdaptorContext() {
this.raContext = null;
this.sleeEndpoint = null;
this.eventTypeCache = null;
this.eventTypeFilter = null;
this.usageParams = null;
}
/**
* ConnectionObserver methods
*/
public void packetReceived(Session source, org.mobicents.protocols.smpp.message.SMPPPacket packet) {
String entityName = raContext.getEntityName();
//Update usage params
incrementUsageParams(packet.getCommandId());
switch (packet.getCommandId()) {
// A connected ESME has requested to bind as an ESME Transceiver
// (by issuing a bind_transceiver PDU) and has received a response from
// the SMSC authorising its Bind request. An ESME bound as a Transceiver
// supports the complete set of operations supported by a Transmitter
// ESME and a Receiver ESME. Thus an ESME bound as a transceiver may
// send short messages to an SMSC for onward delivery to a Mobile
// Station
// or to another ESME. The ESME may also receive short messages from an
// SMSC which may be originated by a mobile station, by another ESME or
// by the SMSC itself (for example an SMSC delivery receipt).
case CommandId.BIND_TRANSCEIVER_RESP:
bindStatus = packet.getCommandStatus();
if (tracer.isFineEnabled()) {
tracer.fine(entityName + " receive bind_transaceiver_resp. Statu = " + bindStatus + " Message = " + this.utils.statusMessage(bindStatus));
}
semaphore.release();
break;
case CommandId.BIND_RECEIVER_RESP:
bindStatus = packet.getCommandStatus();
if (tracer.isFineEnabled()) {
tracer.fine(entityName + " receive bind_receiver_resp. Statu = " + bindStatus + " Message = " + this.utils.statusMessage(bindStatus));
}
semaphore.release();
break;
case CommandId.BIND_TRANSMITTER_RESP:
bindStatus = packet.getCommandStatus();
if (tracer.isFineEnabled()) {
tracer.fine(entityName + " receive bind_transmitter_resp. Statu = " + bindStatus + " Message = " + this.utils.statusMessage(bindStatus));
}
semaphore.release();
break;
// An ESME has unbound from the SMSC and has closed the network
// connection. The SMSC may also unbind from the ESME.
case CommandId.UNBIND_RESP: {
if (tracer.isFineEnabled()) {
tracer.fine(raContext.getEntityName() + " unbound successfuly");
}
semaphore.release();
break;
}
// This message can be sent by either the ESME or SMSC and is used
// to provide a confidence-check of the communication path between
// an ESME and an SMSC. On receipt of this request the receiving
// party should respond with an enquire_link_resp, thus verifying
// that the application level connection between the SMSC and the
// ESME is functioning. The ESME may also respond by sending any
// valid SMPP primitive.
case CommandId.ENQUIRE_LINK:
// TODO reply with enquire_link_resp
if (tracer.isFineEnabled()) {
tracer.fine("Enquire link packet received");
}
break;
case CommandId.ENQUIRE_LINK_RESP:
if (tracer.isFineEnabled()) {
tracer.fine("Enquire link response packet received");
}
break;
case CommandId.DELIVER_SM: {
DeliverSMImpl deliverSMImpl = new DeliverSMImpl((org.mobicents.protocols.smpp.message.DeliverSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(deliverSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
if (isEsmClassUserMessage(deliverSMImpl.getEsmClass())) {
fireEvent(Utils.DELIVER_SM, txImpl, deliverSMImpl);
} else {
fireEvent(Utils.DELIVERY_REPORT, txImpl, deliverSMImpl);
}
}
break;
}
// The command acknowledges deliver_sm message.
case CommandId.DELIVER_SM_RESP: {
// TODO : Take care of Delivery Acknowledgement
DeliverSMRespImpl deliverSMRespImpl = new DeliverSMRespImpl((org.mobicents.protocols.smpp.message.DeliverSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(deliverSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.DELIVER_SM_RESP, txImpl, deliverSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.DATA_SM: {
DataSMImpl dataSMImpl = new DataSMImpl((org.mobicents.protocols.smpp.message.DataSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(dataSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.DATA_SM, txImpl, dataSMImpl);
}
break;
}
case CommandId.DATA_SM_RESP: {
DataSMRespImpl dataSMRespImpl = new DataSMRespImpl((org.mobicents.protocols.smpp.message.DataSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(dataSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.DATA_SM_RESP, txImpl, dataSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.SUBMIT_SM: {
SubmitSMImpl submitSMImpl = new SubmitSMImpl((org.mobicents.protocols.smpp.message.SubmitSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(submitSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.SUBMIT_SM, txImpl, submitSMImpl);
}
break;
}
case CommandId.SUBMIT_SM_RESP: {
SubmitSMRespImpl submitSMRespImpl = new SubmitSMRespImpl((org.mobicents.protocols.smpp.message.SubmitSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(submitSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.SUBMIT_SM_RESP, txImpl, submitSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.SUBMIT_MULTI: {
SubmitMultiImpl submitMultiImpl = new SubmitMultiImpl((org.mobicents.protocols.smpp.message.SubmitMulti) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(submitMultiImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.SUBMIT_MULTI, txImpl, submitMultiImpl);
}
break;
}
case CommandId.SUBMIT_MULTI_RESP: {
SubmitMultiRespImpl submitMultiRespImpl = new SubmitMultiRespImpl((org.mobicents.protocols.smpp.message.SubmitMultiResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(submitMultiRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.SUBMIT_MULTI_RESP, txImpl, submitMultiRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.QUERY_SM: {
QuerySMImpl querySMImpl = new QuerySMImpl((org.mobicents.protocols.smpp.message.QuerySM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(querySMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.QUERY_SM, txImpl, querySMImpl);
}
break;
}
case CommandId.QUERY_SM_RESP: {
QuerySMRespImpl querySMRespImpl = new QuerySMRespImpl((org.mobicents.protocols.smpp.message.QuerySMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(querySMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.QUERY_SM_RESP, txImpl, querySMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.REPLACE_SM: {
ReplaceSMImpl replaceSMImpl = new ReplaceSMImpl((org.mobicents.protocols.smpp.message.ReplaceSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(replaceSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.REPLACE_SM, txImpl, replaceSMImpl);
}
break;
}
case CommandId.REPLACE_SM_RESP: {
ReplaceSMRespImpl replaceSMRespImpl = new ReplaceSMRespImpl((org.mobicents.protocols.smpp.message.ReplaceSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(replaceSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.REPLACE_SM_RESP, txImpl, replaceSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.CANCEL_SM: {
CancelSMImpl cancelSMImpl = new CancelSMImpl((org.mobicents.protocols.smpp.message.CancelSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(cancelSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.CANCEL_SM, txImpl, cancelSMImpl);
}
break;
}
case CommandId.CANCEL_SM_RESP: {
CancelSMRespImpl cancelSMRespImpl = new CancelSMRespImpl((org.mobicents.protocols.smpp.message.CancelSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(cancelSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.CANCEL_SM_RESP, txImpl, cancelSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.BROADCAST_SM: {
BroadcastSMImpl broadcastSMImpl = new BroadcastSMImpl((org.mobicents.protocols.smpp.message.BroadcastSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(broadcastSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.BROADCAST_SM, txImpl, broadcastSMImpl);
}
break;
}
case CommandId.BROADCAST_SM_RESP: {
BroadcastSMRespImpl broadcastSMRespImpl = new BroadcastSMRespImpl((org.mobicents.protocols.smpp.message.BroadcastSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(broadcastSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.BROADCAST_SM_RESP, txImpl, broadcastSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.CANCEL_BROADCAST_SM: {
CancelBroadcastSMImpl cancelBroadcastSMImpl = new CancelBroadcastSMImpl((org.mobicents.protocols.smpp.message.CancelBroadcastSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(cancelBroadcastSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.CANCEL_BROADCAST_SM, txImpl, cancelBroadcastSMImpl);
}
break;
}
case CommandId.CANCEL_BROADCAST_SM_RESP: {
CancelBroadcastSMRespImpl cancelBroadcastSMRespImpl = new CancelBroadcastSMRespImpl(
(org.mobicents.protocols.smpp.message.CancelBroadcastSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(cancelBroadcastSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.CANCEL_BROADCAST_SM_RESP, txImpl, cancelBroadcastSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.QUERY_BROADCAST_SM: {
QueryBroadcastSMImpl queryBroadcastSMImpl = new QueryBroadcastSMImpl((org.mobicents.protocols.smpp.message.QueryBroadcastSM) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(queryBroadcastSMImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.QUERY_BROADCAST_SM, txImpl, queryBroadcastSMImpl);
}
break;
}
case CommandId.QUERY_BROADCAST_SM_RESP: {
QueryBroadcastSMRespImpl queryBroadcastSMRespImpl = new QueryBroadcastSMRespImpl((org.mobicents.protocols.smpp.message.QueryBroadcastSMResp) packet);
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(queryBroadcastSMRespImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.QUERY_BROADCAST_SM_RESP, txImpl, queryBroadcastSMRespImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
break;
}
case CommandId.GENERIC_NACK: {
GenericNackImpl genericNackImpl = new GenericNackImpl((org.mobicents.protocols.smpp.message.GenericNack) packet);
if (genericNackImpl.getCommandStatus() == SmppTransaction.ESME_ROK) {
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Receievd GENERIC_NACK acknowledgemet " + genericNackImpl);
}
} else {
// This is Error Response to one of the Request sent
try {
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(genericNackImpl, false, SmppTransactionType.OUTGOING);
txImpl.cancelResponseNotReceivedTimeout();
fireEvent(Utils.GENERIC_NACK, txImpl, genericNackImpl);
this.endActivity(txImpl);
} catch (Exception e) {
this.tracer.warning("Activity not found for received SMPP Response " + packet, e);
}
}
break;
}
case CommandId.ALERT_NOTIFICATION: {
AlertNotificationImpl alertNotiImpl = new AlertNotificationImpl((org.mobicents.protocols.smpp.message.AlertNotification) packet);
SmppTransactionImpl txImpl = this.smppSession.getSmppTransactionImpl(alertNotiImpl, true, SmppTransactionType.INCOMING);
if (txImpl != null) {
fireEvent(Utils.ALERT_NOTIFICATION, txImpl, alertNotiImpl);
}
this.endActivity(txImpl);
break;
}
default:
tracer.warning("Unexpected packet received! Id = 0x" + Integer.toHexString(packet.getCommandId()));
}
}
public void update(Session source, org.mobicents.protocols.smpp.event.SMPPEvent smppEvent) {
switch (smppEvent.getType()) {
case org.mobicents.protocols.smpp.event.SMPPEvent.RECEIVER_START:
if (this.tracer.isFineEnabled()) {
this.tracer.fine("Receiver Thread started for SMPP RA " + this.raContext.getEntityName());
}
break;
case org.mobicents.protocols.smpp.event.SMPPEvent.RECEIVER_EXCEPTION:
if (this.tracer.isWarningEnabled()) {
org.mobicents.protocols.smpp.event.ReceiverExceptionEvent recExcepEvent = (org.mobicents.protocols.smpp.event.ReceiverExceptionEvent) smppEvent;
this.tracer.warning("The Receiver Thread for SMPP RA " + this.raContext.getEntityName() + " throws recovrable Exception ",
recExcepEvent.getException());
}
//This is recovrable error. Don't reconnect!
//this.reconnect();
break;
case org.mobicents.protocols.smpp.event.SMPPEvent.RECEIVER_EXIT:
org.mobicents.protocols.smpp.event.ReceiverExitEvent recExitEvent = (org.mobicents.protocols.smpp.event.ReceiverExitEvent) smppEvent;
switch (recExitEvent.getReason()) {
case org.mobicents.protocols.smpp.event.ReceiverExitEvent.EXCEPTION:
this.tracer.severe("The Receiver Thread for SMPP RA " + this.raContext.getEntityName() + " exited with error ", recExitEvent.getException());
this.reconnect();
break;
case org.mobicents.protocols.smpp.event.ReceiverExitEvent.BIND_TIMEOUT:
if (this.tracer.isFineEnabled()) {
this.tracer.fine("The Receiver Thread for SMPP RA " + this.raContext.getEntityName() + " exited with BIND_TIMEOUT");
}
break;
case org.mobicents.protocols.smpp.event.ReceiverExitEvent.UNKNOWN:
//This is graceful shutdown. No need to reconnect here
if (this.tracer.isFineEnabled()) {
this.tracer.fine("The Receiver Thread for SMPP RA " + this.raContext.getEntityName() + " exited normally");
}
break;
}
break;
}
}
/**
* Private Methods
*/
private void bindSMSC() throws UnknownHostException, IOException {
this.bindStatus = -1;
protoSmppSession = new org.mobicents.protocols.smpp.Session(host, port);
seq = protoSmppSession.getSequenceNumberScheme();
protoSmppSession.addObserver(this);
protoSmppSession.setVersion(SMPPVersion.VERSION_5_0);
// smscConnection.autoAckLink(true);
// smscConnection.autoAckMessages(true);
IOException ioException = null;
// Bind
try {
this.createBind();
protoSmppSession.bind(bind);
//Update usage params
incrementUsageParams(bind.getCommandId());
semaphore.drainPermits();
semaphore.tryAcquire(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
this.tracer.severe("Binding to SMS failed", e);
this.bindStatus = -1;
} catch (IOException e) {
this.bindStatus = -1;
ioException = e;
}
if (this.bindStatus != SmppTransaction.ESME_ROK) {
AlarmFacility alarmFacility = raContext.getAlarmFacility();
smscAlarm = alarmFacility.raiseAlarm(raContext.getEntityName(), "SMSCALARM", AlarmLevel.CRITICAL,
"SMSCALARM: bind status " + this.utils.statusMessage(bindStatus));
if (ioException != null) {
throw ioException;
} else {
throw new IOException("Could not bind to SMSC. The reason is " + this.utils.statusMessage(bindStatus));
}
}
tracer.info("Successfully bound to SMSC. ");
this.smppSession.setIsAlive(true);
if (smscAlarm != null) {
AlarmFacility alarmFacility = raContext.getAlarmFacility();
alarmFacility.clearAlarm(smscAlarm);
}
}
private Bind createBind() {
BindType bindType = BindType.getBindType(this.getBindType());
switch (bindType) {
case TRANSMITTER:
bind = new BindTransmitter();
break;
case RECEIVER:
bind = new BindReceiver();
break;
case TRANSCEIVER:
bind = new BindTransceiver();
break;
}
bind.setAddressTon(this.getAddressTon());
bind.setAddressNpi(this.getAddressNpi());
bind.setAddressRange(this.getAddressRange());
bind.setSystemType(this.getSystemType());
bind.setSystemId(this.getSystemId());
bind.setPassword(this.getPassword());
return bind;
}
/**
* reconnect() is called from LinkMonitor when connectivity between RA and
* SMSC fails. lets set isBound to true so while loop of LinkMonitor keeps
* trying to establish link again
*/
private void reconnect() {
try {
unbindSMSC();
this.protoSmppSession.closeLink();
} catch (Exception e) {
// ignore all errors during unbinding
}
try {
bindSMSC();
} catch (Exception e) {
if (tracer.isSevereEnabled())
tracer.severe("Reconnect error: " + e.getMessage());
}
}
private void unbindSMSC() {
this.smppSession.setIsAlive(false);
try {
protoSmppSession.unbind();
semaphore.drainPermits();
semaphore.tryAcquire(5, TimeUnit.SECONDS);
if (tracer.isInfoEnabled())
tracer.info(raContext.getEntityName() + ": unbinding from SMSC");
} catch (Exception e) {
if (tracer.isSevereEnabled())
tracer.severe("There was an error unbinding. ", e);
}
}
/**
* Checking if the EsmClass is user message or is at a notification.
*
* @param esmClassArg
* - esm_class value
* @return true if it is a user message, otherwise false
*/
private static boolean isEsmClassUserMessage(int esmClassArg) {
return (esmClassArg & 0X3C) == 0;
}
private void updateStats(){
if(statsOn) {
return;
}
long now = System.currentTimeMillis();
long elpasedNumberOfMessagesCounter = usageParams.getMessagesExchanged() - this.lastMessagesExchanged;
if(elpasedNumberOfMessagesCounter > 0){
double elpasedTimeInSec = (now - this.lastStatsUpdatedTime) / 1000;
double avgMessagesExchangedPerSec = elpasedNumberOfMessagesCounter / elpasedTimeInSec;
usageParams.sampleMessagesExchangedPerSec((long)avgMessagesExchangedPerSec);
}
this.lastMessagesExchanged = usageParams.getMessagesExchanged();
this.lastStatsUpdatedTime = now;
}
private void incrementUsageParams(int commandId) {
if(!statsOn) {
return;
}
usageParams.incrementMessagesExchanged(1);
switch (commandId) {
case CommandId.SUBMIT_SM:
usageParams.incrementReqSubmitSm(1);
break;
case CommandId.SUBMIT_SM_RESP:
usageParams.incrementResSubmitSm(1);
break;
case CommandId.DELIVER_SM:
usageParams.incrementReqDeliverSm(1);
break;
case CommandId.DELIVER_SM_RESP:
usageParams.incrementResDeliverSm(1);
break;
case CommandId.GENERIC_NACK:
usageParams.incrementGenericNack(1);
break;
case CommandId.BIND_RECEIVER:
usageParams.incrementReqBindReceiver(1);
break;
case CommandId.BIND_RECEIVER_RESP:
usageParams.incrementResBindReceiver(1);
break;
case CommandId.BIND_TRANSMITTER:
usageParams.incrementReqBindTransmitter(1);
break;
case CommandId.BIND_TRANSMITTER_RESP:
usageParams.incrementResBindTransmitter(1);
break;
case CommandId.QUERY_SM:
usageParams.incrementReqQuerySm(1);
break;
case CommandId.QUERY_SM_RESP:
usageParams.incrementResQuerySm(1);
break;
case CommandId.UNBIND:
usageParams.incrementReqUnbind(1);
break;
case CommandId.UNBIND_RESP:
usageParams.incrementResUnbind(1);
break;
case CommandId.REPLACE_SM:
usageParams.incrementReqReplaceSm(1);
break;
case CommandId.REPLACE_SM_RESP:
usageParams.incrementResReplaceSm(1);
break;
case CommandId.CANCEL_SM:
usageParams.incrementReqCancelSm(1);
break;
case CommandId.CANCEL_SM_RESP:
usageParams.incrementResCancelSm(1);
break;
case CommandId.BIND_TRANSCEIVER:
usageParams.incrementReqBindTransceiver(1);
break;
case CommandId.BIND_TRANSCEIVER_RESP:
usageParams.incrementResBindTransceiver(1);
break;
case CommandId.OUTBIND:
//TODO Supported?
break;
case CommandId.ENQUIRE_LINK:
usageParams.incrementReqEnquireLink(1);
break;
case CommandId.ENQUIRE_LINK_RESP:
usageParams.incrementResEnquireLink(1);
break;
case CommandId.SUBMIT_MULTI:
usageParams.incrementReqSubmitMulti(1);
break;
case CommandId.SUBMIT_MULTI_RESP:
usageParams.incrementResSubmitMulti(1);
break;
case CommandId.PARAM_RETRIEVE:
usageParams.incrementReqParamRetrieve(1);
break;
case CommandId.PARAM_RETRIEVE_RESP:
usageParams.incrementResParamRetrieve(1);
break;
case CommandId.QUERY_LAST_MSGS:
usageParams.incrementReqQueryLastMessages(1);
break;
case CommandId.QUERY_LAST_MSGS_RESP:
usageParams.incrementResQueryLastMessages(1);
break;
case CommandId.QUERY_MSG_DETAILS:
usageParams.incrementReqQueryMessageDetails(1);
break;
case CommandId.QUERY_MSG_DETAILS_RESP:
usageParams.incrementResQueryMessageDetails(1);
break;
case CommandId.ALERT_NOTIFICATION:
usageParams.incrementReqAlertNotification(1);
break;
case CommandId.DATA_SM:
usageParams.incrementReqDataSm(1);
break;
case CommandId.DATA_SM_RESP:
usageParams.incrementResDataSm(1);
break;
case CommandId.BROADCAST_SM:
usageParams.incrementReqBroadcastSm(1);
break;
case CommandId.BROADCAST_SM_RESP:
usageParams.incrementResBroadcastSm(1);
break;
case CommandId.QUERY_BROADCAST_SM:
usageParams.incrementReqQuerySm(1);
break;
case CommandId.QUERY_BROADCAST_SM_RESP:
usageParams.incrementResQuerySm(1);
break;
case CommandId.CANCEL_BROADCAST_SM:
usageParams.incrementReqBroadcastSm(1);
break;
case CommandId.CANCEL_BROADCAST_SM_RESP:
usageParams.incrementResBroadcastSm(1);
break;
default:
//Do nothing?
//tracer.warning("Unexpected packet received! Id = 0x" + Integer.toHexString(commandId));
}
}
/**
* Protected Methods
*
* @throws StartActivityException
* @throws SLEEException
* @throws IllegalStateException
* @throws NullPointerException
* @throws ActivityAlreadyExistsException
*/
protected void startNewSmppTransactionActivity(SmppTransactionImpl txImpl) throws ActivityAlreadyExistsException, NullPointerException,
IllegalStateException, SLEEException, StartActivityException {
sleeEndpoint.startActivity(txImpl.getHandle(), txImpl, ActivityFlags.REQUEST_ENDED_CALLBACK);
this.handleVsActivityMap.put(txImpl.getHandle(), txImpl);
}
protected void startNewSmppTransactionSuspendedActivity(SmppTransactionImpl txImpl) throws ActivityAlreadyExistsException, NullPointerException,
IllegalStateException, SLEEException, StartActivityException {
sleeEndpoint.startActivitySuspended(txImpl.getHandle(), txImpl, ActivityFlags.REQUEST_ENDED_CALLBACK);
this.handleVsActivityMap.put(txImpl.getHandle(), txImpl);
}
protected void sendResponse(ExtSmppResponse response) throws IOException {
this.protoSmppSession.sendPacket(response.getSMPPPacket());
//Update usage params
incrementUsageParams(response.getCommandId());
}
protected void sendRequest(ExtSmppRequest request) throws IOException {
this.protoSmppSession.sendPacket(request.getSMPPPacket());
//Update usage params
incrementUsageParams(request.getCommandId());
}
protected void fireEvent(String eventName, SmppTransactionImpl activity, Object event) {
final ActivityHandle handle = this.getActivityHandle(activity);
if (handle == null) {
this.tracer.warning("Firing event " + eventName + " for null ActivityHandle Activity=" + activity);
return;
}
final FireableEventType eventType = eventTypeCache.getEventType(eventLookup, eventName);
if (eventTypeFilter.filterEvent(eventType)) {
if (tracer.isFineEnabled()) {
tracer.fine("event " + eventName + " filtered");
}
return;
}
final String addressStr = this.utils.getAddressForEventFire(activity.getSmppRequest());
final Address address = new Address(AddressPlan.E164_MOBILE, addressStr);
try {
sleeEndpoint.fireEvent(handle, eventType, event, address, null);
if (tracer.isInfoEnabled()) {
tracer.info("Fired event: " + eventName);
}
} catch (Throwable e) {
tracer.severe("Failed to fire event", e);
}
}
protected void endActivity(SmppTransactionImpl activity) {
try {
this.sleeEndpoint.endActivity(activity.getHandle());
} catch (Exception e) {
this.tracer.severe("Error while Ending Activity " + activity, e);
}
}
/**
* Thread for sending ENQUIRE_LINK
*/
private class LinkMonitor implements Runnable {
public void run() {
if (tracer.isFineEnabled())
tracer.fine("In LinkMonitor, isRAStoped = " + isRAStoped);
// We keep trying only of we are bound atleast once and we are Head
// Member
while (!isRAStoped) {
// long currentTime = System.currentTimeMillis();
try {
Thread.sleep(enquireLinkTimeout);
updateStats();
try {
EnquireLink sm = new EnquireLink();
protoSmppSession.sendPacket(sm);
//Update usage params
incrementUsageParams(sm.getCommandId());
if (tracer.isFineEnabled()) {
tracer.fine("Sent enquire link for " + raContext.getEntityName());
}
} catch (NotBoundException nbe) {
if (tracer.isWarningEnabled())
tracer.warning("Connection lost! for RA " + raContext.getEntityName() + "Reconnecting...", nbe);
reconnect();
} catch (IOException ie) {
if (tracer.isSevereEnabled())
tracer.severe("Connection lost! for RA " + raContext.getEntityName() + " Communication failed", ie);
reconnect();
} catch (BadCommandIDException ex) {
tracer.severe("BadCommandIDException. Failed to enquire link ", ex);
} catch (VersionException ex) {
if (tracer.isSevereEnabled())
tracer.severe("Failed to enquire link due to wrong Version ", ex);
}
} catch (InterruptedException e) {
if (tracer.isInfoEnabled())
tracer.info("Terminate link monitor: " + raContext.getEntityName());
}
}// while loop
}
}
protected ResourceAdaptorContext getRAContext() {
return this.raContext;
}
public ConcurrentHashMap getHandleVsActivityMap() {
return handleVsActivityMap;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy