
org.restcomm.protocols.ss7.m3ua.impl.AspStateMaintenanceHandler Maven / Gradle / Ivy
/*
* 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.m3ua.impl;
import javolution.util.FastList;
import org.apache.log4j.Logger;
import org.restcomm.protocols.ss7.m3ua.Asp;
import org.restcomm.protocols.ss7.m3ua.ExchangeType;
import org.restcomm.protocols.ss7.m3ua.Functionality;
import org.restcomm.protocols.ss7.m3ua.IPSPType;
import org.restcomm.protocols.ss7.m3ua.impl.fsm.FSM;
import org.restcomm.protocols.ss7.m3ua.impl.fsm.UnknownTransitionException;
import org.restcomm.protocols.ss7.m3ua.message.MessageClass;
import org.restcomm.protocols.ss7.m3ua.message.MessageType;
import org.restcomm.protocols.ss7.m3ua.message.aspsm.ASPDown;
import org.restcomm.protocols.ss7.m3ua.message.aspsm.ASPDownAck;
import org.restcomm.protocols.ss7.m3ua.message.aspsm.ASPUp;
import org.restcomm.protocols.ss7.m3ua.message.aspsm.ASPUpAck;
import org.restcomm.protocols.ss7.m3ua.message.aspsm.Heartbeat;
import org.restcomm.protocols.ss7.m3ua.message.aspsm.HeartbeatAck;
import org.restcomm.protocols.ss7.m3ua.parameter.ASPIdentifier;
import org.restcomm.protocols.ss7.m3ua.parameter.ErrorCode;
import org.restcomm.protocols.ss7.m3ua.parameter.TrafficModeType;
/**
*
* @author amit bhayani
*
*/
public class AspStateMaintenanceHandler extends MessageHandler {
private static final Logger logger = Logger.getLogger(AspStateMaintenanceHandler.class);
public AspStateMaintenanceHandler(AspFactoryImpl aspFactoryImpl) {
super(aspFactoryImpl);
}
protected void handleAspUp(ASPUp aspUp) {
if (aspFactoryImpl.getFunctionality() == Functionality.SGW
|| (aspFactoryImpl.getFunctionality() == Functionality.AS && aspFactoryImpl.getExchangeType() == ExchangeType.DE)
|| (aspFactoryImpl.getFunctionality() == Functionality.IPSP && aspFactoryImpl.getExchangeType() == ExchangeType.DE)
|| (aspFactoryImpl.getFunctionality() == Functionality.IPSP
&& aspFactoryImpl.getExchangeType() == ExchangeType.SE && aspFactoryImpl.getIpspType() == IPSPType.SERVER)) {
ASPUpAck aspUpAck = (ASPUpAck) this.aspFactoryImpl.messageFactory.createMessage(MessageClass.ASP_STATE_MAINTENANCE,
MessageType.ASP_UP_ACK);
ASPIdentifier aspId = aspUp.getASPIdentifier();
aspUpAck.setASPIdentifier(aspId);
this.aspFactoryImpl.write(aspUpAck);
// If an ASP Up message is received and, internally, the remote ASP
// is in the ASP-ACTIVE state, an ASP Up Ack message is returned, as
// well as an Error message ("Unexpected Message"). In addition, the
// remote ASP state is changed to ASP-INACTIVE in all relevant
// Application Servers, and all registered Routing Keys are
// considered deregistered.
for (FastList.Node n = this.aspFactoryImpl.aspList.head(), end = this.aspFactoryImpl.aspList.tail(); (n = n
.getNext()) != end;) {
AspImpl aspImpl = (AspImpl) n.getValue();
// Set the ASPIdentifier for each ASP
aspImpl.setASPIdentifier(aspUp.getASPIdentifier());
FSM aspPeerFSM = aspImpl.getPeerFSM();
if (aspPeerFSM == null) {
logger.error(String.format("Received ASPUP=%s for ASP=%s. But peer FSM is null.", aspUp,
this.aspFactoryImpl.getName()));
return;
}
if (AspState.getState(aspPeerFSM.getState().getName()) == AspState.ACTIVE) {
// Check if ASP is in ACTIVE, its error state
ErrorCode errorCodeObj = this.aspFactoryImpl.parameterFactory.createErrorCode(ErrorCode.Unexpected_Message);
this.sendError(aspImpl.getAs().getRoutingContext(), errorCodeObj);
// break;
}
try {
// Signal ASP about state change
aspPeerFSM.setAttribute(FSM.ATTRIBUTE_MESSAGE, aspUp);
aspPeerFSM.signal(TransitionState.ASP_UP);
// Signal corresponding AS about ASP's state transition
FSM asLocalFSM = ((AsImpl) aspImpl.getAs()).getLocalFSM();
asLocalFSM.setAttribute(AsImpl.ATTRIBUTE_ASP, aspImpl);
asLocalFSM.signal(TransitionState.ASP_UP);
} catch (UnknownTransitionException e) {
logger.error(e.getMessage(), e);
}
}
} else {
// TODO : Should we silently drop ASPUP_ACK?
// ASPUP_ACK is unexpected in this state
ErrorCode errorCodeObj = this.aspFactoryImpl.parameterFactory.createErrorCode(ErrorCode.Unexpected_Message);
sendError(null, errorCodeObj);
}
}
protected void handleAspUpAck(ASPUpAck aspUpAck) {
if (!this.aspFactoryImpl.started) {
// If management stopped this ASP, ignore ASPUpAck
return;
}
if (aspFactoryImpl.getFunctionality() == Functionality.AS
|| (aspFactoryImpl.getFunctionality() == Functionality.SGW && aspFactoryImpl.getExchangeType() == ExchangeType.DE)
|| (aspFactoryImpl.getFunctionality() == Functionality.IPSP && aspFactoryImpl.getExchangeType() == ExchangeType.DE)
|| (aspFactoryImpl.getFunctionality() == Functionality.IPSP
&& aspFactoryImpl.getExchangeType() == ExchangeType.SE && aspFactoryImpl.getIpspType() == IPSPType.CLIENT)) {
for (FastList.Node n = this.aspFactoryImpl.aspList.head(), end = this.aspFactoryImpl.aspList.tail(); (n = n
.getNext()) != end;) {
AspImpl aspImpl = (AspImpl) n.getValue();
FSM aspLocalFSM = aspImpl.getLocalFSM();
if (aspLocalFSM == null) {
logger.error(String.format("Received ASPUP_ACK=%s for ASP=%s. But local FSM is null.", aspUpAck,
this.aspFactoryImpl.getName()));
return;
}
boolean transToActive = this.activate(aspImpl);
if (!transToActive) {
// Transition to INACTIVE
try {
aspLocalFSM.signal(TransitionState.ASP_INACTIVE);
} catch (UnknownTransitionException e) {
logger.error(e.getMessage(), e);
}
} else {
// Transition to ACTIVE_SENT
try {
aspLocalFSM.signal(TransitionState.ASP_ACTIVE_SENT);
if (aspFactoryImpl.getFunctionality() == Functionality.IPSP) {
// If its IPSP, we know NTFY will not be received,
// so transition AS FSM here
AsImpl asImpl = (AsImpl) aspImpl.getAs();
FSM asPeerFSM = asImpl.getPeerFSM();
if (asPeerFSM == null) {
logger.error(String.format("Received ASPUP_ACK=%s for ASP=%s. But Peer FSM of AS=%s is null.",
aspUpAck, this.aspFactoryImpl.getName(), asImpl));
return;
}
AsState asPeerFSMState = AsState.getState(asPeerFSM.getState().getName());
if (AsState.DOWN == asPeerFSMState) {
// Transition to INACTIVE only if its DOWN
asPeerFSM.setAttribute(AsImpl.ATTRIBUTE_ASP, aspImpl);
asPeerFSM.signal(TransitionState.AS_STATE_CHANGE_INACTIVE);
}
}
} catch (UnknownTransitionException e) {
logger.error(e.getMessage(), e);
}
}// if..else
}// for
} else {
// TODO : Should we silently drop ASPUP_ACK?
// ASPUP_ACK is unexpected in this state
ErrorCode errorCodeObj = this.aspFactoryImpl.parameterFactory.createErrorCode(ErrorCode.Unexpected_Message);
sendError(null, errorCodeObj);
}
}
protected void handleAspDown(ASPDown aspDown) {
if (aspFactoryImpl.getFunctionality() == Functionality.SGW
|| (aspFactoryImpl.getFunctionality() == Functionality.AS && aspFactoryImpl.getExchangeType() == ExchangeType.DE)
|| (aspFactoryImpl.getFunctionality() == Functionality.IPSP && aspFactoryImpl.getExchangeType() == ExchangeType.DE)
|| (aspFactoryImpl.getFunctionality() == Functionality.IPSP
&& aspFactoryImpl.getExchangeType() == ExchangeType.SE && aspFactoryImpl.getIpspType() == IPSPType.SERVER)) {
ASPDownAck aspDwnAck = (ASPDownAck) this.aspFactoryImpl.messageFactory.createMessage(
MessageClass.ASP_STATE_MAINTENANCE, MessageType.ASP_DOWN_ACK);
this.aspFactoryImpl.write(aspDwnAck);
// ASPSM should be given to all ASP's
for (FastList.Node n = this.aspFactoryImpl.aspList.head(), end = this.aspFactoryImpl.aspList.tail(); (n = n
.getNext()) != end;) {
AspImpl aspImpl = (AspImpl) n.getValue();
FSM aspPeerFSM = aspImpl.getPeerFSM();
if (aspPeerFSM == null) {
logger.error(String.format("Received ASPDOWN=%s for ASP=%s. But peer FSM is null.", aspDown,
this.aspFactoryImpl.getName()));
return;
}
try {
// Signal ASP about state change
aspPeerFSM.setAttribute(FSM.ATTRIBUTE_MESSAGE, aspDown);
aspPeerFSM.signal(TransitionState.ASP_DOWN);
// Signal corresponding AS about ASP's state transition
FSM asLocalFSM = ((AsImpl) aspImpl.getAs()).getLocalFSM();
asLocalFSM.setAttribute(AsImpl.ATTRIBUTE_ASP, aspImpl);
asLocalFSM.signal(TransitionState.ASP_DOWN);
} catch (UnknownTransitionException e) {
logger.error(e.getMessage(), e);
}
}
} else {
// TODO : Should we silently drop ASPUP_ACK?
// ASPUP_ACK is unexpected in this state
ErrorCode errorCodeObj = this.aspFactoryImpl.parameterFactory.createErrorCode(ErrorCode.Unexpected_Message);
sendError(null, errorCodeObj);
}
}
protected void handleAspDownAck(ASPDownAck aspUpAck) {
if (!this.aspFactoryImpl.started) {
boolean stopAssociation = true;
for (FastList.Node n = this.aspFactoryImpl.aspList.head(), end = this.aspFactoryImpl.aspList.tail(); (n = n
.getNext()) != end;) {
AspImpl aspImpl = (AspImpl) n.getValue();
FSM fsm = aspImpl.getLocalFSM();
if (fsm == null) {
logger.error(String.format("Received ASPDOWN_ACK=%s for ASP=%s. But local FSM is null.", aspUpAck,
this.aspFactoryImpl.getName()));
continue;
}
FSM fsmPeer = aspImpl.getPeerFSM();
// If ASP's peer FSM is not null and it's state is not DOWN,
// don't stop the underlying Association
if (fsmPeer != null) {
AspState aspPeerState = AspState.getState(fsmPeer.getState().getName());
if (aspPeerState != AspState.DOWN) {
stopAssociation = false;
}
}
try {
fsm.signal(TransitionState.ASP_DOWN_ACK);
} catch (UnknownTransitionException e) {
logger.error(e.getMessage(), e);
}
}// for
if (!stopAssociation) {
logger.error(String
.format("Ungracefully stopping the underlying Association=%s for AspFactory=%s. Atleast one of the ASP's is Double Exchange and Peer ASP state is still not down",
this.aspFactoryImpl.association.getName(), this.aspFactoryImpl.getName()));
}
try {
if (this.aspFactoryImpl.aspFactoryStopTimer != null) {
this.aspFactoryImpl.aspFactoryStopTimer.cancel();
}
this.aspFactoryImpl.transportManagement.stopAssociation(this.aspFactoryImpl.association.getName());
} catch (Exception e) {
logger.error(
String.format("Exception while starting the Association=%s", this.aspFactoryImpl.association.getName()),
e);
}
} else {
logger.error(String.format("Received ASPDOWN_ACK=%s for ASPFactory=%s. But Aspfactory is down.", aspUpAck,
this.aspFactoryImpl.getName()));
}
}
/**
* If we receive Heartbeat, we send back response
*
* @param hrtBeat
*/
public void handleHeartbeat(Heartbeat hrtBeat) {
HeartbeatAck hrtBeatAck = (HeartbeatAck) this.aspFactoryImpl.messageFactory.createMessage(
MessageClass.ASP_STATE_MAINTENANCE, MessageType.HEARTBEAT_ACK);
hrtBeatAck.setHeartbeatData(hrtBeat.getHeartbeatData());
this.aspFactoryImpl.write(hrtBeatAck);
}
private boolean activate(AspImpl aspImpl) {
// If its loadshare, we want to send ASP_ACTIVE else if its
// Override and there is already one ACTIVE, we leave this one
// as INACTIVE
AsImpl asImpl = (AsImpl) aspImpl.getAs();
// By default we assume Traffic Mode is Loadshare
if (asImpl.getTrafficModeType() == null || asImpl.getTrafficModeType().getMode() == TrafficModeType.Loadshare) {
// Activate this ASP
this.aspFactoryImpl.sendAspActive(asImpl);
return true;
} else if (asImpl.getTrafficModeType().getMode() == TrafficModeType.Override) {
for (FastList.Node n = asImpl.appServerProcs.head(), end = asImpl.appServerProcs.tail(); (n = n.getNext()) != end;) {
AspImpl asptemp = (AspImpl) n.getValue();
FSM fsm = asptemp.getLocalFSM();
AspState aspState = AspState.getState(fsm.getState().getName());
if (!asptemp.getName().equals(aspImpl.getName())
&& (aspState == AspState.ACTIVE_SENT || aspState == AspState.ACTIVE)) {
return false;
}
}// for
this.aspFactoryImpl.sendAspActive(asImpl);
return true;
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy