/* * TeleStax, Open Source Cloud Communications * Copyright 2012, 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.mobicents.smsc.slee.services.hr; import javax.slee.ActivityContextInterface; import javax.slee.SbbContext; 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.dialog.MAPAbortProviderReason; import org.mobicents.protocols.ss7.map.api.dialog.MAPRefuseReason; import org.mobicents.protocols.ss7.map.api.errors.MAPErrorMessage; import org.mobicents.protocols.ss7.map.api.errors.MAPErrorMessageAbsentSubscriber; 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.InformServiceCentreRequest; import org.mobicents.protocols.ss7.map.api.service.sms.MAPDialogSms; import org.mobicents.protocols.ss7.map.api.service.sms.MWStatus; import org.mobicents.protocols.ss7.map.api.service.sms.SendRoutingInfoForSMRequest; import org.mobicents.protocols.ss7.map.api.service.sms.SendRoutingInfoForSMResponse; import org.mobicents.protocols.ss7.sccp.parameter.SccpAddress; import org.mobicents.protocols.ss7.tcap.asn.ApplicationContextName; import org.mobicents.slee.resource.map.events.DialogClose; import org.mobicents.slee.resource.map.events.DialogDelimiter; import org.mobicents.slee.resource.map.events.DialogNotice; import org.mobicents.slee.resource.map.events.DialogProviderAbort; import org.mobicents.slee.resource.map.events.DialogReject; import org.mobicents.slee.resource.map.events.DialogRequest; 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.RejectComponent; import org.mobicents.smsc.domain.MProcManagement; import org.mobicents.smsc.library.CorrelationIdValue; import org.mobicents.smsc.library.MessageUtil; import org.mobicents.smsc.mproc.impl.MProcResult; /** * * @author amit bhayani * @author servey vetyutnev * */ public abstract class HrSriClientSbb extends HomeRoutingCommonSbb implements HrSriForwardInterface { protected MAPApplicationContextVersion maxMAPApplicationContextVersion = null; private static final String className = HrSriClientSbb.class .getSimpleName(); public HrSriClientSbb() { super(className); } public void onDialogRequest(DialogRequest evt, ActivityContextInterface aci) { super.onDialogRequest(evt, aci); } public void onDialogDelimiter(DialogDelimiter evt, ActivityContextInterface aci) { super.onDialogDelimiter(evt, aci); try { this.onSriFullResponse(); } catch (Throwable e1) { logger.severe("Exception in HrSriClientSbb.onDialogDelimiter (home routing) when fetching records and issuing events: " + e1.getMessage(), e1); } } public void onDialogClose(DialogClose evt, ActivityContextInterface aci) { try { super.onDialogClose(evt, aci); this.onSriFullResponse(); } catch (Throwable e1) { logger.severe("Exception in HrSriClientSbb.onDialogClose (home routing) when fetching records and issuing events: " + e1.getMessage(), e1); } } public void onRejectComponent(RejectComponent event, ActivityContextInterface aci) { super.onRejectComponent(event, aci); String reason = this.getRejectComponentReason(event); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue == null) { this.logger.severe("HrSriClientSbb.onRejectComponent(): CorrelationIdValue CMP missed"); return; } this.returnSriFailure(correlationIdValue, null, "Home routing: onRejectComponent after SRI Request: " + reason != null ? reason.toString() : ""); } public void onDialogReject(DialogReject evt, ActivityContextInterface aci) { super.onDialogReject(evt, aci); try { MAPRefuseReason mapRefuseReason = evt.getRefuseReason(); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue == null) { this.logger.severe("HrSriClientSbb.onDialogReject(): CorrelationIdValue CMP missed"); return; } if (mapRefuseReason == MAPRefuseReason.PotentialVersionIncompatibility && evt.getMAPDialog().getApplicationContext().getApplicationContextVersion() != MAPApplicationContextVersion.version1) { if (logger.isWarningEnabled()) { this.logger.warning("Home routing: Rx : Sri (home routing) onDialogReject / PotentialVersionIncompatibility=" + evt); } // possible a peer supports only MAP V1 // Now send new SRI with supported ACN (MAP V1) this.sendSRI(correlationIdValue.getMsisdn().getAddress(), correlationIdValue.getMsisdn().getAddressNature().getIndicator(), correlationIdValue .getMsisdn().getNumberingPlan().getIndicator(), this.getSRIMAPApplicationContext(MAPApplicationContextVersion.version1), correlationIdValue); return; } // If ACN not supported, lets use the new one suggested if (mapRefuseReason == MAPRefuseReason.ApplicationContextNotSupported) { if (logger.isWarningEnabled()) { this.logger.warning("Home routing: Rx : Sri (home routing) onDialogReject / ApplicationContextNotSupported=" + evt); } // Now send new SRI with supported ACN ApplicationContextName tcapApplicationContextName = evt.getAlternativeApplicationContext(); MAPApplicationContext supportedMAPApplicationContext = MAPApplicationContext.getInstance(tcapApplicationContextName.getOid()); this.sendSRI(correlationIdValue.getMsisdn().getAddress(), correlationIdValue.getMsisdn().getAddressNature().getIndicator(), correlationIdValue .getMsisdn().getNumberingPlan().getIndicator(), this.getSRIMAPApplicationContext(supportedMAPApplicationContext.getApplicationContextVersion()), correlationIdValue); return; } this.returnSriFailure(correlationIdValue, null, "Home routing: onDialogReject after SRI Request: " + mapRefuseReason != null ? mapRefuseReason.toString() : ""); } catch (Throwable e1) { logger.severe("Exception in SriSbb.onDialogReject() (home routing) when fetching records and issuing events: " + e1.getMessage(), e1); } } public void onDialogUserAbort(DialogUserAbort evt, ActivityContextInterface aci) { try { super.onDialogUserAbort(evt, aci); String reason = getUserAbortReason(evt); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue == null) { this.logger.severe("HrSriClientSbb.onDialogUserAbort(): CorrelationIdValue CMP missed"); return; } this.returnSriFailure(correlationIdValue, null, "(home routing) onDialogUserAbort after SRI Request: " + reason != null ? reason.toString() : ""); } catch (Throwable e1) { logger.severe("Exception in SriSbb.onDialogUserAbort() (home routing) when fetching records and issuing events: " + e1.getMessage(), e1); } } public void onDialogProviderAbort(DialogProviderAbort evt, ActivityContextInterface aci) { try { super.onDialogProviderAbort(evt, aci); MAPAbortProviderReason abortProviderReason = evt.getAbortProviderReason(); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue == null) { this.logger.severe("HrSriClientSbb.onDialogProviderAbort(): CorrelationIdValue CMP missed"); return; } this.returnSriFailure(correlationIdValue, null, "(home routing) onDialogProviderAbort after SRI Request: " + abortProviderReason != null ? abortProviderReason.toString() : ""); } catch (Throwable e1) { logger.severe("Exception in HrSriClientSbb.onDialogProviderAbort() (home routing) when fetching records and issuing events: " + e1.getMessage(), e1); } } public void onDialogNotice(DialogNotice evt, ActivityContextInterface aci) { super.onDialogNotice(evt, aci); } public void onDialogTimeout(DialogTimeout evt, ActivityContextInterface aci) { try { super.onDialogTimeout(evt, aci); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue == null) { this.logger.severe("HrSriClientSbb.onDialogTimeout(): CorrelationIdValue CMP missed"); return; } this.returnSriFailure(correlationIdValue, null, "(home routing) onDialogTimeout after SRI Request"); } catch (Throwable e1) { logger.severe("Exception in HrSriClientSbb.onDialogTimeout() (home routing) when fetching records and issuing events: " + e1.getMessage(), e1); } } /** * MAP SMS Events */ /** * Received SRI request. But this is error, we should never receive this * request * * @param evt * @param aci */ public void onSendRoutingInfoForSMRequest(SendRoutingInfoForSMRequest evt, ActivityContextInterface aci) { this.logger.severe("Received SEND_ROUTING_INFO_FOR_SM_REQUEST = " + evt); } /** * Received response for SRI sent earlier * * @param evt * @param aci */ public void onSendRoutingInfoForSMResponse(SendRoutingInfoForSMResponse evt, ActivityContextInterface aci) { if (this.logger.isFineEnabled()) { this.logger.fine("\nHome routing: HrSriClientSbb: Received SEND_ROUTING_INFO_FOR_SM_RESPONSE = " + evt + " Dialog=" + evt.getMAPDialog()); } if (evt.getMAPDialog().getApplicationContext().getApplicationContextVersion() == MAPApplicationContextVersion.version1 && evt.getMwdSet() != null && evt.getMwdSet()) { MWStatus mwStatus = evt.getMAPDialog().getService().getMAPProvider().getMAPParameterFactory() .createMWStatus(false, true, false, false); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue != null) { correlationIdValue.setMwStatus(mwStatus); correlationIdValue.setSriMapVersion(evt.getMAPDialog().getApplicationContext().getApplicationContextVersion().getVersion()); this.setCorrelationIdValue(correlationIdValue); } } this.setSendRoutingInfoForSMResponse(evt); } public void onInformServiceCentreRequest(InformServiceCentreRequest evt, ActivityContextInterface aci) { if (this.logger.isInfoEnabled()) { this.logger.info("\nHome routing: HrSriClientSbb: Received INFORM_SERVICE_CENTER_REQUEST = " + evt + " Dialog=" + evt.getMAPDialog()); } CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue != null) { correlationIdValue.setMwStatus(evt.getMwStatus()); correlationIdValue.setInformServiceCentreRequest(evt); this.setCorrelationIdValue(correlationIdValue); } } public void onErrorComponent(ErrorComponent event, ActivityContextInterface aci) { super.onErrorComponent(event, aci); try { // we store error into CMP MAPErrorMessage mapErrorMessage = event.getMAPErrorMessage(); this.setErrorResponse(mapErrorMessage); if (mapErrorMessage.isEmAbsentSubscriber()) { MAPErrorMessageAbsentSubscriber errAs = mapErrorMessage.getEmAbsentSubscriber(); Boolean mwdSet = errAs.getMwdSet(); if (mwdSet != null && mwdSet) { MWStatus mwStatus = event.getMAPDialog().getService().getMAPProvider().getMAPParameterFactory().createMWStatus(false, true, false, false); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue != null) { correlationIdValue.setMwStatus(mwStatus); this.setCorrelationIdValue(correlationIdValue); } } } } catch (Throwable e1) { logger.severe("Exception in HrSriClientSbb.onErrorComponent when fetching records and issuing events: " + e1.getMessage(), e1); } } /** * CMD */ public abstract void setCorrelationIdValue(CorrelationIdValue correlationIdValue); public abstract CorrelationIdValue getCorrelationIdValue(); public abstract void setSendRoutingInfoForSMResponse(SendRoutingInfoForSMResponse sendRoutingInfoForSMResponse); public abstract SendRoutingInfoForSMResponse getSendRoutingInfoForSMResponse(); public abstract void setErrorResponse(MAPErrorMessage errorResponse); public abstract MAPErrorMessage getErrorResponse(); public abstract void setSriMapVersion(int sriMapVersion); public abstract int getSriMapVersion(); public abstract void setInProcess(int inProcess); public abstract int getInProcess(); /** * SBB Local Object Methods * */ @Override public void setSbbContext(SbbContext sbbContext) { super.setSbbContext(sbbContext); this.maxMAPApplicationContextVersion = MAPApplicationContextVersion.getInstance(smscPropertiesManagement .getMaxMapVersion()); } @Override public void setupSriRequest(CorrelationIdValue correlationIdValue) { if (this.logger.isFineEnabled()) { this.logger.fine("\nHome routing: HrSriClientSbb: Received SriRequest: event= " + correlationIdValue); } this.setCorrelationIdValue(correlationIdValue); this.setInProcess(1); this.sendSRI(correlationIdValue.getMsisdn().getAddress(), correlationIdValue.getMsisdn().getAddressNature().getIndicator(), correlationIdValue .getMsisdn().getNumberingPlan().getIndicator(), this.getSRIMAPApplicationContext(this.maxMAPApplicationContextVersion), correlationIdValue); } private void sendSRI(String destinationAddress, int ton, int npi, MAPApplicationContext mapApplicationContext, CorrelationIdValue correlationIdValue) { // Send out SRI MAPDialogSms mapDialogSms = null; try { // 1. Create Dialog first and add the SRI request to it mapDialogSms = this.setupRoutingInfoForSMRequestIndication(destinationAddress, ton, npi, mapApplicationContext, correlationIdValue.getNetworkId()); // 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 (mapDialogSms != null) { mapDialogSms.release(); } String reason = "Home routing: HrSriClientSbb: MAPException when sending SRI from sendSRI(): " + e.toString(); this.logger.severe(reason, e); this.returnSriFailure(correlationIdValue, null, reason); } } private MAPDialogSms setupRoutingInfoForSMRequestIndication(String destinationAddress, int ton, int npi, MAPApplicationContext mapApplicationContext, int networkId) throws MAPException { // this.mapParameterFactory.creat String hlrAddress = destinationAddress; String hrHlrNumber = smscPropertiesManagement.getHrHlrNumber(networkId); if (hrHlrNumber != null && hrHlrNumber.length() > 0) { hlrAddress = hrHlrNumber; } SccpAddress destinationAddr = this.convertAddressFieldToSCCPAddress(hlrAddress, ton, npi); MAPDialogSms mapDialogSms = this.mapProvider.getMAPServiceSms().createNewDialog(mapApplicationContext, this.getServiceCenterSccpAddress(networkId), null, destinationAddr, null); mapDialogSms.setNetworkId(networkId); ISDNAddressString isdn = this.getCalledPartyISDNAddressString(destinationAddress, ton, npi); AddressString serviceCenterAddress = this.getServiceCenterAddressString(networkId); boolean sm_RP_PRI = true; mapDialogSms.addSendRoutingInfoForSMRequest(isdn, sm_RP_PRI, serviceCenterAddress, null, false, null, null, null); if (this.logger.isInfoEnabled()) this.logger.info("\nHome routing: HrSriClientSbb: Sending: SendRoutingInfoForSMRequest: isdn=" + isdn + ", serviceCenterAddress=" + serviceCenterAddress + ", sm_RP_PRI=" + sm_RP_PRI); return mapDialogSms; } private void onSriFullResponse() { SendRoutingInfoForSMResponse sendRoutingInfoForSMResponse = this.getSendRoutingInfoForSMResponse(); MAPErrorMessage errorMessage = this.getErrorResponse(); CorrelationIdValue correlationIdValue = this.getCorrelationIdValue(); if (correlationIdValue == null) { this.logger.severe("Home routing HrSriClientSbb.onSriFullResponse(): CorrelationIdValue CMP missed"); return; } if (sendRoutingInfoForSMResponse != null) { // we have positive response to SRI request correlationIdValue.setImsi(sendRoutingInfoForSMResponse.getIMSI().getData()); correlationIdValue.setLocationInfoWithLMSI(sendRoutingInfoForSMResponse.getLocationInfoWithLMSI()); correlationIdValue.setSendRoutingInfoForSMResponse(sendRoutingInfoForSMResponse); MProcResult mProcResult = MProcManagement.getInstance().applyMProcHrSri(getMProcRuleRa(), correlationIdValue); if (mProcResult.isHrIsByPassed()) { this.returnSriHrByPass(correlationIdValue); } else { this.returnSriSuccess(correlationIdValue); } return; } if (errorMessage != null) { // we have a negative response this.returnSriFailure(correlationIdValue, errorMessage, "Home routing HrSriClientSbb.onSriFullResponse(): MAP ErrorMessage received: " + errorMessage); } else { // we have no responses - this is an error behaviour this.returnSriFailure(correlationIdValue, null, "Home routing HrSriClientSbb.onSriFullResponse(): Empty response after SRI Request"); } } private void returnSriSuccess(CorrelationIdValue correlationIdValue) { int inProcess = this.getInProcess(); if (inProcess == 0) // SriSucess or Failure is already processed return; HrSriClientSbbLocalObject local = (HrSriClientSbbLocalObject) super.sbbContext.getSbbLocalObject(); HrSriResultInterface parent = (HrSriResultInterface) local.getParent(); parent.onSriSuccess(correlationIdValue, false); } private void returnSriHrByPass(CorrelationIdValue correlationIdValue) { int inProcess = this.getInProcess(); if (inProcess == 0) // SriSucess or Failure is already processed return; HrSriClientSbbLocalObject local = (HrSriClientSbbLocalObject) super.sbbContext.getSbbLocalObject(); HrSriResultInterface parent = (HrSriResultInterface) local.getParent(); parent.onSriHrByPass(correlationIdValue); } private void returnSriFailure(CorrelationIdValue correlationIdValue, MAPErrorMessage errorResponse, String cause) { int inProcess = this.getInProcess(); if (inProcess == 0) // SriSuccess or Failure is already processed return; this.setInProcess(0); HrSriClientSbbLocalObject local = (HrSriClientSbbLocalObject) super.sbbContext.getSbbLocalObject(); HrSriResultInterface parent = (HrSriResultInterface) local.getParent(); parent.onSriFailure(correlationIdValue, errorResponse, cause); } private SccpAddress convertAddressFieldToSCCPAddress(String address, int ton, int npi) { return MessageUtil.getSccpAddress(sccpParameterFact, address, ton, npi, smscPropertiesManagement.getHlrSsn(), smscPropertiesManagement.getGlobalTitleIndicator(), smscPropertiesManagement.getTranslationType()); } private MAPApplicationContext getSRIMAPApplicationContext(MAPApplicationContextVersion applicationContextVersion) { MAPApplicationContext mapApplicationContext = MAPApplicationContext.getInstance( MAPApplicationContextName.shortMsgGatewayContext, applicationContextVersion); this.setSriMapVersion(applicationContextVersion.getVersion()); return mapApplicationContext; } }