/* * 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.ActivityEndEvent; import javax.slee.EventContext; import javax.slee.InitialEventSelector; import javax.slee.ServiceID; import javax.slee.serviceactivity.ServiceActivity; import javax.slee.serviceactivity.ServiceStartedEvent; 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.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.IMSI; import org.mobicents.protocols.ss7.map.api.primitives.ISDNAddressString; import org.mobicents.protocols.ss7.map.api.primitives.NetworkResource; import org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan; import org.mobicents.protocols.ss7.map.api.service.sms.InformServiceCentreRequest; import org.mobicents.protocols.ss7.map.api.service.sms.LocationInfoWithLMSI; 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.slee.ChildRelationExt; 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.MoChargingType; import org.mobicents.smsc.domain.NextCorrelationIdResult; import org.mobicents.smsc.library.CorrelationIdValue; import org.mobicents.smsc.library.SbbStates; import org.mobicents.smsc.library.SmsSetCache; /** * * @author amit bhayani * @author servey vetyutnev * */ public abstract class HrSriServerSbb extends HomeRoutingCommonSbb implements HrSriResultInterface { private static final String className = HrSriServerSbb.class.getSimpleName(); public HrSriServerSbb() { super(className); } public void onDialogRequest(DialogRequest evt, ActivityContextInterface aci) { super.onDialogRequest(evt, aci); } public void onDialogDelimiter(DialogDelimiter evt, ActivityContextInterface aci) { super.onDialogDelimiter(evt, aci); } public void onErrorComponent(ErrorComponent event, ActivityContextInterface aci) { super.onErrorComponent(event, aci); } public void onRejectComponent(RejectComponent event, ActivityContextInterface aci) { super.onRejectComponent(event, aci); } public void onDialogReject(DialogReject evt, ActivityContextInterface aci) { super.onDialogReject(evt, aci); } public void onDialogUserAbort(DialogUserAbort evt, ActivityContextInterface aci) { super.onDialogUserAbort(evt, aci); } public void onDialogProviderAbort(DialogProviderAbort evt, ActivityContextInterface aci) { super.onDialogProviderAbort(evt, aci); } public void onDialogNotice(DialogNotice evt, ActivityContextInterface aci) { super.onDialogNotice(evt, aci); } public void onDialogTimeout(DialogTimeout evt, ActivityContextInterface aci) { super.onDialogTimeout(evt, aci); } /** * Initial event selector method to check if the Event should initalize the */ public InitialEventSelector initialEventSelect(InitialEventSelector ies) { Object event = ies.getEvent(); DialogRequest dialogRequest = null; if (event instanceof DialogRequest) { dialogRequest = (DialogRequest) event; if (MAPApplicationContextName.shortMsgGatewayContext == dialogRequest .getMAPDialog().getApplicationContext() .getApplicationContextName()) { ies.setInitialEvent(true); ies.setActivityContextSelected(true); } else { ies.setInitialEvent(false); } } return ies; } /** * 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) { if (this.logger.isInfoEnabled()) { this.logger.info("\nHome routing: HrSriServerSbb: Received SEND_ROUTING_INFO_FOR_SM_REQUEST = " + evt + " Dialog=" + evt.getMAPDialog()); } this.setInvokeId(evt.getInvokeId()); MAPDialogSms dialog = evt.getMAPDialog(); // we are changing here SSN in CallingPartyAddress of a SRI response to HLR SSN // because it is possible that this address has been updated inside SCCP routing procedure // when a message came to SMSC // TODO: check if it is a proper solution ? SccpAddress locAddr = dialog.getLocalAddress(); SccpAddress locAddr2 = sccpParameterFact.createSccpAddress(locAddr.getAddressIndicator().getRoutingIndicator(), locAddr.getGlobalTitle(), locAddr.getSignalingPointCode(), smscPropertiesManagement.getHlrSsn()); dialog.setLocalAddress(locAddr2); if (smscPropertiesManagement.getHrCharging() == MoChargingType.reject) { try { MAPErrorMessage errorMessage = this.mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageFacilityNotSup(null, null, null); dialog.sendErrorComponent(evt.getInvokeId(), errorMessage); if (this.logger.isInfoEnabled()) { this.logger.info("\nHome routing: Sent ErrorComponent = " + errorMessage); } dialog.close(false); return; } catch (Throwable e) { logger.severe("Home routing: Error while sending Error message", e); return; } } setupSriRequest(evt.getMsisdn(), evt.getServiceCentreAddress(), dialog.getNetworkId(), dialog.getRemoteAddress()); } /** * Received response for SRI sent earlier * * @param evt * @param aci */ public void onSendRoutingInfoForSMResponse(SendRoutingInfoForSMResponse evt, ActivityContextInterface aci) { this.logger.severe("Home routing: Received SEND_ROUTING_INFO_FOR_SM_RESPONSE = " + evt); } private void setupSriRequest(ISDNAddressString msisdn, AddressString serviceCentreAddress, int networkId, SccpAddress originatorSccpAddress) { smscStatAggregator.updateMsgInHrSriReq(); HrSriClientSbbLocalObject hrSriClientSbbLocalObject = this.getHrSriClientSbbLocalObject(); if (hrSriClientSbbLocalObject != null) { String sca = msisdn.getAddress(); NextCorrelationIdResult correlationIDRes = homeRoutingManagement.getNextCorrelationId(sca); if (correlationIDRes.getSmscAddress() != null && !correlationIDRes.getSmscAddress().equals("")) this.setSmscAddressForCountryCode(correlationIDRes.getSmscAddress()); String correlationID = correlationIDRes.getCorrelationId(); CorrelationIdValue correlationIdValue = new CorrelationIdValue(correlationID, msisdn, serviceCentreAddress, networkId, originatorSccpAddress); boolean sriBypass = smscPropertiesManagement.getHrSriBypass(networkId); if (sriBypass) { // bypass of SRI request to a local HLR - just sending of a response onSriSuccess(correlationIdValue, true); } else { // sending SRI request to a local HLR hrSriClientSbbLocalObject.setupSriRequest(correlationIdValue); } if (this.logger.isFineEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("Home routing: Created correlationId="); sb.append(correlationID); sb.append(" for received ServiceCentedAddress="); sb.append(sca); sb.append(" sriBypass: "); sb.append(sriBypass); this.logger.fine(sb.toString()); } } } /** * CMD */ public abstract void setInvokeId(long invokeId); public abstract long getInvokeId(); public abstract void setSmscAddressForCountryCode(String smscAddress); public abstract String getSmscAddressForCountryCode(); public void onServiceStartedEvent(ServiceStartedEvent event, ActivityContextInterface aci, EventContext eventContext) { ServiceID serviceID = event.getService(); this.logger.info("Rx: onServiceStartedEvent: event=" + event + ", serviceID=" + serviceID); SbbStates.setHomeRoutingServiceState(true); } public void onActivityEndEvent(ActivityEndEvent event, ActivityContextInterface aci, EventContext eventContext) { boolean isServiceActivity = (aci.getActivity() instanceof ServiceActivity); if (isServiceActivity) { this.logger.info("Rx: onActivityEndEvent: event=" + event + ", isServiceActivity=" + isServiceActivity); SbbStates.setHomeRoutingServiceState(false); } } /** * Get HrSriClientSbb child SBB * * @return */ public abstract ChildRelationExt getHrSriClientSbb(); private HrSriClientSbbLocalObject getHrSriClientSbbLocalObject() { ChildRelationExt relation = getHrSriClientSbb(); HrSriClientSbbLocalObject ret = (HrSriClientSbbLocalObject) relation.get(ChildRelationExt.DEFAULT_CHILD_NAME); if (ret == null) { try { ret = (HrSriClientSbbLocalObject) relation.create(ChildRelationExt.DEFAULT_CHILD_NAME); } catch (Exception e) { if (this.logger.isSevereEnabled()) { this.logger.severe("Exception while trying to creat HrSriClientSbb child", e); } } } return ret; } /** * HrSriResultInterface * */ @Override public void onSriSuccess(CorrelationIdValue correlationIdValue, boolean sriBypass) { MAPDialogSms dlg = this.getActivity(); if (dlg == null) { this.logger.severe("Home routing: can not get MAPDialog for sending SRI positive Response"); return; } if (!sriBypass) { smscStatAggregator.updateMsgInHrSriPosReq(); StringBuilder sb = new StringBuilder(); sb.append("Home routing: positive SRI response from HLR: transaction: "); sb.append(correlationIdValue); if (this.logger.isInfoEnabled()) this.logger.info(sb.toString()); } // storing correlationId into a cache try { SmsSetCache.getInstance().putCorrelationIdCacheElement(correlationIdValue, smscPropertiesManagement.getCorrelationIdLiveTime()); } catch (Exception e1) { if (dlg != null) { dlg.release(); } String reason = "Home routing: Exception when ImsiCacheElement : " + e1.toString(); this.logger.severe(reason, e1); return; } // sending positive SRI response try { String smscAddressForCountryCode = this.getSmscAddressForCountryCode(); ISDNAddressString networkNodeNumber; if (smscAddressForCountryCode != null) { networkNodeNumber = this.mapParameterFactory.createISDNAddressString(AddressNature.international_number, NumberingPlan.ISDN, smscAddressForCountryCode); } else { networkNodeNumber = getNetworkNodeNumber(correlationIdValue.getNetworkId()); } LocationInfoWithLMSI li = this.mapParameterFactory.createLocationInfoWithLMSI(networkNodeNumber, null, null, false, null); this.doSendResponse(correlationIdValue, dlg, correlationIdValue.getCorrelationID(), li); } catch (MAPException e) { if (dlg != null) { dlg.release(); } String reason = "Home routing: MAPException when sending SRI positive Response : " + e.toString(); this.logger.severe(reason, e); } } private void doSendResponse(CorrelationIdValue correlationIdValue, MAPDialogSms dlg, String imsiValue, LocationInfoWithLMSI li) throws MAPException { long invokeId = this.getInvokeId(); IMSI imsi = this.mapParameterFactory.createIMSI(imsiValue); MWStatus mwStatus = correlationIdValue.getMwStatus(); Boolean mwdSet = null; if (dlg.getApplicationContext().getApplicationContextVersion() == MAPApplicationContextVersion.version1) { if (mwStatus != null) { if (mwStatus.getMnrfSet()) mwdSet = true; mwStatus = null; } } dlg.addSendRoutingInfoForSMResponse(invokeId, imsi, li, null, mwdSet); InformServiceCentreRequest isc = correlationIdValue.getInformServiceCentreRequest(); if (mwStatus != null && isc != null) { dlg.addInformServiceCentreRequest(isc.getStoredMSISDN(), isc.getMwStatus(), null, isc.getAbsentSubscriberDiagnosticSM(), isc.getAdditionalAbsentSubscriberDiagnosticSM()); } dlg.close(false); } @Override public void onSriHrByPass(CorrelationIdValue correlationIdValue) { MAPDialogSms dlg = this.getActivity(); if (dlg == null) { this.logger.severe("Home routing: can not get MAPDialog for sending SRI hrByPass Response"); return; } smscStatAggregator.updateMsgInHrSriHrByPass(); StringBuilder sb = new StringBuilder(); sb.append("Home routing: bypassing of Home routing: procedure: transaction: "); sb.append(correlationIdValue); if (this.logger.isInfoEnabled()) this.logger.info(sb.toString()); // sending original SRI response try { SendRoutingInfoForSMResponse sendRoutingInfoForSMResponse = correlationIdValue.getSendRoutingInfoForSMResponse(); this.doSendResponse(correlationIdValue, dlg, sendRoutingInfoForSMResponse.getIMSI().getData(), sendRoutingInfoForSMResponse.getLocationInfoWithLMSI()); } catch (MAPException e) { if (dlg != null) { dlg.release(); } String reason = "Home routing: MAPException when sending SRI bypassing of Home routing: " + e.toString(); this.logger.severe(reason, e); } } @Override public void onSriFailure(CorrelationIdValue correlationIdValue, MAPErrorMessage errorResponse, String cause) { MAPDialogSms dlg = this.getActivity(); if (dlg == null) { this.logger.severe("Home routing: can not get MAPDialog for sending SRI negative Response"); return; } smscStatAggregator.updateMsgInHrSriNegReq(); StringBuilder sb = new StringBuilder(); sb.append("Home routing: negative SRI response from HLR: transaction: "); sb.append(correlationIdValue); sb.append(",\n cause="); sb.append(cause); if (this.logger.isInfoEnabled()) this.logger.info(sb.toString()); // sending negative SRI response try { // processing of error response if (errorResponse == null) { // no errorResponse obtained - we need to create SysteFailure errorResponse = this.mapErrorMessageFactory.createMAPErrorMessageSystemFailure(dlg.getApplicationContext().getApplicationContextVersion() .getVersion(), NetworkResource.hlr, null, null); } else { // we have errorResponse from HLR // TODO: we need to update values depending on MAP protocol version // not all versions support all messages } long invokeId = this.getInvokeId(); dlg.sendErrorComponent(invokeId, errorResponse); dlg.close(false); } catch (MAPException e) { if (dlg != null) { dlg.release(); } String reason = "Home routing: MAPException when sending SRI negative Response: " + e.toString(); this.logger.severe(reason, e); } } private MAPDialogSms getActivity() { for (ActivityContextInterface aci : this.sbbContext.getActivities()) { Object act = aci.getActivity(); if (act instanceof MAPDialogSms) { MAPDialogSms dlg = (MAPDialogSms) act; return dlg; } } return null; } }