/* * 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.loadService; import org.apache.log4j.Logger; 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.MAPDialog; import org.mobicents.protocols.ss7.map.api.MAPDialogListener; import org.mobicents.protocols.ss7.map.api.MAPException; import org.mobicents.protocols.ss7.map.api.MAPMessage; import org.mobicents.protocols.ss7.map.api.MAPProvider; import org.mobicents.protocols.ss7.map.api.MAPStack; import org.mobicents.protocols.ss7.map.api.datacoding.CBSDataCodingScheme; import org.mobicents.protocols.ss7.map.api.dialog.MAPAbortProviderReason; import org.mobicents.protocols.ss7.map.api.dialog.MAPAbortSource; import org.mobicents.protocols.ss7.map.api.dialog.MAPNoticeProblemDiagnostic; import org.mobicents.protocols.ss7.map.api.dialog.MAPRefuseReason; import org.mobicents.protocols.ss7.map.api.dialog.MAPUserAbortChoice; 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.primitives.MAPExtensionContainer; import org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan; import org.mobicents.protocols.ss7.map.api.primitives.USSDString; import org.mobicents.protocols.ss7.map.api.service.supplementary.ActivateSSRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.ActivateSSResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.DeactivateSSRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.DeactivateSSResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.EraseSSRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.EraseSSResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.GetPasswordRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.GetPasswordResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.InterrogateSSRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.InterrogateSSResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.MAPDialogSupplementary; import org.mobicents.protocols.ss7.map.api.service.supplementary.MAPServiceSupplementaryListener; import org.mobicents.protocols.ss7.map.api.service.supplementary.ProcessUnstructuredSSRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.ProcessUnstructuredSSResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.RegisterPasswordRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.RegisterPasswordResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.RegisterSSRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.RegisterSSResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.UnstructuredSSNotifyRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.UnstructuredSSNotifyResponse; import org.mobicents.protocols.ss7.map.api.service.supplementary.UnstructuredSSRequest; import org.mobicents.protocols.ss7.map.api.service.supplementary.UnstructuredSSResponse; import org.mobicents.protocols.ss7.map.datacoding.CBSDataCodingSchemeImpl; import org.mobicents.protocols.ss7.sccp.NetworkIdState; import org.mobicents.protocols.ss7.sccp.impl.parameter.SccpAddressImpl; import org.mobicents.protocols.ss7.sccp.parameter.SccpAddress; import org.mobicents.protocols.ss7.tcap.asn.ApplicationContextName; import org.mobicents.protocols.ss7.tcap.asn.comp.Problem; import com.google.common.util.concurrent.RateLimiter; /** * @author sergey vetyutnev * */ public class MapServiceUssdClient implements MAPDialogListener, MAPServiceSupplementaryListener { private MAPStack mapStack; private MAPProvider mapProvider; protected final Logger logger; private int delayBeforeLoad = 60; private int numberOfDialogs = 10000; private int maxConcurrentDialogs = 15; private int endCount = -100; volatile long start = 0L; volatile long prev = 0L; private RateLimiter rateLimiterObj = null; private boolean stopped = false; protected static int CLIENT_SPC = 1; protected static int SERVER_SPC = 2; protected static int SSN = 8; protected SccpAddress SCCP_CLIENT_ADDRESS; protected SccpAddress SCCP_SERVER_ADDRESS; public MapServiceUssdClient(MAPStack mapStack) { this.mapStack = mapStack; this.logger = Logger.getLogger(MapServiceUssdClient.class.getCanonicalName()); } public void start() throws Exception { this.logger.info("Starting MapServerUssdClient ..."); this.mapProvider = this.mapStack.getMAPProvider(); this.mapProvider.addMAPDialogListener(this); this.mapProvider.getMAPServiceSupplementary().addMAPServiceListener(this); this.mapProvider.getMAPServiceSupplementary().acivate(); this.rateLimiterObj = RateLimiter.create(getMaxConcurrentDialogs()); // rate SCCP_CLIENT_ADDRESS = new SccpAddressImpl(RoutingIndicator.ROUTING_BASED_ON_DPC_AND_SSN, null, CLIENT_SPC, SSN); SCCP_SERVER_ADDRESS = new SccpAddressImpl(RoutingIndicator.ROUTING_BASED_ON_DPC_AND_SSN, null, SERVER_SPC, SSN); Thread mainThread = new Thread(new MapServerUssdClient_StartClass()); mainThread.start(); this.logger.info("Started MapServerUssdClient ..."); } public void stop() { this.logger.info("Stopping MapServerUssdClient ..."); stopped = true; this.logger.info("Stopped MapServerUssdClient ..."); } private void execute() { try { // delay before starting of work Thread.sleep(1000 * getDelayBeforeLoad()); while (endCount < getNumberOfDialogs() && !stopped) { if (endCount < 0) { start = System.currentTimeMillis(); prev = start; // logger.warn("StartTime = " + client.start); } initiateUSSD(); } } catch (Exception e) { logger.error("General MapServerUssdClient executing Exception: " + e.getMessage(), e); } } private void initiateUSSD() throws MAPException { NetworkIdState networkIdState = this.mapStack.getMAPProvider().getNetworkIdState(0); int executorCongestionLevel = this.mapStack.getMAPProvider().getExecutorCongestionLevel(); if (!(networkIdState == null || networkIdState.isAvailavle() && networkIdState.getCongLevel() <= 0 && executorCongestionLevel <= 0)) { // congestion or unavailable logger.warn("**** Outgoing congestion control: MAP load test client: networkIdState=" + networkIdState + ", executorCongestionLevel=" + executorCongestionLevel); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.rateLimiterObj.acquire(); // System.out.println("initiateUSSD"); // First create Dialog AddressString origRef = this.mapProvider.getMAPParameterFactory().createAddressString( AddressNature.international_number, NumberingPlan.ISDN, "12345"); AddressString destRef = this.mapProvider.getMAPParameterFactory().createAddressString( AddressNature.international_number, NumberingPlan.ISDN, "67890"); MAPDialogSupplementary mapDialog = this.mapProvider.getMAPServiceSupplementary().createNewDialog( MAPApplicationContext.getInstance(MAPApplicationContextName.networkUnstructuredSsContext, MAPApplicationContextVersion.version2), SCCP_CLIENT_ADDRESS, origRef, SCCP_SERVER_ADDRESS, destRef); CBSDataCodingScheme ussdDataCodingScheme = new CBSDataCodingSchemeImpl(0x0f); // USSD String: *125*+31628839999# // The Charset is null, here we let system use default Charset (UTF-7 as // explained in GSM 03.38. However if MAP User wants, it can set its own // impl of Charset USSDString ussdString = this.mapProvider.getMAPParameterFactory().createUSSDString("*125*+31628839999#", null, null); ISDNAddressString msisdn = this.mapProvider.getMAPParameterFactory().createISDNAddressString( AddressNature.international_number, NumberingPlan.ISDN, "31628838002"); mapDialog.addProcessUnstructuredSSRequest(ussdDataCodingScheme, ussdString, null, msisdn); // This will initiate the TC-BEGIN with INVOKE component mapDialog.send(); } private class MapServerUssdClient_StartClass implements Runnable { @Override public void run() { execute(); } } @Override public void onErrorComponent(MAPDialog mapDialog, Long invokeId, MAPErrorMessage mapErrorMessage) { logger.error(String.format("onErrorComponent for Dialog=%d and invokeId=%d MAPErrorMessage=%s", mapDialog.getLocalDialogId(), invokeId, mapErrorMessage)); } @Override public void onRejectComponent(MAPDialog mapDialog, Long invokeId, Problem problem, boolean isLocalOriginated) { logger.error(String.format("onRejectComponent for Dialog=%d and invokeId=%d Problem=%s isLocalOriginated=%s", mapDialog.getLocalDialogId(), invokeId, problem, isLocalOriginated)); } @Override public void onInvokeTimeout(MAPDialog mapDialog, Long invokeId) { logger.error(String.format("onInvokeTimeout for Dialog=%d and invokeId=%d", mapDialog.getLocalDialogId(), invokeId)); } @Override public void onMAPMessage(MAPMessage mapMessage) { // TODO Auto-generated method stub } @Override public void onRegisterSSRequest(RegisterSSRequest request) { // TODO Auto-generated method stub } @Override public void onRegisterSSResponse(RegisterSSResponse response) { // TODO Auto-generated method stub } @Override public void onEraseSSRequest(EraseSSRequest request) { // TODO Auto-generated method stub } @Override public void onEraseSSResponse(EraseSSResponse response) { // TODO Auto-generated method stub } @Override public void onActivateSSRequest(ActivateSSRequest request) { // TODO Auto-generated method stub } @Override public void onActivateSSResponse(ActivateSSResponse response) { // TODO Auto-generated method stub } @Override public void onDeactivateSSRequest(DeactivateSSRequest request) { // TODO Auto-generated method stub } @Override public void onDeactivateSSResponse(DeactivateSSResponse response) { // TODO Auto-generated method stub } @Override public void onInterrogateSSRequest(InterrogateSSRequest request) { // TODO Auto-generated method stub } @Override public void onInterrogateSSResponse(InterrogateSSResponse response) { // TODO Auto-generated method stub } @Override public void onGetPasswordRequest(GetPasswordRequest request) { // TODO Auto-generated method stub } @Override public void onGetPasswordResponse(GetPasswordResponse response) { // TODO Auto-generated method stub } @Override public void onRegisterPasswordRequest(RegisterPasswordRequest request) { // TODO Auto-generated method stub } @Override public void onRegisterPasswordResponse(RegisterPasswordResponse response) { // TODO Auto-generated method stub } @Override public void onProcessUnstructuredSSRequest(ProcessUnstructuredSSRequest procUnstrReqInd) { // This error condition. Client should never receive the // ProcessUnstructuredSSRequestIndication logger.error(String.format("onProcessUnstructuredSSRequestIndication for Dialog=%d and invokeId=%d", procUnstrReqInd .getMAPDialog().getLocalDialogId(), procUnstrReqInd.getInvokeId())); } @Override public void onProcessUnstructuredSSResponse(ProcessUnstructuredSSResponse procUnstrResInd) { if (logger.isDebugEnabled()) { logger.debug(String.format("Rx ProcessUnstructuredSSResponseIndication. USSD String=%s", procUnstrResInd.getUSSDString())); } } @Override public void onUnstructuredSSRequest(UnstructuredSSRequest unstrReqInd) { if (logger.isDebugEnabled()) { logger.debug(String.format("Rx UnstructuredSSRequestIndication. USSD String=%s ", unstrReqInd.getUSSDString())); } MAPDialogSupplementary mapDialog = unstrReqInd.getMAPDialog(); try { CBSDataCodingScheme ussdDataCodingScheme = new CBSDataCodingSchemeImpl(0x0f); USSDString ussdString = this.mapProvider.getMAPParameterFactory().createUSSDString("1", null, null); AddressString msisdn = this.mapProvider.getMAPParameterFactory().createAddressString( AddressNature.international_number, NumberingPlan.ISDN, "31628838002"); mapDialog.addUnstructuredSSResponse(unstrReqInd.getInvokeId(), ussdDataCodingScheme, ussdString); mapDialog.send(); } catch (MAPException e) { logger.error(String.format("Error while sending UnstructuredSSResponse for Dialog=%d", mapDialog.getLocalDialogId())); } } @Override public void onUnstructuredSSResponse(UnstructuredSSResponse unstrResInd) { // This error condition. Client should never receive the // UnstructuredSSResponseIndication logger.error(String.format("onUnstructuredSSResponseIndication for Dialog=%d and invokeId=%d", unstrResInd .getMAPDialog().getLocalDialogId(), unstrResInd.getInvokeId())); } @Override public void onUnstructuredSSNotifyRequest(UnstructuredSSNotifyRequest unstrNotifyInd) { // This error condition. Client should never receive the // UnstructuredSSNotifyRequestIndication logger.error(String.format("onUnstructuredSSNotifyRequestIndication for Dialog=%d and invokeId=%d", unstrNotifyInd .getMAPDialog().getLocalDialogId(), unstrNotifyInd.getInvokeId())); } @Override public void onUnstructuredSSNotifyResponse(UnstructuredSSNotifyResponse unstrNotifyInd) { // TODO Auto-generated method stub } @Override public void onDialogDelimiter(MAPDialog mapDialog) { if (logger.isDebugEnabled()) { logger.debug(String.format("onDialogDelimiter for DialogId=%d", mapDialog.getLocalDialogId())); } } @Override public void onDialogRequest(MAPDialog mapDialog, AddressString destReference, AddressString origReference, MAPExtensionContainer extensionContainer) { if (logger.isDebugEnabled()) { logger.debug(String.format( "onDialogRequest for DialogId=%d DestinationReference=%s OriginReference=%s MAPExtensionContainer=%s", mapDialog.getLocalDialogId(), destReference, origReference, extensionContainer)); } } @Override public void onDialogRequestEricsson(MAPDialog mapDialog, AddressString destReference, AddressString origReference, AddressString eriImsi, AddressString eriVlrNo) { if (logger.isDebugEnabled()) { logger.debug(String.format("onDialogRequest for DialogId=%d DestinationReference=%s OriginReference=%s ", mapDialog.getLocalDialogId(), destReference, origReference)); } } @Override public void onDialogAccept(MAPDialog mapDialog, MAPExtensionContainer extensionContainer) { if (logger.isDebugEnabled()) { logger.debug(String.format("onDialogAccept for DialogId=%d MAPExtensionContainer=%s", mapDialog.getLocalDialogId(), extensionContainer)); } } @Override public void onDialogReject(MAPDialog mapDialog, MAPRefuseReason refuseReason, ApplicationContextName alternativeApplicationContext, MAPExtensionContainer extensionContainer) { logger.error(String.format( "onDialogReject for DialogId=%d MAPRefuseReason=%s ApplicationContextName=%s MAPExtensionContainer=%s", mapDialog.getLocalDialogId(), refuseReason, alternativeApplicationContext, extensionContainer)); } @Override public void onDialogUserAbort(MAPDialog mapDialog, MAPUserAbortChoice userReason, MAPExtensionContainer extensionContainer) { logger.error(String.format("onDialogUserAbort for DialogId=%d MAPUserAbortChoice=%s MAPExtensionContainer=%s", mapDialog.getLocalDialogId(), userReason, extensionContainer)); } @Override public void onDialogProviderAbort(MAPDialog mapDialog, MAPAbortProviderReason abortProviderReason, MAPAbortSource abortSource, MAPExtensionContainer extensionContainer) { logger.error(String.format( "onDialogProviderAbort for DialogId=%d MAPAbortProviderReason=%s MAPAbortSource=%s MAPExtensionContainer=%s", mapDialog.getLocalDialogId(), abortProviderReason, abortSource, extensionContainer)); } @Override public void onDialogClose(MAPDialog mapDialog) { if (logger.isDebugEnabled()) { logger.debug(String.format("DialogClose for Dialog=%d", mapDialog.getLocalDialogId())); } } @Override public void onDialogNotice(MAPDialog mapDialog, MAPNoticeProblemDiagnostic noticeProblemDiagnostic) { logger.error(String.format("onDialogNotice for DialogId=%d MAPNoticeProblemDiagnostic=%s ", mapDialog.getLocalDialogId(), noticeProblemDiagnostic)); } @Override public void onDialogRelease(MAPDialog mapDialog) { if (logger.isDebugEnabled()) { logger.debug(String.format("onDialogResease for DialogId=%d", mapDialog.getLocalDialogId())); } this.endCount++; if (this.endCount < getNumberOfDialogs()) { if ((this.endCount % 2000) == 0) { long current = System.currentTimeMillis(); float sec = (float) (current - prev) / 1000f; prev = current; logger.warn("Completed 2000 Dialogs, dlg per a sec: " + (float) (2000 / sec)); } } else { if (this.endCount == getNumberOfDialogs()) { long current = System.currentTimeMillis(); logger.warn("Start Time = " + start); logger.warn("Current Time = " + current); float sec = (float) (current - start) / 1000f; logger.warn("Total time in sec = " + sec); logger.warn("Throughput = " + (float) (getNumberOfDialogs() / sec)); } } } @Override public void onDialogTimeout(MAPDialog mapDialog) { logger.error(String.format("onDialogTimeout for DialogId=%d", mapDialog.getLocalDialogId())); } public int getDelayBeforeLoad() { return delayBeforeLoad; } public void setDelayBeforeLoad(int delayBeforeLoad) { this.delayBeforeLoad = delayBeforeLoad; } public int getNumberOfDialogs() { return numberOfDialogs; } public void setNumberOfDialogs(int numberOfDialogs) { this.numberOfDialogs = numberOfDialogs; } public int getMaxConcurrentDialogs() { return maxConcurrentDialogs; } public void setMaxConcurrentDialogs(int maxConcurrentDialogs) { this.maxConcurrentDialogs = maxConcurrentDialogs; } }