/*
* TeleStax, Open Source Cloud Communications Copyright 2012.
* 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.protocols.ss7.map.service.callhandling;
import org.apache.log4j.Logger;
import org.mobicents.protocols.asn.AsnInputStream;
import org.mobicents.protocols.asn.Tag;
import org.mobicents.protocols.ss7.map.MAPDialogImpl;
import org.mobicents.protocols.ss7.map.MAPProviderImpl;
import org.mobicents.protocols.ss7.map.MAPServiceBaseImpl;
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.MAPDialog;
import org.mobicents.protocols.ss7.map.api.MAPException;
import org.mobicents.protocols.ss7.map.api.MAPOperationCode;
import org.mobicents.protocols.ss7.map.api.MAPParsingComponentException;
import org.mobicents.protocols.ss7.map.api.MAPParsingComponentExceptionReason;
import org.mobicents.protocols.ss7.map.api.MAPServiceListener;
import org.mobicents.protocols.ss7.map.api.dialog.ServingCheckData;
import org.mobicents.protocols.ss7.map.api.dialog.ServingCheckResult;
import org.mobicents.protocols.ss7.map.api.primitives.AddressString;
import org.mobicents.protocols.ss7.map.api.service.callhandling.MAPDialogCallHandling;
import org.mobicents.protocols.ss7.map.api.service.callhandling.MAPServiceCallHandling;
import org.mobicents.protocols.ss7.map.api.service.callhandling.MAPServiceCallHandlingListener;
import org.mobicents.protocols.ss7.map.dialog.ServingCheckDataImpl;
import org.mobicents.protocols.ss7.sccp.parameter.SccpAddress;
import org.mobicents.protocols.ss7.tcap.api.tc.dialog.Dialog;
import org.mobicents.protocols.ss7.tcap.asn.comp.ComponentType;
import org.mobicents.protocols.ss7.tcap.asn.comp.Invoke;
import org.mobicents.protocols.ss7.tcap.asn.comp.OperationCode;
import org.mobicents.protocols.ss7.tcap.asn.comp.Parameter;
/*
*
* @author cristian veliscu
* @author eva ogallar
*/
public class MAPServiceCallHandlingImpl extends MAPServiceBaseImpl implements MAPServiceCallHandling {
private static final Logger loger = Logger.getLogger(MAPServiceCallHandlingImpl.class);
// Include these constants in MAPApplicationContextName and MAPOperationCode
// sendRoutingInfo_Request: add constant to MAPMessageType
// sendRoutingInfo_Response: add constant to MAPMessageType
protected static final int version = 3;
public MAPServiceCallHandlingImpl(MAPProviderImpl mapProviderImpl) {
super(mapProviderImpl);
}
@Override
public MAPDialogCallHandling createNewDialog(MAPApplicationContext appCntx, SccpAddress origAddress, AddressString origReference, SccpAddress destAddress,
AddressString destReference) throws MAPException {
return this.createNewDialog(appCntx, origAddress, origReference, destAddress, destReference, null);
}
@Override
public MAPDialogCallHandling createNewDialog(MAPApplicationContext appCntx, SccpAddress origAddress, AddressString origReference, SccpAddress destAddress,
AddressString destReference, Long localTrId) throws MAPException {
// We cannot create a dialog if the service is not activated
if (!this.isActivated())
throw new MAPException(
"Cannot create MAPDialogRoutingInformation because MAPServiceRoutingInformation is not activated");
Dialog tcapDialog = this.createNewTCAPDialog(origAddress, destAddress, localTrId);
MAPDialogCallHandlingImpl dialog = new MAPDialogCallHandlingImpl(appCntx, tcapDialog, this.mapProviderImpl, this,
origReference, destReference);
this.putMAPDialogIntoCollection(dialog);
return dialog;
}
@Override
protected MAPDialogImpl createNewDialogIncoming(MAPApplicationContext appCntx, Dialog tcapDialog) {
return new MAPDialogCallHandlingImpl(appCntx, tcapDialog, this.mapProviderImpl, this, null, null);
}
@Override
public void addMAPServiceListener(MAPServiceCallHandlingListener mapServiceListener) {
super.addMAPServiceListener(mapServiceListener);
}
@Override
public void removeMAPServiceListener(MAPServiceCallHandlingListener mapServiceListener) {
super.removeMAPServiceListener(mapServiceListener);
}
@Override
public ServingCheckData isServingService(MAPApplicationContext dialogApplicationContext) {
MAPApplicationContextName ctx = dialogApplicationContext.getApplicationContextName();
int vers = dialogApplicationContext.getApplicationContextVersion().getVersion();
switch (ctx) {
case locationInfoRetrievalContext:
if (vers >= 1 && vers <= 3) {
return new ServingCheckDataImpl(ServingCheckResult.AC_Serving);
} else {
return new ServingCheckDataImpl(ServingCheckResult.AC_VersionIncorrect);
}
case roamingNumberEnquiryContext:
if (vers >= 1 && vers <= 3) {
return new ServingCheckDataImpl(ServingCheckResult.AC_Serving);
} else {
return new ServingCheckDataImpl(ServingCheckResult.AC_VersionIncorrect);
}
case ServiceTerminationContext:
if (vers == 3) {
return new ServingCheckDataImpl(ServingCheckResult.AC_Serving);
} else {
return new ServingCheckDataImpl(ServingCheckResult.AC_VersionIncorrect);
}
}
return new ServingCheckDataImpl(ServingCheckResult.AC_NotServing);
}
@Override
public MAPApplicationContext getMAPv1ApplicationContext(int operationCode, Invoke invoke) {
switch (operationCode) {
case MAPOperationCode.sendRoutingInfo:
return MAPApplicationContext.getInstance(MAPApplicationContextName.locationInfoRetrievalContext,
MAPApplicationContextVersion.version1);
case MAPOperationCode.provideRoamingNumber:
return MAPApplicationContext.getInstance(MAPApplicationContextName.roamingNumberEnquiryContext,
MAPApplicationContextVersion.version1);
}
return null;
}
@Override
public void processComponent(ComponentType compType, OperationCode oc, Parameter parameter, MAPDialog mapDialog,
Long invokeId, Long linkedId, Invoke linkedInvoke) throws MAPParsingComponentException {
// if (compType == ComponentType.Invoke && this.mapProviderImpl.isCongested()) {
// // we reject all supplementary services when congestion
// return;
// }
MAPDialogCallHandlingImpl mapDialogImpl = (MAPDialogCallHandlingImpl) mapDialog;
Long ocValue = oc.getLocalOperationCode();
if (ocValue == null)
new MAPParsingComponentException("", MAPParsingComponentExceptionReason.UnrecognizedOperation);
MAPApplicationContextName acn = mapDialog.getApplicationContext().getApplicationContextName();
int vers = mapDialog.getApplicationContext().getApplicationContextVersion().getVersion();
int ocValueInt = (int) (long) ocValue;
switch (ocValueInt) {
case MAPOperationCode.sendRoutingInfo:
if (compType == ComponentType.Invoke)
this.sendRoutingInformationRequest(parameter, mapDialogImpl, invokeId);
else if (compType == ComponentType.ReturnResult || compType == ComponentType.ReturnResultLast)
this.sendRoutingInformationResponse(parameter, mapDialogImpl, invokeId,
compType == ComponentType.ReturnResult);
break;
case MAPOperationCode.provideRoamingNumber:
if (compType == ComponentType.Invoke)
this.provideRoamingNumberRequest(parameter, mapDialogImpl, invokeId);
else if (compType == ComponentType.ReturnResult || compType == ComponentType.ReturnResultLast)
this.provideRoamingNumberResponse(parameter, mapDialogImpl, invokeId,
compType == ComponentType.ReturnResult);
break;
case MAPOperationCode.istCommand:
if (compType == ComponentType.Invoke)
this.istCommandRequest(parameter, mapDialogImpl, invokeId);
else if (compType == ComponentType.ReturnResult || compType == ComponentType.ReturnResultLast)
this.istCommandResponse(parameter, mapDialogImpl, invokeId, compType == ComponentType.ReturnResult);
break;
default:
throw new MAPParsingComponentException("MAPServiceCallHandling: unknown incoming operation code: " + ocValueInt,
MAPParsingComponentExceptionReason.UnrecognizedOperation);
}
}
private void sendRoutingInformationRequest(Parameter parameter, MAPDialogCallHandlingImpl mapDialogImpl, Long invokeId)
throws MAPParsingComponentException {
long version = mapDialogImpl.getApplicationContext().getApplicationContextVersion().getVersion();
SendRoutingInformationRequestImpl ind = new SendRoutingInformationRequestImpl(version);
if (parameter == null)
throw new MAPParsingComponentException(
"Error while decoding SendRoutingInformationRequestIndication: Parameter is mandatory but not found",
MAPParsingComponentExceptionReason.MistypedParameter);
// No matter what MAP version V1,V2,V3: tag=Tag.SEQUENCE and tagClass=Tag.CLASS_UNIVERSAL
if (parameter.getTag() != Tag.SEQUENCE || parameter.getTagClass() != Tag.CLASS_UNIVERSAL || parameter.isPrimitive())
throw new MAPParsingComponentException(
"Error while decoding SendRoutingInformationRequestIndication: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
byte[] buf = parameter.getData();
AsnInputStream ais = new AsnInputStream(buf);
ind.decodeData(ais, buf.length);
ind.setInvokeId(invokeId);
ind.setMAPDialog(mapDialogImpl);
for (MAPServiceListener serLis : this.serviceListeners) {
try {
serLis.onMAPMessage(ind);
((MAPServiceCallHandlingListener) serLis).onSendRoutingInformationRequest(ind);
} catch (Exception e) {
loger.error("Error processing SendRoutingInformationRequestIndication: " + e.getMessage(), e);
}
}
}
private void sendRoutingInformationResponse(Parameter parameter, MAPDialogCallHandlingImpl mapDialogImpl, Long invokeId,
boolean returnResultNotLast) throws MAPParsingComponentException {
long version = mapDialogImpl.getApplicationContext().getApplicationContextVersion().getVersion();
SendRoutingInformationResponseImpl ind = new SendRoutingInformationResponseImpl(version);
if (parameter == null)
throw new MAPParsingComponentException(
"Error while decoding SendRoutingInformationResponseIndication: Parameter is mandatory but not found",
MAPParsingComponentExceptionReason.MistypedParameter);
if (version >= 3) { // tag=3 and tagClass=Tag.CLASS_CONTEXT_SPECIFIC
if (parameter.getTag() != SendRoutingInformationResponseImpl.TAG_sendRoutingInfoRes
|| parameter.getTagClass() != Tag.CLASS_CONTEXT_SPECIFIC || parameter.isPrimitive())
throw new MAPParsingComponentException(
"Error while decoding SendRoutingInformationResponseIndication: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
} else {
if (parameter.getTag() != Tag.SEQUENCE || parameter.getTagClass() != Tag.CLASS_UNIVERSAL || parameter.isPrimitive())
throw new MAPParsingComponentException(
"Error while decoding SendRoutingInformationResponseIndication: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
}
byte[] buf = parameter.getData();
AsnInputStream ais = new AsnInputStream(buf);
ind.decodeData(ais, buf.length);
ind.setInvokeId(invokeId);
ind.setMAPDialog(mapDialogImpl);
ind.setReturnResultNotLast(returnResultNotLast);
for (MAPServiceListener serLis : this.serviceListeners) {
try {
serLis.onMAPMessage(ind);
((MAPServiceCallHandlingListener) serLis).onSendRoutingInformationResponse(ind);
} catch (Exception e) {
loger.error("Error processing SendRoutingInformationResponseIndication: " + e.getMessage(), e);
}
}
}
private void provideRoamingNumberRequest(Parameter parameter, MAPDialogCallHandlingImpl mapDialogImpl, Long invokeId)
throws MAPParsingComponentException {
long version = mapDialogImpl.getApplicationContext().getApplicationContextVersion().getVersion();
ProvideRoamingNumberRequestImpl ind = new ProvideRoamingNumberRequestImpl(version);
if (parameter == null)
throw new MAPParsingComponentException(
"Error while decoding ProvideRoamingNumberRequestIndication: Parameter is mandatory but not found",
MAPParsingComponentExceptionReason.MistypedParameter);
// No matter what MAP version V1,V2,V3: tag=Tag.SEQUENCE and tagClass=Tag.CLASS_UNIVERSAL
if (parameter.getTag() != Tag.SEQUENCE || parameter.getTagClass() != Tag.CLASS_UNIVERSAL || parameter.isPrimitive())
throw new MAPParsingComponentException(
"Error while decoding ProvideRoamingNumberRequestIndication: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
byte[] buf = parameter.getData();
AsnInputStream ais = new AsnInputStream(buf);
ind.decodeData(ais, buf.length);
ind.setInvokeId(invokeId);
ind.setMAPDialog(mapDialogImpl);
for (MAPServiceListener serLis : this.serviceListeners) {
try {
serLis.onMAPMessage(ind);
((MAPServiceCallHandlingListener) serLis).onProvideRoamingNumberRequest(ind);
} catch (Exception e) {
loger.error("Error processing ProvideRoamingNumberRequestIndication: " + e.getMessage(), e);
}
}
}
private void provideRoamingNumberResponse(Parameter parameter, MAPDialogCallHandlingImpl mapDialogImpl, Long invokeId,
boolean returnResultNotLast) throws MAPParsingComponentException {
long version = mapDialogImpl.getApplicationContext().getApplicationContextVersion().getVersion();
ProvideRoamingNumberResponseImpl ind = new ProvideRoamingNumberResponseImpl(version);
if (parameter == null)
throw new MAPParsingComponentException(
"Error while decoding ProvideRoamingNumberResponseIndication: Parameter is mandatory but not found",
MAPParsingComponentExceptionReason.MistypedParameter);
if (version >= 3) {
if (parameter.getTag() != Tag.SEQUENCE || parameter.getTagClass() != Tag.CLASS_UNIVERSAL || parameter.isPrimitive())
throw new MAPParsingComponentException(
"Error while decoding ProvideRoamingNumberResponseIndication: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
} else {
if (parameter.getTag() != Tag.STRING_OCTET || parameter.getTagClass() != Tag.CLASS_UNIVERSAL
|| !parameter.isPrimitive())
throw new MAPParsingComponentException(
"Error while decoding ProvideRoamingNumberResponseIndication: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
}
byte[] buf = parameter.getData();
AsnInputStream ais = new AsnInputStream(buf, parameter.getTagClass(), parameter.isPrimitive(), parameter.getTag());
ind.decodeData(ais, buf.length);
ind.setInvokeId(invokeId);
ind.setMAPDialog(mapDialogImpl);
ind.setReturnResultNotLast(returnResultNotLast);
for (MAPServiceListener serLis : this.serviceListeners) {
try {
serLis.onMAPMessage(ind);
((MAPServiceCallHandlingListener) serLis).onProvideRoamingNumberResponse(ind);
} catch (Exception e) {
loger.error("Error processing ProvideRoamingNumberResponseIndication: " + e.getMessage(), e);
}
}
}
private void istCommandRequest(Parameter parameter, MAPDialogCallHandlingImpl mapDialogImpl, Long invokeId)
throws MAPParsingComponentException {
IstCommandRequestImpl ind = new IstCommandRequestImpl();
if (parameter == null)
throw new MAPParsingComponentException(
"Error while decoding IstCommandRequest: Parameter is mandatory but not found",
MAPParsingComponentExceptionReason.MistypedParameter);
// No matter what MAP version V1,V2,V3: tag=Tag.SEQUENCE and tagClass=Tag.CLASS_UNIVERSAL
if (parameter.getTag() != Tag.SEQUENCE || parameter.getTagClass() != Tag.CLASS_UNIVERSAL || parameter.isPrimitive())
throw new MAPParsingComponentException(
"Error while decoding IstCommandRequest: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
byte[] buf = parameter.getData();
AsnInputStream ais = new AsnInputStream(buf);
ind.decodeData(ais, buf.length);
ind.setInvokeId(invokeId);
ind.setMAPDialog(mapDialogImpl);
for (MAPServiceListener serLis : this.serviceListeners) {
try {
serLis.onMAPMessage(ind);
((MAPServiceCallHandlingListener) serLis).onIstCommandRequest(ind);
} catch (Exception e) {
loger.error("Error processing IstCommandRequest: " + e.getMessage(), e);
}
}
}
private void istCommandResponse(Parameter parameter, MAPDialogCallHandlingImpl mapDialogImpl, Long invokeId,
boolean returnResultNotLast) throws MAPParsingComponentException {
IstCommandResponseImpl ind = new IstCommandResponseImpl();
if (parameter != null) {
if (parameter.getTag() != Tag.SEQUENCE || parameter.getTagClass() != Tag.CLASS_UNIVERSAL || parameter.isPrimitive()) {
throw new MAPParsingComponentException(
"Error while decoding IstCommandResponse: Bad tag or tagClass or parameter is primitive, received tag="
+ parameter.getTag(), MAPParsingComponentExceptionReason.MistypedParameter);
}
byte[] buf = parameter.getData();
AsnInputStream ais = new AsnInputStream(buf, parameter.getTagClass(), parameter.isPrimitive(), parameter.getTag());
ind.decodeData(ais, buf.length);
}
ind.setInvokeId(invokeId);
ind.setMAPDialog(mapDialogImpl);
ind.setReturnResultNotLast(returnResultNotLast);
for (MAPServiceListener serLis : this.serviceListeners) {
try {
serLis.onMAPMessage(ind);
((MAPServiceCallHandlingListener) serLis).onIstCommandResponse(ind);
} catch (Exception e) {
loger.error("Error processing IstCommandResponse: " + e.getMessage(), e);
}
}
}
}