All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.restcomm.protocols.ss7.sccp.impl.SccpConnectionWithTimers Maven / Gradle / Ivy

The newest version!
package org.restcomm.protocols.ss7.sccp.impl;

import org.restcomm.protocols.ss7.sccp.SccpConnection;
import org.restcomm.protocols.ss7.sccp.SccpConnectionState;
import org.restcomm.protocols.ss7.sccp.SccpListener;
import org.restcomm.protocols.ss7.sccp.impl.message.SccpConnCcMessageImpl;
import org.restcomm.protocols.ss7.sccp.impl.message.SccpConnItMessageImpl;
import org.restcomm.protocols.ss7.sccp.impl.message.SccpConnRscMessageImpl;
import org.restcomm.protocols.ss7.sccp.impl.parameter.CreditImpl;
import org.restcomm.protocols.ss7.sccp.impl.parameter.ReleaseCauseImpl;
import org.restcomm.protocols.ss7.sccp.impl.parameter.SequenceNumberImpl;
import org.restcomm.protocols.ss7.sccp.impl.parameter.SequencingSegmentingImpl;
import org.restcomm.protocols.ss7.sccp.message.SccpConnMessage;
import org.restcomm.protocols.ss7.sccp.parameter.LocalReference;
import org.restcomm.protocols.ss7.sccp.parameter.ProtocolClass;
import org.restcomm.protocols.ss7.sccp.parameter.ReleaseCauseValue;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static org.restcomm.protocols.ss7.sccp.SccpConnectionState.CLOSED;
import static org.restcomm.protocols.ss7.sccp.SccpConnectionState.CONNECTION_INITIATED;
import static org.restcomm.protocols.ss7.sccp.SccpConnectionState.DISCONNECT_INITIATED;
import static org.restcomm.protocols.ss7.sccp.SccpConnectionState.RSR_SENT;

abstract class SccpConnectionWithTimers extends SccpConnectionWithTransmitQueueImpl {
    private ConnEstProcess connEstProcess;
    private IasInactivitySendProcess iasInactivitySendProcess;
    private IarInactivityReceiveProcess iarInactivityReceiveProcess;
    private RelProcess relProcess;
    private RepeatRelProcess repeatRelProcess;
    private IntProcess intProcess;
    private GuardProcess guardProcess;
    private ResetProcess resetProcess;

    public SccpConnectionWithTimers(int sls, int localSsn, LocalReference localReference, ProtocolClass protocol, SccpStackImpl stack, SccpRoutingControl sccpRoutingControl) {
        super(sls, localSsn, localReference, protocol, stack, sccpRoutingControl);
        connEstProcess = new ConnEstProcess();
        iasInactivitySendProcess = new IasInactivitySendProcess();
        iarInactivityReceiveProcess = new IarInactivityReceiveProcess();
        relProcess = new RelProcess();
        repeatRelProcess = new RepeatRelProcess();
        intProcess = new IntProcess();
        guardProcess = new GuardProcess();
        resetProcess = new ResetProcess();
    }

    protected void stopTimers() {
        connEstProcess.stopTimer();
        iasInactivitySendProcess.stopTimer();
        iarInactivityReceiveProcess.stopTimer();
        relProcess.stopTimer();
        repeatRelProcess.stopTimer();
        intProcess.stopTimer();
        guardProcess.stopTimer();
        resetProcess.stopTimer();
    }

    protected void receiveMessage(SccpConnMessage message) throws Exception {
        iarInactivityReceiveProcess.resetTimer();

        if (message instanceof SccpConnCcMessageImpl) {
            connEstProcess.stopTimer();

        } else if (message instanceof SccpConnRscMessageImpl) {
            resetProcess.stopTimer();
        }

        super.receiveMessage(message);
    }

    protected void sendMessage(SccpConnMessage message) throws Exception {
        if (stack.state != SccpStackImpl.State.RUNNING) {
            logger.error("Trying to send SCCP message from SCCP user but SCCP stack is not RUNNING");
            return;
        }
        iasInactivitySendProcess.resetTimer();
        super.sendMessage(message);
    }

    public void setState(SccpConnectionState state) {
        try {
            connectionLock.lock();
            super.setState(state);

            if (state == RSR_SENT) {
                resetProcess.startTimer();

            } else if (state == DISCONNECT_INITIATED) {
                relProcess.startTimer();
                iasInactivitySendProcess.stopTimer();
                iarInactivityReceiveProcess.stopTimer();

            } else if (state == CONNECTION_INITIATED) {
                connEstProcess.startTimer();
            }
        } finally {
            connectionLock.unlock();
        }
    }

    protected class ConnEstProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getConnEstTimerDelay();
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED) {
                    return;
                }

                disconnect(new ReleaseCauseImpl(ReleaseCauseValue.SCCP_FAILURE), new byte[]{});

            } catch (Exception e) {
                logger.error(e);
            } finally {
                connectionLock.unlock();
            }
        }
    }

    protected class IasInactivitySendProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getIasTimerDelay();
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED || getState() == CONNECTION_INITIATED) {
                    return;
                }

                SccpConnItMessageImpl it = new SccpConnItMessageImpl(getSls(), getLocalSsn());
                it.setProtocolClass(getProtocolClass());
                it.setSourceLocalReferenceNumber(getLocalReference());
                it.setDestinationLocalReferenceNumber(getRemoteReference());

                // could be overwritten during preparing
                it.setCredit(new CreditImpl(0));
                it.setSequencingSegmenting(new SequencingSegmentingImpl(new SequenceNumberImpl(0, false),
                        new SequenceNumberImpl(0, false), lastMoreDataSent));
                prepareMessageForSending(it);
                sendMessage(it);

            } catch (Exception e) {
                logger.error(e);
            } finally {
                connectionLock.unlock();
            }
        }
    }

    protected class IarInactivityReceiveProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getIarTimerDelay();
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED) {
                    return;
                }

                disconnect(new ReleaseCauseImpl(ReleaseCauseValue.EXPIRATION_OF_RECEIVE_INACTIVITY_TIMER), new byte[] {});

            } catch (Exception e) {
                logger.error(e);
            } finally {
                connectionLock.unlock();
            }
        }
    }

    protected class RelProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getRelTimerDelay();
        }

        @Override
        public void startTimer() {
            try {
                connectionLock.lock();
                if (this.isStarted()) {
                    return; // ignore if already started
                }
                super.startTimer();

            } finally {
                connectionLock.unlock();
            }
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED) {
                    return;
                }

                disconnect(new ReleaseCauseImpl(ReleaseCauseValue.SCCP_FAILURE), new byte[]{});
                intProcess.startTimer();
                repeatRelProcess.startTimer();

            } catch (Exception e) {
                logger.error(e);
            } finally {
                connectionLock.unlock();
            }
        }
    }

    protected class RepeatRelProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getRepeatRelTimerDelay();
        }

        @Override
        public void startTimer() {
            try {
                connectionLock.lock();
                if (this.isStarted()) {
                    return; // ignore if already started
                }
                super.startTimer();

            } finally {
                connectionLock.unlock();
            }
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED) {
                    return;
                }

                disconnect(new ReleaseCauseImpl(ReleaseCauseValue.SCCP_FAILURE), new byte[]{});
                repeatRelProcess.startTimer();

            } catch (Exception e) {
                logger.error(e);
            } finally {
                connectionLock.unlock();
            }
        }
    }

    protected class IntProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getIntTimerDelay();
        }

        @Override
        public void startTimer() {
            try {
                connectionLock.lock();
                if (this.isStarted()) {
                    return; // ignore if already started
                }
                super.startTimer();

            } finally {
                connectionLock.unlock();
            }
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED) {
                    return;
                }

                repeatRelProcess.stopTimer();

                SccpListener listener = getListener();
                if (listener != null) {
                    listener.onDisconnectIndication((SccpConnection) SccpConnectionWithTimers.this, new ReleaseCauseImpl(ReleaseCauseValue.SCCP_FAILURE), new byte[] {});
                }
                stack.removeConnection(getLocalReference());

            } finally {
                connectionLock.unlock();
            }
        }
    }

    protected class GuardProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getGuardTimerDelay();
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED) {
                    return;
                }
                // do smt...

            } finally {
                connectionLock.unlock();
            }
        }
    }

    protected class ResetProcess extends BaseProcess implements Runnable {
        {
            delay = stack.getResetTimerDelay();
        }

        @Override
        public void run() {
            try {
                connectionLock.lock();
                if (getState() == CLOSED) {
                    return;
                }

                disconnect(new ReleaseCauseImpl(ReleaseCauseValue.SCCP_FAILURE), new byte[]{});
                stack.removeConnection(getLocalReference());

            } catch (Exception e) {
                logger.error(e);
            } finally {
                connectionLock.unlock();
            }
        }
    }

    private class BaseProcess implements Runnable {
        protected long delay = stack.getConnEstTimerDelay();
        private Future future;

        public void startTimer() {
            try {
                connectionLock.lock();
                if (this.future != null) { // need to lock because otherwise this check won't ensure safety
                    logger.error(new IllegalStateException(String.format("Already started %s timer", getClass())));
                }
                this.future = stack.timerExecutors.schedule(this, delay, TimeUnit.MILLISECONDS);

            } finally {
                connectionLock.unlock();
            }
        }

        public void stopTimer() {
            try {
                connectionLock.lock();
                if (this.future != null) { // need to lock because otherwise this check won't ensure safety
                    this.future.cancel(false);
                    this.future = null;
                }

            } finally {
                connectionLock.unlock();
            }
        }

        public void resetTimer() {
            stopTimer();
            startTimer();
        }

        public boolean isStarted() {
            return future != null;
        }

        @Override
        public void run() {
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy