
org.restcomm.protocols.ss7.sccp.impl.SccpManagement Maven / Gradle / Ivy
The newest version!
/*
* 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.restcomm.protocols.ss7.sccp.impl;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javolution.util.FastList;
import javolution.util.FastMap;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.restcomm.protocols.ss7.indicator.RoutingIndicator;
import org.restcomm.protocols.ss7.mtp.Mtp3StatusCause;
import org.restcomm.protocols.ss7.sccp.ConcernedSignalingPointCode;
import org.restcomm.protocols.ss7.sccp.Mtp3ServiceAccessPoint;
import org.restcomm.protocols.ss7.sccp.RemoteSccpStatus;
import org.restcomm.protocols.ss7.sccp.RemoteSubSystem;
import org.restcomm.protocols.ss7.sccp.SccpListener;
import org.restcomm.protocols.ss7.sccp.SccpManagementEventListener;
import org.restcomm.protocols.ss7.sccp.SccpProtocolVersion;
import org.restcomm.protocols.ss7.sccp.impl.message.SccpDataMessageImpl;
import org.restcomm.protocols.ss7.sccp.impl.message.SccpMessageImpl;
import org.restcomm.protocols.ss7.sccp.impl.parameter.SccpAddressImpl;
import org.restcomm.protocols.ss7.sccp.message.SccpDataMessage;
import org.restcomm.protocols.ss7.sccp.message.SccpMessage;
import org.restcomm.protocols.ss7.sccp.parameter.SccpAddress;
/**
* @author amit bhayani
* @author sergey vetyutnev
*
*/
public class SccpManagement {
private final Logger logger;
protected static final int MTP3_PAUSE = 3;
protected static final int MTP3_RESUME = 4;
protected static final int MTP3_STATUS = 5;
protected static final int SSA = 1;
protected static final int SSP = 2;
protected static final int SST = 3;
protected static final int SOR = 4;
protected static final int SOG = 5;
protected static final int SSC = 6;
private static final String S_SSA = "SSA";
private static final String S_SSP = "SSP";
private static final String S_SST = "SST";
private static final String S_SOR = "SOR";
private static final String S_SOG = "SOG";
private static final String S_SSC = "SSC";
private static final String S_DEFAULT = "UNIDENTIFIED";
protected static final int UNAVAILABILITY_CAUSE_UNKNOWN = 0;
protected static final int UNAVAILABILITY_CAUSE_UNEQUIPED = 1;
protected static final int UNAVAILABILITY_CAUSE_INACCESSIBLE = 2;
private static final int ALL_POINT_CODE = -1;
// private static final int SST_TIMER_DURATION_MIN = 10000;
// private static final int SST_TIMER_DURATION_MAX = 600000;
private SccpProviderImpl sccpProviderImpl;
private SccpStackImpl sccpStackImpl;
private SccpRoutingControl sccpRoutingControl;
private ScheduledExecutorService managementExecutors;
// Keeps track of how many SST are running for given DPC
private final FastMap> dpcVsSst = new FastMap>();
// Keeps the time when the last SSP (after recdMsgForProhibitedSsn()) has
// been sent
private final FastMap dpcSspSent = new FastMap();
private final String name;
public SccpManagement(String name, SccpProviderImpl sccpProviderImpl, SccpStackImpl sccpStackImpl) {
this.name = name;
this.logger = Logger.getLogger(SccpManagement.class.getCanonicalName() + "-" + this.name);
this.sccpProviderImpl = sccpProviderImpl;
this.sccpStackImpl = sccpStackImpl;
}
public SccpRoutingControl getSccpRoutingControl() {
return sccpRoutingControl;
}
public void setSccpRoutingControl(SccpRoutingControl sccpRoutingControl) {
this.sccpRoutingControl = sccpRoutingControl;
}
public ScheduledExecutorService getManagementExecutors() {
return managementExecutors;
}
public void onManagementMessage(SccpDataMessage message) {
byte[] data = message.getData();
int messgType = data[0] & 0xff;
int affectedSsn = data[1] & 0xff;
int affectedPc;
int subsystemMultiplicity;
int congestionLevel = 0;
if (this.sccpStackImpl.getSccpProtocolVersion() == SccpProtocolVersion.ANSI) {
affectedPc = (data[2] & 0xff) | ((data[3] & 0xff) << 8) | ((data[4] & 0xff) << 16);
subsystemMultiplicity = data[5] & 0xff;
if (messgType == SSC)
congestionLevel = data[6] & 0x0f;
} else {
affectedPc = (data[2] & 0xff) | ((data[3] & 0xff) << 8);
subsystemMultiplicity = data[4] & 0xff;
if (messgType == SSC)
congestionLevel = data[5] & 0x0f;
}
switch (messgType) {
case SSA:
if (logger.isInfoEnabled()) {
logger.info(String.format(
"Rx : SSA, Affected SSN=%d, Affected PC=%d, Subsystem Multiplicity Ind=%d SeqControl=%d",
affectedSsn, affectedPc, subsystemMultiplicity, message.getSls()));
}
// Stop the SST if already started
this.cancelSst(affectedPc, affectedSsn);
if (affectedSsn == 1) {
this.allowRsp(affectedPc, false, RemoteSccpStatus.AVAILABLE);
} else {
// Mark remote SSN Allowed
this.allowSsn(affectedPc, affectedSsn);
}
break;
case SSP:
if (logger.isEnabledFor(Level.WARN)) {
logger.warn(String.format(
"Rx : SSP, Affected SSN=%d, Affected PC=%d, Subsystem Multiplicity Ind=%d SeqControl=%d",
affectedSsn, affectedPc, subsystemMultiplicity, message.getSls()));
}
if (affectedSsn == 1) {
// A subsystem prohibited message with SSN = 1 is not allowed
} else {
this.prohibitSsn(affectedPc, affectedSsn);
this.startSst(affectedPc, affectedSsn);
}
break;
case SST:
if (logger.isInfoEnabled()) {
logger.info(String.format(
"Rx : SST, Affected SSN=%d, Affected PC=%d, Subsystem Multiplicity Ind=%d SeqControl=%d",
affectedSsn, affectedPc, subsystemMultiplicity, message.getSls()));
}
if (affectedSsn == 1) {
// In the case where the Subsystem-Status-Test message is
// testing the status of SCCP management (SSN = 1), if the SCCP
// at the destination node is functioning, then a Subsystem
// Allowed message with SSN = 1 is sent to SCCP management at
// the node conducting the test. If the SCCP is not functioning,
// then the MTP cannot deliver the SST message to the SCCP. A
// UPU message is returned to the SST initiating node by the
// MTP.
this.sendSSA(message, affectedSsn);
} else {
SccpListener listener = this.sccpProviderImpl.getSccpListener(affectedSsn);
if (listener != null) {
this.sendSSA(message, affectedSsn);
return;
}
if (logger.isInfoEnabled()) {
logger.info(String.format("Received SST for unavailable SSN=%d", affectedSsn));
}
}
break;
case SOR:
if (logger.isEnabledFor(Level.WARN)) {
logger.warn("Received SOR. SOR not yet implemented, dropping message");
}
break;
case SOG:
if (logger.isEnabledFor(Level.WARN)) {
logger.warn("Received SOG. SOG not yet implemented, dropping message");
}
break;
case SSC:
if (logger.isInfoEnabled()) {
logger.info(String
.format("Rx : SSC, Affected SSN=%d, Affected PC=%d, Subsystem Multiplicity Ind=%d SeqControl=%d congestionLevel=%d",
affectedSsn, affectedPc, subsystemMultiplicity, message.getSls(), congestionLevel));
}
this.onCongState(affectedPc, congestionLevel);
break;
default:
logger.error("Received SCMG with unknown MessageType.");
break;
}
}
private void sendManagementMessage(int dpc, int messageTypeCode, int affectedSsn, int subsystemMultiplicityIndicator, Integer congestionLevel) {
Mtp3ServiceAccessPoint sap = this.sccpStackImpl.router.findMtp3ServiceAccessPoint(dpc, 0);
if (sap == null) {
logger.warn(String.format("Failed sendManagementMessage : Mtp3ServiceAccessPoint has not found for dpc=%d", dpc));
return;
}
int affectedPc;
if (messageTypeCode == SST || messageTypeCode == SOG) {
affectedPc = dpc;
} else {
affectedPc = sap.getOpc();
}
SccpAddress calledAdd = new SccpAddressImpl(RoutingIndicator.ROUTING_BASED_ON_DPC_AND_SSN, null, dpc, 1);
SccpAddress callingAdd = new SccpAddressImpl(RoutingIndicator.ROUTING_BASED_ON_DPC_AND_SSN, null, affectedPc, 1);
byte[] data = null;
if(messageTypeCode == SSC)
data = createManagementMessageBody(messageTypeCode, affectedPc, affectedSsn, subsystemMultiplicityIndicator, congestionLevel);
else
data = createManagementMessageBody(messageTypeCode, affectedPc, affectedSsn, subsystemMultiplicityIndicator);
SccpDataMessageImpl msg = (SccpDataMessageImpl) sccpProviderImpl.getMessageFactory().createDataMessageClass0(calledAdd,
callingAdd, data, -1, false, null, null);
if (logger.isDebugEnabled()) {
logger.debug(String.format("Tx :SCMG Type=%d, Affected SSN=%d, AffectedPc=%d", messageTypeCode, affectedSsn,
affectedPc));
}
try {
msg.setOutgoingDpc(msg.getCalledPartyAddress().getSignalingPointCode());
this.sccpRoutingControl.sendManagementMessage(msg);
// this.sccpRoutingControl.sendMessageToMtp(msg);
} catch (Exception e) {
logger.error(String.format("Exception while trying to send SSP message=%s", msg), e);
}
}
private byte[] createManagementMessageBody(int messageTypeCode, int affectedPc, int affectedSsn,
int subsystemMultiplicityIndicator) {
return createManagementMessageBody(messageTypeCode, affectedPc, affectedSsn, subsystemMultiplicityIndicator, -1);
}
private byte[] createManagementMessageBody(int messageTypeCode, int affectedPc, int affectedSsn,
int subsystemMultiplicityIndicator, int congestionLevel) {
byte[] data;
if (this.sccpStackImpl.getSccpProtocolVersion() == SccpProtocolVersion.ANSI) {
if (congestionLevel >= 0)
data = new byte[7];
else
data = new byte[6];
} else {
if (congestionLevel >= 0)
data = new byte[6];
else
data = new byte[5];
}
data[0] = (byte) messageTypeCode;
data[1] = (byte) affectedSsn; // affected SSN
if (this.sccpStackImpl.getSccpProtocolVersion() == SccpProtocolVersion.ANSI) {
data[2] = (byte) (affectedPc & 0x000000ff);
data[3] = (byte) ((affectedPc & 0x0000ff00) >> 8);
data[4] = (byte) ((affectedPc & 0x00ff0000) >> 16);
data[5] = (byte) subsystemMultiplicityIndicator;
if (congestionLevel >= 0)
data[6] = (byte) congestionLevel;
} else {
data[2] = (byte) (affectedPc & 0x000000ff);
data[3] = (byte) ((affectedPc & 0x0000ff00) >> 8);
data[4] = (byte) subsystemMultiplicityIndicator;
if (congestionLevel >= 0)
data[5] = (byte) congestionLevel;
}
return data;
}
private void sendSSA(SccpMessage msg, int affectedSsn) {
this.sendManagementMessage(((SccpMessageImpl) msg).getIncomingOpc(), SSA, affectedSsn, 0 , null);
}
protected void broadcastChangedSsnState(int affectedSsn, boolean inService) {
this.broadcastChangedSsnState(affectedSsn, inService, ALL_POINT_CODE);
}
private void broadcastChangedSsnState(int affectedSsn, boolean inService, int concernedPointCode) {
FastMap lst = this.sccpStackImpl.sccpResource.concernedSpcs;
for (FastMap.Entry e = lst.head(), end = lst.tail(); (e = e.getNext()) != end;) {
ConcernedSignalingPointCode concernedSubSystem = e.getValue();
int dpc = concernedSubSystem.getRemoteSpc();
if (concernedPointCode == ALL_POINT_CODE || concernedPointCode == dpc) {
// Send SSA/SSP to only passed concerned point code
if (inService)
this.sendManagementMessage(dpc, SSA, affectedSsn, 0, null);
else
this.sendManagementMessage(dpc, SSP, affectedSsn, 0, null);
}
}
}
protected void recdMsgForProhibitedSsn(SccpMessage msg, int ssn) {
// we do not send new SSP's to the same DPC+SSN during the one second
// interval
int dpc = msg.getIncomingOpc();
DpcSsn key = new DpcSsn(dpc, ssn);
long now = System.currentTimeMillis();
synchronized (this.dpcSspSent) {
Long dt = this.dpcSspSent.get(key);
if (dt != null && now - dt < 1000)
return;
this.dpcSspSent.put(key, now);
}
// Send SSP (when message is mtp3-originated)
if (msg.getIsMtpOriginated()) {
this.sendManagementMessage(dpc, SSP, ssn, 0, null);
}
}
protected void receivedForCongestionUser(SccpMessage msg, int ssn, Integer congestionLevel) {
int dpc = msg.getIncomingOpc();
if (msg.getIsMtpOriginated()) {
this.sendManagementMessage(dpc, SSC, ssn, 0, congestionLevel);
}
}
public void handleMtp3Pause(int affectedPc) {
// Look at Q.714 Section 5.2.2
this.cancelAllSst(affectedPc, true);
this.prohibitRsp(affectedPc, true, RemoteSccpStatus.INACCESIBBLE);
}
protected void handleMtp3Resume(int affectedPc) {
// Look at Q.714 Section 5.2.2
this.allowRsp(affectedPc, true, RemoteSccpStatus.AVAILABLE);
// Send SSA for all SS registered to affectedPc if it's included in
// concerned point-code
FastMap lstrs = this.sccpProviderImpl.getAllSccpListeners();
for (FastMap.Entry e1 = lstrs.head(), end1 = lstrs.tail(); (e1 = e1.getNext()) != end1;) {
int affectedSsn = e1.getKey();
this.broadcastChangedSsnState(affectedSsn, true, affectedPc);
}
}
protected void handleMtp3Status(Mtp3StatusCause cause, int affectedPc, int congStatus) {
switch (cause) {
case SignallingNetworkCongested:
// Signaling Network Congestion
this.onCongState(affectedPc, congStatus);
break;
case UserPartUnavailability_Unknown:
case UserPartUnavailability_InaccessibleRemoteUser:
this.prohibitRsp(affectedPc, false,
(cause == Mtp3StatusCause.UserPartUnavailability_Unknown ? RemoteSccpStatus.UNAVAILABLE
: RemoteSccpStatus.INACCESIBBLE));
SubSystemTest sstForSsn1 = this.cancelAllSst(affectedPc, false);
if (sstForSsn1 != null) {
sstForSsn1.setRecdMtpStatusResp(true);
} else {
// ITU-T Q.714 5.3.4.2 Actions at the initiating node
// A subsystem status test for SSN = 1 is initiated when an
// MTP-STATUS indication primitive is received with
// "remote user inaccessibility" or "unknown" information
// for the SCCP at a remote signalling point
// Start sending the SST for SSN1
this.startSst(affectedPc, 1);
}
break;
case UserPartUnavailability_UnequippedRemoteUser:
// See ITU-T Q.714 5.2.2 Signalling point prohibited
// In the case where the SCCP has received an MTP-STATUS
// indication primitive relating to an unavailable SCCP, the
// SCCP marks the status of the SCCP and each SSN for the
// relevant destination to "prohibited" and initiates a
// subsystem status test with SSN = 1. If the cause in the
// MTP-STATUS indication primitive indicates "unequipped user",
// then no subsystem status test is initiated.
this.prohibitRsp(affectedPc, false, RemoteSccpStatus.UNEQUIPPED);
// Discontinues all subsystem status tests (including SSN = 1)
// if an MTP-PAUSE or MTP-STATUS indication primitive is
// received with a cause of "unequipped SCCP"
this.cancelAllSst(affectedPc, true);
break;
}
}
protected void handleMtp3EndCongestion(int affectedPc) {
this.onEndCong(affectedPc);
}
private void prohibitAllSsn(int affectedPc) {
FastMap lstrs = this.sccpProviderImpl.getAllSccpListeners();
FastMap remoteSsns = this.sccpStackImpl.sccpResource.remoteSsns;
for (FastMap.Entry e = remoteSsns.head(), end = remoteSsns.tail(); (e = e.getNext()) != end;) {
RemoteSubSystemImpl remoteSsn = (RemoteSubSystemImpl) e.getValue();
if (remoteSsn.getRemoteSpc() == affectedPc) {
if (!remoteSsn.isRemoteSsnProhibited()) {
remoteSsn.setRemoteSsnProhibited(true);
setRemoteSsnState(remoteSsn, false);
}
}
}
}
private void allowAllSsn(int affectedPc) {
FastMap remoteSsns = this.sccpStackImpl.sccpResource.remoteSsns;
for (FastMap.Entry e = remoteSsns.head(), end = remoteSsns.tail(); (e = e.getNext()) != end;) {
RemoteSubSystemImpl remoteSsn = (RemoteSubSystemImpl) e.getValue();
if (remoteSsn.getRemoteSpc() == affectedPc) {
if (remoteSsn.getMarkProhibitedWhenSpcResuming()) {
if (!remoteSsn.isRemoteSsnProhibited()) {
remoteSsn.setRemoteSsnProhibited(true);
this.startSst(affectedPc, remoteSsn.getRemoteSsn());
setRemoteSsnState(remoteSsn, false);
}
} else {
if (remoteSsn.isRemoteSsnProhibited()) {
remoteSsn.setRemoteSsnProhibited(false);
setRemoteSsnState(remoteSsn, true);
}
}
}
}
}
private void prohibitRsp(int affectedPc, boolean spcChanging, RemoteSccpStatus remoteSccpStatus) {
RemoteSignalingPointCodeImpl remoteSpc = (RemoteSignalingPointCodeImpl) this.sccpStackImpl.getSccpResource()
.getRemoteSpcByPC(affectedPc);
if (remoteSpc != null) {
boolean oldRemoteSpcProhibited = remoteSpc.isRemoteSpcProhibited();
boolean oldRemoteSccpProhibited = remoteSpc.isRemoteSccpProhibited();
if (spcChanging)
remoteSpc.setRemoteSpcProhibited(true);
if (remoteSccpStatus != null && remoteSccpStatus != RemoteSccpStatus.AVAILABLE)
remoteSpc.setRemoteSccpProhibited(true);
this.sccpStackImpl.ss7ExtSccpDetailedInterface.onProhibitRsp(affectedPc, remoteSccpStatus, remoteSpc);
for (SccpManagementEventListener lstr : this.sccpProviderImpl.managementEventListeners) {
try {
if (remoteSpc.isRemoteSpcProhibited() != oldRemoteSpcProhibited) {
lstr.onRemoteSpcDown(remoteSpc);
}
} catch (Throwable ee) {
logger.error("Exception while invoking onRemoteSpcDown", ee);
}
try {
if (remoteSpc.isRemoteSccpProhibited() != oldRemoteSccpProhibited) {
lstr.onRemoteSccpDown(remoteSpc);
}
} catch (Throwable ee) {
logger.error("Exception while invoking onRemoteSccpDown", ee);
}
}
}
this.prohibitAllSsn(affectedPc);
}
private void allowRsp(int affectedPc, boolean spcChanging, RemoteSccpStatus remoteSccpStatus) {
RemoteSignalingPointCodeImpl remoteSpc = (RemoteSignalingPointCodeImpl) this.sccpStackImpl.getSccpResource()
.getRemoteSpcByPC(affectedPc);
if (remoteSpc != null) {
boolean oldRemoteSpcProhibited = remoteSpc.isRemoteSpcProhibited();
boolean oldRemoteSccpProhibited = remoteSpc.isRemoteSccpProhibited();
if (spcChanging)
remoteSpc.setRemoteSpcProhibited(false);
if (remoteSccpStatus != null && remoteSccpStatus == RemoteSccpStatus.AVAILABLE)
remoteSpc.setRemoteSccpProhibited(false);
remoteSpc.clearCongLevel();
this.sccpStackImpl.ss7ExtSccpDetailedInterface.onAllowRsp(affectedPc, remoteSccpStatus);
for (SccpManagementEventListener lstr : this.sccpProviderImpl.managementEventListeners) {
try {
if (remoteSpc.isRemoteSpcProhibited() != oldRemoteSpcProhibited) {
lstr.onRemoteSpcUp(remoteSpc);
}
} catch (Throwable ee) {
logger.error("Exception while invoking onRemoteSpcUp", ee);
}
try {
if (remoteSpc.isRemoteSccpProhibited() != oldRemoteSccpProhibited) {
lstr.onRemoteSccpUp(remoteSpc);
}
} catch (Throwable ee) {
logger.error("Exception while invoking onRemoteSccpUp", ee);
}
}
}
this.allowAllSsn(affectedPc);
}
private void prohibitSsn(int affectedPc, int ssn) {
FastMap remoteSsns = this.sccpStackImpl.sccpResource.remoteSsns;
for (FastMap.Entry e = remoteSsns.head(), end = remoteSsns.tail(); (e = e.getNext()) != end;) {
RemoteSubSystemImpl remoteSsn = (RemoteSubSystemImpl) e.getValue();
if (remoteSsn.getRemoteSpc() == affectedPc && remoteSsn.getRemoteSsn() == ssn) {
if (!remoteSsn.isRemoteSsnProhibited()) {
setRemoteSsnState(remoteSsn, false);
}
break;
}
}
}
private void setRemoteSsnState(RemoteSubSystemImpl remoteSsn, boolean isEnabled) {
remoteSsn.setRemoteSsnProhibited(!isEnabled);
FastMap lstrs = this.sccpProviderImpl.getAllSccpListeners();
for (FastMap.Entry e1 = lstrs.head(), end1 = lstrs.tail(); (e1 = e1.getNext()) != end1;) {
try {
e1.getValue().onState(remoteSsn.getRemoteSpc(), remoteSsn.getRemoteSsn(), isEnabled, 0);
} catch (Exception ee) {
logger.error("Exception while invoking onState", ee);
}
}
for (SccpManagementEventListener lstr : this.sccpProviderImpl.managementEventListeners) {
try {
if (isEnabled)
lstr.onRemoteSubSystemUp(remoteSsn);
else
lstr.onRemoteSubSystemDown(remoteSsn);
} catch (Throwable ee) {
logger.error("Exception while invoking onRemoteSubSystemUp/Down", ee);
}
}
}
private void allowSsn(int affectedPc, int ssn) {
FastMap remoteSsns = this.sccpStackImpl.sccpResource.remoteSsns;
for (FastMap.Entry e = remoteSsns.head(), end = remoteSsns.tail(); (e = e.getNext()) != end;) {
RemoteSubSystemImpl remoteSsn = (RemoteSubSystemImpl) e.getValue();
if (remoteSsn.getRemoteSpc() == affectedPc && (ssn == 1 || remoteSsn.getRemoteSsn() == ssn)) {
if (remoteSsn.isRemoteSsnProhibited()) {
remoteSsn.setRemoteSsnProhibited(false);
setRemoteSsnState(remoteSsn, true);
}
break;
}
}
}
private void startSst(int affectedPc, int affectedSsn) {
FastList ssts = this.getSubSystemTestListForAffectedDpc(affectedPc, true);
synchronized (ssts) {
SubSystemTest sst = getSubSystemTestBySsn(ssts, affectedSsn);
if (sst == null) {
sst = new SubSystemTest(affectedSsn, affectedPc, ssts);
sst.startTest();
} else {
sst.resetTimerDuration();
sst.stopTest();
sst.startTest();
}
}
}
private void cancelSst(int affectedPc, int affectedSsn) {
FastList ssts1 = this.getSubSystemTestListForAffectedDpc(affectedPc, false);
if (ssts1 != null) {
SubSystemTest sst1 = getSubSystemTestBySsn(ssts1, affectedSsn);
if (sst1 != null) {
sst1.stopTest();
}
}
}
private SubSystemTest cancelAllSst(int affectedPc, boolean cancelSstForSsn1) {
SubSystemTest sstForSsn1 = null;
// cancel all SST if any
FastList ssts = this.getSubSystemTestListForAffectedDpc(affectedPc, false);
if (ssts != null) {
ArrayList arr = new ArrayList();
synchronized (ssts) {
// TODO : Amit: Added n.getValue() != null check. Evaluate
// javolution.FastList as why for loop continues even after
// removing
// last element?
for (FastList.Node n = ssts.head(), endSst = ssts.tail(); ((n = n.getNext()) != endSst)
&& n.getValue() != null;) {
arr.add(n.getValue());
}
}
for (SubSystemTest sst : arr) {
// If SSN = 1 but flag ssn1 is false, means we don't stop this
// SST and return back the reference to it
if (sst.getSsn() == 1 && !cancelSstForSsn1) {
sstForSsn1 = sst;
continue;
}
sst.stopTest();
}
}
return sstForSsn1;
}
private FastList getSubSystemTestListForAffectedDpc(int affectedPc, boolean createIfAbsent) {
synchronized (dpcVsSst) {
FastList ssts = dpcVsSst.get(affectedPc);
if (ssts != null || !createIfAbsent)
return ssts;
ssts = new FastList();
dpcVsSst.put(affectedPc, ssts);
return ssts;
}
}
private SubSystemTest getSubSystemTestBySsn(FastList ssts, int affectedSsn) {
synchronized (ssts) {
SubSystemTest sst = null;
for (FastList.Node n = ssts.head(), end = ssts.tail(); (n = n.getNext()) != end;) {
sst = n.getValue();
if (sst.getSsn() == affectedSsn) {
break;
}
}
return sst;
}
}
private void onCongState(int affectedPc, int congStatus) {
RemoteSignalingPointCodeImpl remoteSpc = (RemoteSignalingPointCodeImpl) this.sccpStackImpl.getSccpResource()
.getRemoteSpcByPC(affectedPc);
if (remoteSpc != null) {
remoteSpc.increaseCongLevel(congStatus);
}
}
private void onEndCong(int affectedPc) {
RemoteSignalingPointCodeImpl remoteSpc = (RemoteSignalingPointCodeImpl) this.sccpStackImpl.getSccpResource()
.getRemoteSpcByPC(affectedPc);
if (remoteSpc != null) {
remoteSpc.clearCongLevel();
}
}
public void onRestrictionLevelChange(int affectedPc, int restrictionLevel, boolean levelEncreased) {
this.sccpStackImpl.ss7ExtSccpDetailedInterface.onRestrictionLevelChange(affectedPc, restrictionLevel, levelEncreased);
}
private void doOnNetworkIdState(int affectedPc) {
// TODO: implement it
}
private class SubSystemTest implements Runnable {
// FIXME: remove "Thread", so we eat less resources.
private volatile boolean started = false;
// Flag to check if received an MTP-STATUS indication primitive stating
// User Part Unavailable.
private volatile boolean recdMtpStatusResp = true;
private Future testFuture;
private FastList testsList; // just a ref to list of
// testse for DPC, instances
// of this classes should be
// there.
private int ssn = 0;
private int affectedPc = 0;
private int currentTimerDelay = sccpStackImpl.sstTimerDuration_Min;
SubSystemTest(int ssn, int affectedPc, FastList testsList) {
this.ssn = ssn;
this.affectedPc = affectedPc;
this.testsList = testsList;
}
public int getSsn() {
return ssn;
}
public void setRecdMtpStatusResp(boolean recdMtpStatusResp) {
this.recdMtpStatusResp = recdMtpStatusResp;
}
void stopTest() {
synchronized (this.testsList) {
started = false;
Future f = this.testFuture;
if (f != null) {
this.testsList.remove(this);
this.testFuture = null;
f.cancel(false);
}
}
try {
notify();
} catch (Exception e) {
}
}
void startTest() {
synchronized (this.testsList) {
if (!started) {
this.testFuture = managementExecutors.schedule(this, currentTimerDelay, TimeUnit.MILLISECONDS);
// increase the "T(stat info)" timer delay up to 10 minutes
// for the next step
currentTimerDelay = (int) (currentTimerDelay * sccpStackImpl.sstTimerDuration_IncreaseFactor);
if (currentTimerDelay > sccpStackImpl.sstTimerDuration_Max)
currentTimerDelay = sccpStackImpl.sstTimerDuration_Max;
started = true;
this.testsList.add(this);
}
}
}
private void resetTimerDuration() {
currentTimerDelay = sccpStackImpl.sstTimerDuration_Min;
}
public void run() {
if (started) {
synchronized (this.testsList) {
if (this.ssn == 1 && !this.recdMtpStatusResp) {
// If no MTP STATUS received, means we consider
// previously
// unavailable (SCCP) has recovered
this.stopTest();
// Stop the SST if already started
FastList ssts1 = getSubSystemTestListForAffectedDpc(affectedPc, false);
if (ssts1 != null) {
SubSystemTest sst1 = getSubSystemTestBySsn(ssts1, ssn);
if (sst1 != null) {
sst1.stopTest();
}
}
if (ssn == 1) {
allowRsp(affectedPc, false, RemoteSccpStatus.AVAILABLE);
} else {
// Mark remote SSN Allowed
allowSsn(affectedPc, ssn);
}
return;
}
// Set it false again so we wait for response again after
// sending SST for SSN = 1 bellow
this.recdMtpStatusResp = false;
// TODO : How much to sleep?
this.stopTest();
this.startTest();
}
sendManagementMessage(affectedPc, SST, ssn, 0, null);
}// while
}// run
}// SubSystemTest
public void start() {
synchronized (dpcVsSst) {
this.dpcVsSst.clear();
}
managementExecutors = Executors.newScheduledThreadPool(1);
}
public void stop() {
// no need to stop, it will clean on start, and scheduler is dead.
managementExecutors.shutdownNow();
}
private String getMessageType(int msgType) {
switch (msgType) {
case SSA:
return S_SSA;
case SSP:
return S_SSP;
case SST:
return S_SST;
case SOR:
return S_SOR;
case SOG:
return S_SOG;
case SSC:
return S_SSC;
default:
return S_DEFAULT;
}
}
private class DpcSsn {
private int dpc;
private int ssn;
public DpcSsn(int aDpc, int aSsn) {
dpc = aDpc;
ssn = aSsn;
}
public int getDpc() {
return dpc;
}
public int getSsn() {
return ssn;
}
@Override
public boolean equals(Object obj) {
if (obj == null && !(obj instanceof DpcSsn))
return false;
DpcSsn y = (DpcSsn) obj;
if (this.dpc == y.dpc && this.ssn == y.ssn)
return true;
else
return false;
}
@Override
public int hashCode() {
return this.dpc + 256 * 256 * this.ssn;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy