All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mobicents.ussdgateway.slee.sri.SriSbb Maven / Gradle / Ivy

There is a newer version: 7.1.63
Show newest version
/*
 * 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 
 */

package org.mobicents.ussdgateway.slee.sri;

import javax.slee.ActivityContextInterface;
import javax.slee.CreateException;
import javax.slee.SbbContext;

import org.mobicents.protocols.ss7.indicator.NatureOfAddress;
import org.mobicents.protocols.ss7.indicator.NumberingPlan;
import org.mobicents.protocols.ss7.indicator.RoutingIndicator;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContext;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContextName;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContextVersion;
import org.mobicents.protocols.ss7.map.api.MAPException;
import org.mobicents.protocols.ss7.map.api.MAPProvider;
import org.mobicents.protocols.ss7.map.api.dialog.MAPRefuseReason;
import org.mobicents.protocols.ss7.map.api.errors.MAPErrorCode;
import org.mobicents.protocols.ss7.map.api.errors.MAPErrorMessage;
import org.mobicents.protocols.ss7.map.api.primitives.AddressNature;
import org.mobicents.protocols.ss7.map.api.primitives.AddressString;
import org.mobicents.protocols.ss7.map.api.primitives.ISDNAddressString;
import org.mobicents.protocols.ss7.map.api.service.sms.MAPDialogSms;
import org.mobicents.protocols.ss7.map.api.service.sms.SendRoutingInfoForSMResponse;
import org.mobicents.protocols.ss7.sccp.impl.parameter.ParameterFactoryImpl;
import org.mobicents.protocols.ss7.sccp.parameter.GlobalTitle;
import org.mobicents.protocols.ss7.sccp.parameter.ParameterFactory;
import org.mobicents.protocols.ss7.sccp.parameter.SccpAddress;
import org.mobicents.protocols.ss7.tcap.api.MessageType;
import org.mobicents.protocols.ss7.tcap.asn.ApplicationContextName;
import org.mobicents.protocols.ss7.tcap.asn.comp.Problem;
import org.mobicents.slee.resource.map.MAPContextInterfaceFactory;
import org.mobicents.slee.resource.map.events.DialogClose;
import org.mobicents.slee.resource.map.events.DialogDelimiter;
import org.mobicents.slee.resource.map.events.DialogProviderAbort;
import org.mobicents.slee.resource.map.events.DialogReject;
import org.mobicents.slee.resource.map.events.DialogTimeout;
import org.mobicents.slee.resource.map.events.DialogUserAbort;
import org.mobicents.slee.resource.map.events.ErrorComponent;
import org.mobicents.slee.resource.map.events.InvokeTimeout;
import org.mobicents.slee.resource.map.events.RejectComponent;
import org.mobicents.ussdgateway.UssdPropertiesManagement;
import org.mobicents.ussdgateway.UssdPropertiesManagementMBean;
import org.mobicents.ussdgateway.UssdStatAggregator;
import org.mobicents.ussdgateway.XmlMAPDialog;
import org.mobicents.ussdgateway.slee.USSDBaseSbb;
import org.mobicents.ussdgateway.slee.cdr.RecordStatus;

/**
 * SRI lookup SBB
 * 
 * @author baranowb
 * @author sergey vetyutnev
 * 
 */
public abstract class SriSbb extends USSDBaseSbb implements SriChild {

	// -------------------------------------------------------------
	// Helper fields, to avoid initialization... over and over and over
	// -------------------------------------------------------------
	protected UssdPropertiesManagementMBean ussdPropertiesManagement = null;

	protected ParameterFactory sccpParameterFact;

	public SriSbb() {
		super("SriSbb");
	}

	// -------------------------------------------------------------
	// SBB LO
	// -------------------------------------------------------------
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.mobicents.ussdgateway.slee.sri.SriChild#performSRILookup(java.lang
	 * .String)
	 */
	@Override
	public void performSRIQuery(String msisdn, XmlMAPDialog xmlMapDialog) throws Exception {
		if (super.logger.isFineEnabled())
			super.logger.fine("Perform SRI on '" + msisdn + "'");

		this.setXmlMAPDialog(xmlMapDialog);
        this.setMsisdnCMP(msisdn);

        this.performSRIQuery(msisdn, getSriMAPApplicationContext());
	}

	public void performSRIQuery(String msisdn, MAPApplicationContext desiredContext) throws MAPException {
		if (super.logger.isFineEnabled())
			super.logger.fine("Perform SRI on '" + msisdn + "', '" + desiredContext + "'");

		MAPDialogSms mapDialogSms = null;
		int networkId = this.getXmlMAPDialog().getNetworkId();
		try {
			String hlrAddress = msisdn;
            if (ussdPropertiesManagement.getHrHlrGt() != null && ussdPropertiesManagement.getHrHlrGt().length() > 0
                    && !ussdPropertiesManagement.getHrHlrGt().equals("-1")) {
                hlrAddress = ussdPropertiesManagement.getHrHlrGt();
			}
			SccpAddress destAddress = this.convertAddressFieldToSCCPAddress(hlrAddress);

			if (super.logger.isFinestEnabled()) {
				super.logger.finest("Creating dialog Context '" + desiredContext + "',origAddress '"
						+ this.getUssdGwSccpAddress(networkId) + "', destAddress '" + destAddress + "'");
			}

			mapDialogSms = this.mapProvider.getMAPServiceSms().createNewDialog(desiredContext,
					this.getUssdGwSccpAddress(networkId), null, destAddress, null);
			mapDialogSms.setNetworkId(networkId);

			mapDialogSms.addSendRoutingInfoForSMRequest(this.getCalledPartyISDNAddressString(msisdn), true,
					this.getUssdGwAddress(networkId), null, false, null, null, null);

			// 2. Create the ACI and attach this SBB
			ActivityContextInterface sriDialogACI = this.mapAcif.getActivityContextInterface(mapDialogSms);
			sriDialogACI.attach(this.sbbContext.getSbbLocalObject());
			// 3. Finally send the request
			mapDialogSms.send();
		} catch (MAPException e) {
			if (logger.isSevereEnabled())
				logger.severe("Error while trying to send SendRoutingInfoForSMRequest", e);
			// something horrible, release MAPDialog and free resources

			if (mapDialogSms != null) {
				mapDialogSms.release();
			}

			throw e;
		}
	}

    // -------------------------------------------------------------
    // MAP event handlers: SRI
    // -------------------------------------------------------------

    /**
     * Received response for SRI sent earlier
     * 
     * @param evt
     * @param aci
     */
    public void onSendRoutingInfoForSMResponse(SendRoutingInfoForSMResponse evt, ActivityContextInterface aci) {
        if (this.logger.isFineEnabled()) {
            this.logger.fine("Received SEND_ROUTING_INFO_FOR_SM_RESPONSE = " + evt + " Dialog=" + evt.getMAPDialog());
        }

        this.setSendRoutingInfoForSMResponse(evt);
    }

	// -------------------------------------------------------------
	// MAP event handlers: regular
	// -------------------------------------------------------------

    public void onDialogDelimiter(DialogDelimiter evt, ActivityContextInterface aci) {
        try {
            this.onSriFullResponse(evt.getMAPDialog().getTCAPMessageType(), aci);
            evt.getMAPDialog().close(false);
        } catch (Throwable e1) {
            logger.severe("Exception in SriSbb.onDialogDelimiter when fetching records and issuing events: " + e1.getMessage(), e1);
        }
    }

    public void onDialogClose(DialogClose evt, ActivityContextInterface aci) {
        try {
            this.onSriFullResponse(evt.getMAPDialog().getTCAPMessageType(), aci);
        } catch (Throwable e1) {
            logger.severe("Exception in SriSbb.onDialogClose when fetching records and issuing events: " + e1.getMessage(), e1);
        }
    }

    private void onSriFullResponse(MessageType messageType, ActivityContextInterface aci) {
        SendRoutingInfoForSMResponse evt = this.getSendRoutingInfoForSMResponse();

        if (evt != null) {
            detachFromCurrentDialog(aci);

            SriSbbLocalObject local = (SriSbbLocalObject) super.sbbContext.getSbbLocalObject();
            SriParent parent = (SriParent) local.getParent();
            parent.onSRIResult(local, evt.getIMSI(), evt.getLocationInfoWithLMSI());
        } else {
            XmlMAPDialog xmlMAPDialog = this.getXmlMAPDialog();
            xmlMAPDialog.reset();
            MAPErrorMessage errorComponent = this.getErrorComponent();
            RecordStatus recordStatus = RecordStatus.FAILED_SYSTEM_FAILURE;
            try {
                if (errorComponent != null) {
                    xmlMAPDialog.sendErrorComponent(this.getErrorInvokeId(), errorComponent);

                    switch ((int) (long) (errorComponent.getErrorCode())) {
                    case MAPErrorCode.absentSubscriber:
                    case MAPErrorCode.absentSubscriberSM:
                        super.ussdStatAggregator.updateMapErrorAbsentSubscribers();
                        recordStatus = RecordStatus.SRI_ABSENT_SUBSCRIBER;
                        break;
                    case MAPErrorCode.callBarred:
                        super.ussdStatAggregator.updateMapErrorCallBarred();
                        recordStatus = RecordStatus.SRI_CALL_BARRED;
                        break;
                    case MAPErrorCode.teleserviceNotProvisioned:
                        super.ussdStatAggregator.updateMapErrorTeleserviceNotProvisioned();
                        recordStatus = RecordStatus.SRI_TELESERVICE_NOT_PROVISIONED;
                        break;
                    case MAPErrorCode.unknownSubscriber:
                        super.ussdStatAggregator.updateMapErrorUnknownSubscriber();
                        recordStatus = RecordStatus.SRI_UNKNOWN_SUBSCRIBER;
                        break;
                    default:
                        super.ussdStatAggregator.updateMapErrorComponentOther();
                        recordStatus = RecordStatus.SRI_MAP_ERROR_COMPONENT;
                        break;
                    }
                }
                Problem rejectProblem = this.getRejectProblem();
                if (rejectProblem != null) {
                    xmlMAPDialog.sendRejectComponent(this.getRejectInvokeId(), rejectProblem);
                    recordStatus = RecordStatus.SRI_MAP_REJECT_COMPONENT;
                }
            } catch (MAPException e) {
                // can not be Exception here
            }
            xmlMAPDialog.setTCAPMessageType(messageType);

            sendErrorToParent(xmlMAPDialog, recordStatus);
        }
    }

    public void onInvokeTimeout(InvokeTimeout evt, ActivityContextInterface aci) {
		// TODO:
		logger.warning("Invoke timeout received:" + evt);
		// this.sendErrorToParent();
	}

	public void onErrorComponent(ErrorComponent event, ActivityContextInterface aci) {
        if (logger.isWarningEnabled())
            logger.warning("Error component received:" + event);

        this.setErrorComponent(event.getMAPErrorMessage());
        this.setErrorInvokeId(event.getInvokeId());
	}

	public void onRejectComponent(RejectComponent event, ActivityContextInterface aci) {
        if (logger.isWarningEnabled())
            logger.warning("Reject component received:" + event);

        this.setRejectProblem(event.getProblem());
        this.setRejectInvokeId(event.getInvokeId());
	}

	public void onDialogReject(DialogReject evt, ActivityContextInterface aci) {

		MAPRefuseReason mapRefuseReason = evt.getRefuseReason();
		if (super.logger.isFineEnabled())
			super.logger.fine("Dialog rejected because '" + mapRefuseReason + "'");

		// If ACN not supported, lets use the new one suggested
		if (mapRefuseReason == MAPRefuseReason.ApplicationContextNotSupported) {
			detachFromCurrentDialog(aci);

			// Now send new SRI with supported ACN
			ApplicationContextName tcapApplicationContextName = evt.getAlternativeApplicationContext();
			MAPApplicationContext supportedMAPApplicationContext = MAPApplicationContext
					.getInstance(tcapApplicationContextName.getOid());

			try {
				this.performSRIQuery(getMsisdnCMP(), supportedMAPApplicationContext);
				return;
			} catch (MAPException e) {
				logger.severe("Error while trying to performSRIQuery", e);

			}
		}

		super.logger.severe("Dialog Rejected " + evt);

		XmlMAPDialog xmlMAPDialog = this.getXmlMAPDialog();
		xmlMAPDialog.reset();
		xmlMAPDialog.setMapRefuseReason(evt.getRefuseReason());
		xmlMAPDialog.setTCAPMessageType(evt.getMAPDialog().getTCAPMessageType());

        this.sendErrorToParent(xmlMAPDialog, RecordStatus.SRI_DIALOG_REJECTED);
	}

	public void onDialogUserAbort(DialogUserAbort evt, ActivityContextInterface aci) {
		if (super.logger.isWarningEnabled())
			super.logger.warning("User abort received: " + evt);
		try {
			XmlMAPDialog xmlMAPDialog = this.getXmlMAPDialog();
			xmlMAPDialog.reset();
			xmlMAPDialog.abort(evt.getUserReason());
			xmlMAPDialog.setTCAPMessageType(evt.getMAPDialog().getTCAPMessageType());

            this.sendErrorToParent(xmlMAPDialog, RecordStatus.SRI_DIALOG_USER_ABORT);
		} catch (MAPException e) {
			logger.severe("Error while trying to send back MAPUserAbortChoice to HTTP App", e);
		}
	}

	public void onDialogProviderAbort(DialogProviderAbort evt, ActivityContextInterface aci) {
		if (logger.isWarningEnabled())
			logger.warning("Provider abort received: " + evt);

		XmlMAPDialog xmlMAPDialog = this.getXmlMAPDialog();
		xmlMAPDialog.reset();
		xmlMAPDialog.setMapAbortProviderReason(evt.getAbortProviderReason());
		xmlMAPDialog.setTCAPMessageType(evt.getMAPDialog().getTCAPMessageType());

        this.sendErrorToParent(xmlMAPDialog, RecordStatus.SRI_PROVIDER_ABORT);
	}

	public void onDialogTimeout(DialogTimeout evt, ActivityContextInterface aci) {
		if (logger.isWarningEnabled())
			logger.warning("DialogTimeout received: " + evt);

		XmlMAPDialog xmlMAPDialog = this.getXmlMAPDialog();
		xmlMAPDialog.reset();
		xmlMAPDialog.setDialogTimedOut(true);
		if (evt.getMAPDialog().getTCAPMessageType() != null) {
			// TODO : MAP RA is setting MessaegType to null if Dialog is sent
			// and remote side never responded, fix this in RA
			xmlMAPDialog.setTCAPMessageType(evt.getMAPDialog().getTCAPMessageType());
		}

        super.ussdStatAggregator.updateMapDialogTimeouts();

		this.sendErrorToParent(xmlMAPDialog, RecordStatus.SRI_DIALOG_TIMEOUT);
	}

	// -------------------------------------------------------------
	// SLEE: callbacks
	// -------------------------------------------------------------

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.mobicents.ussdgateway.slee.USSDBaseSbb#setSbbContext(javax.slee.
	 * SbbContext)
	 */
	@Override
	public void setSbbContext(SbbContext sbbContext) {
		super.setSbbContext(sbbContext);
		super.logger = sbbContext.getTracer("SRI-" + getClass().getName());
		try {
			super.mapAcif = (MAPContextInterfaceFactory) super.sbbContext
					.getActivityContextInterfaceFactory(mapRATypeID);
			super.mapProvider = (MAPProvider) super.sbbContext.getResourceAdaptorInterface(mapRATypeID, mapRaLink);
			super.mapParameterFactory = super.mapProvider.getMAPParameterFactory();
            super.ussdStatAggregator = UssdStatAggregator.getInstance();

			this.ussdPropertiesManagement = UssdPropertiesManagement.getInstance();
			this.sccpParameterFact = new ParameterFactoryImpl();
		} catch (Exception ne) {
			if (logger.isSevereEnabled())
				super.logger.severe("Could not set SBB context:", ne);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.mobicents.ussdgateway.slee.USSDBaseSbb#unsetSbbContext()
	 */
	@Override
	public void unsetSbbContext() {
		super.unsetSbbContext();
		this.ussdPropertiesManagement = null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.mobicents.ussdgateway.slee.USSDBaseSbb#sbbCreate()
	 */
	@Override
	public void sbbCreate() throws CreateException {
		// TODO Auto-generated method stub
		super.sbbCreate();
	}

	// -------------------------------------------------------------
	// SLEE: CMPs
	// -------------------------------------------------------------
	public abstract void setXmlMAPDialog(XmlMAPDialog dialog);

	public abstract XmlMAPDialog getXmlMAPDialog();

	public abstract void setMsisdnCMP(String msisdn);

	public abstract String getMsisdnCMP();

	// address CMP stuff

	public abstract void setMAPApplicationContextCMP(MAPApplicationContext ctx);

	public abstract MAPApplicationContext getMAPApplicationContextCMP();

	public abstract void setUssdGwAddressCMP(AddressString gwAddress);

	public abstract AddressString getUssdGwAddressCMP();

	public abstract void setUssdGwSCCPAddressCMP(SccpAddress gwSccpAddress);

	public abstract SccpAddress getUssdGwSCCPAddressCMP();

    public abstract void setSendRoutingInfoForSMResponse(SendRoutingInfoForSMResponse sendRoutingInfoForSMResponse);

    public abstract SendRoutingInfoForSMResponse getSendRoutingInfoForSMResponse();

    public abstract void setErrorComponent(MAPErrorMessage errorComponent);

    public abstract MAPErrorMessage getErrorComponent();

    public abstract void setErrorInvokeId(long errorInvokeId);

    public abstract long getErrorInvokeId();

    public abstract void setRejectProblem(Problem rejectProblem);

    public abstract Problem getRejectProblem();

    public abstract void setRejectInvokeId(long rejectInvokeId);

    public abstract long getRejectInvokeId();

	// -------------------------------------------------------------
	// Helper methods
	// -------------------------------------------------------------

	protected ISDNAddressString getCalledPartyISDNAddressString(String destinationAddress) {
		return super.mapParameterFactory.createISDNAddressString(AddressNature.international_number,
				org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan.ISDN, destinationAddress);
	}

	protected SccpAddress convertAddressFieldToSCCPAddress(String address) {
		GlobalTitle gt = sccpParameterFact.createGlobalTitle(address, 0, NumberingPlan.ISDN_TELEPHONY, null,
				NatureOfAddress.INTERNATIONAL);
		return sccpParameterFact.createSccpAddress(RoutingIndicator.ROUTING_BASED_ON_GLOBAL_TITLE, gt, 0,
				ussdPropertiesManagement.getHlrSsn());
	}

	protected MAPApplicationContext getSriMAPApplicationContext() throws MAPException {
		MAPApplicationContext ctx = this.getMAPApplicationContextCMP();
		if (ctx == null) {
            ctx = MAPApplicationContext.getInstance(MAPApplicationContextName.shortMsgGatewayContext,
                    MAPApplicationContextVersion.getInstance(this.ussdPropertiesManagement.getMaxMapVersion()));
            if (ctx == null) {
                throw new MAPException("Not suitable context: " + MAPApplicationContextName.shortMsgGatewayContext + " for "
                        + this.ussdPropertiesManagement.getMaxMapVersion());
            }

			this.setMAPApplicationContextCMP(ctx);
		}
		return ctx;
	}

	protected AddressString getUssdGwAddress(int networkId) {
		AddressString address = this.getUssdGwAddressCMP();
		if (address == null) {
			address = this.mapParameterFactory.createAddressString(AddressNature.international_number,
					// TODO: getUssdGWGt seems wrong here?
					org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan.ISDN,
					ussdPropertiesManagement.getUssdGt(networkId));
			this.setUssdGwAddressCMP(address);
		}
		return address;
	}

	protected SccpAddress getUssdGwSccpAddress(int networkId) {
		SccpAddress address = this.getUssdGwSCCPAddressCMP();
		if (address == null) {
			GlobalTitle gt = sccpParameterFact.createGlobalTitle(ussdPropertiesManagement.getUssdGt(networkId), 0,
					NumberingPlan.ISDN_TELEPHONY, null, NatureOfAddress.INTERNATIONAL);
			address = sccpParameterFact.createSccpAddress(RoutingIndicator.ROUTING_BASED_ON_GLOBAL_TITLE, gt, 0,
					ussdPropertiesManagement.getUssdSsn());
			this.setUssdGwSCCPAddressCMP(address);
		}
		return address;
	}

	protected void detachFromCurrentDialog(ActivityContextInterface aci) {
		aci.detach(super.sbbContext.getSbbLocalObject());
		MAPDialogSms mapDialogSms = (MAPDialogSms) aci.getActivity();
		mapDialogSms.release();
	}

    private void sendErrorToParent(XmlMAPDialog xmlMAPDialog, RecordStatus recordStatus) {
        xmlMAPDialog.setSriPart(true);
        SriSbbLocalObject local = (SriSbbLocalObject) super.sbbContext.getSbbLocalObject();
        SriParent parent = (SriParent) local.getParent();
        parent.onSriError(xmlMAPDialog, recordStatus);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy