//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / NNI SSCF protocol
//
//File: nsscfstate2_10_3.cpp
//
//Version: $Revision: 1.9 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/05/26 14:29:50 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications and Multimedia
//
//Author:
//      Juhana Räsänen
//
//Description:
//      See corresponding header file
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 


#include <assert.h>
#include "nsscfstate2_10_3.h"
#include "nsscfprotocol.h"
#include "protocol/sscop/sscop.h"
#include "iface/aaif/aaupprimitives.h"
#include "iface/naalif/naaldownprimitives.h"
#include "pf/frame.h"


//
// Variable: nsscfProving_DataTransferReady :: _only
// Function: nsscfProving_DataTransferReady :: instance()
//
// Description:
//     Implements the singleton pattern used for actual states
//

nsscfProving_DataTransferReady *
nsscfProving_DataTransferReady :: _only = 0;

nsscfProving_DataTransferReady *
nsscfProving_DataTransferReady :: instance(void)
{
    if (_only == 0)
    {
        _only = new nsscfProving_DataTransferReady;
        assert(_only != 0);
    }
    return _only;
}


nsscfProving_DataTransferReady :: nsscfProving_DataTransferReady(void)
    : nsscfState()
{
    return;
}

nsscfProving_DataTransferReady :: ~nsscfProving_DataTransferReady(void)
{
    _only = 0;
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: naalSTOPreqAct()
// Implemented as in Q.2140 page 56 SDL description

void nsscfProving_DataTransferReady ::
naalSTOPreqAct(naalSTOPreq *, pfProtocol *protocol_)
{
    nsscfProtocol *nsscf = (nsscfProtocol *) protocol_;
    releaseConnection(nsscf, nsscfOOSpdu, 0);
    nsscf->sendMaalREPORTind(LBC_EMPTY, UBC_OOS);
    nsscf->sendMaalSTOP_PROVINGind();
    nsscf->timerT2stop();
    nsscf->timerT3stop();
    nsscf->setUPSnormal();
    nsscf->toNsscfOutOfService_OutgoingDisconnectionPending();
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: aaRELEASEindAct()
// Implemented as in Q.2140 page 56 SDL description

void nsscfProving_DataTransferReady ::
aaRELEASEindAct(aaRELEASEind *messenger_, pfProtocol *protocol_)
{
    nsscfProtocol *nsscf = (nsscfProtocol *) protocol_;
    pfUlong source = messenger_->getSource();
    if (source == SSCOP_RELEASE_USER)
    {
        nsscfPDU pdu = nsscf->decodePDU(messenger_->getSSCOP_UU());
        nsscf->sendMaalREPORTind(LBC_RR, UBC_EMPTY, R_SSCOP_UU, pdu);
    }
    else
    {
        nsscf->sendMaalREPORTind(LBC_SR);
    }
    nsscf->sendMaalSTOP_PROVINGind();
    nsscf->timerT3stop();
    nsscf->timerT1start();
    nsscf->toNsscfAlignment_Idle();
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: aaDATAindAct()
// Implemented as in Q.2140 page 56 SDL description

void nsscfProving_DataTransferReady ::
aaDATAindAct(aaDATAind *messenger_, pfProtocol *protocol_)
{
    nsscfProtocol *nsscf = (nsscfProtocol *) protocol_;
    pfFrame mu = messenger_->getMessageUnit();
    if (mu.length() > NSSCF_PDU_LENGTH)
    {
        releaseConnection(nsscf, nsscfPEpdu, 0);
        nsscf->sendMaalREPORTind(LBC_LR, UBC_EMPTY, R_PE);
        nsscf->sendMaalSTOP_PROVINGind();
        nsscf->timerT3stop();
        nsscf->toNsscfAlignment_OutgoingDisconnectionPending();
    }
    else if ((mu.length() == NSSCF_PDU_LENGTH) &&
             (nsscf->decodePDU(mu) == nsscfINSpdu))
    {
        nsscf->setInService();
    }
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: aaRESYNCindAct()
// Implemented as in Q.2140 page 57 SDL description

void nsscfProving_DataTransferReady ::
aaRESYNCindAct(aaRESYNCind *, pfProtocol *protocol_)
{
    nsscfProtocol *nsscf = (nsscfProtocol *) protocol_;
    releaseConnection(nsscf, nsscfPEpdu, 0);
    nsscf->sendMaalREPORTind(LBC_LR, UBC_EMPTY, R_PE);
    nsscf->sendMaalSTOP_PROVINGind();
    nsscf->timerT3stop();
    nsscf->toNsscfAlignment_OutgoingDisconnectionPending();
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: aaRECOVERindAct()
// Implemented as in Q.2140 page 57 SDL description

void nsscfProving_DataTransferReady ::
aaRECOVERindAct(aaRECOVERind *, pfProtocol *protocol_)
{
    nsscfProtocol *nsscf = (nsscfProtocol *) protocol_;
    releaseConnection(nsscf, nsscfPEpdu, 0);
    nsscf->sendMaalREPORTind(LBC_LR, UBC_EMPTY, R_PE);
    nsscf->sendMaalSTOP_PROVINGind();
    nsscf->timerT3stop();
    nsscf->toNsscfAlignment_OutgoingDisconnectionPending();
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: maalPROVING_UNSUCCESFULrespAct()
// Implemented as in Q.2140 page 57 SDL description

void nsscfProving_DataTransferReady ::
maalPROVING_UNSUCCESFULrespAct(maalPROVING_UNSUCCESFULresp *,
                               pfProtocol *protocol_)
{
    nsscfProtocol *nsscf = (nsscfProtocol *) protocol_;
    releaseConnection(nsscf, nsscfPNSpdu, 0);
    nsscf->timerT3stop();
    nsscf->toNsscfAlignment_OutgoingDisconnectionPending();
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: maalRELEASEreqAct()
// Implemented as in Q.2140 page 58 SDL description

void nsscfProving_DataTransferReady ::
maalRELEASEreqAct(maalRELEASEreq *, pfProtocol *protocol_)
{
    nsscfProtocol *nsscf = (nsscfProtocol *) protocol_;
    releaseConnection(nsscf, nsscfMIpdu, 1);
    nsscf->timerT2stop();
    nsscf->timerT3stop();
    nsscf->setUPSnormal();
    nsscf->toNsscfOutOfService_OutgoingDisconnectionPending();
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: nsscfT2timeoutAct()
// Implemented as in Q.2140 page 58 SDL description

void nsscfProving_DataTransferReady ::
nsscfT2timeoutAct(nsscfProtocol *protocol_)
{
    releaseConnection(protocol_, nsscfANSpdu, 1);
    protocol_->sendMaalREPORTind(LBC_LR, UBC_OOS, R_ANS);
    protocol_->sendMaalSTOP_PROVINGind();
    protocol_->timerT3stop();
    protocol_->setUPSnormal();
    protocol_->toNsscfOutOfService_OutgoingDisconnectionPending();
    return;
}


//////////////////////////////////////////////////////////////////////////
// void nsscfProving_DataTransferReady :: nsscfT3timeoutAct()
// Implemented as in Q.2140 page 58 SDL description

void nsscfProving_DataTransferReady ::
nsscfT3timeoutAct(nsscfProtocol *protocol_)
{
    if (protocol_->getC1() > 0)
    {
        protocol_->sendAaDATAreq(protocol_->encodePDU(nsscfNMpdu));
        protocol_->decreaseC1();
        protocol_->timerT3start();
    }
    else
    {
        if (protocol_->isLPO() == 0)
        {
            protocol_->sendAaDATAreq(protocol_->encodePDU(nsscfINSpdu));
            protocol_->sendMaalSTOP_PROVINGind();
            if (protocol_->isInService() != 0)
            {
                protocol_->sendNaalIN_SERVICEind();
                protocol_->sendMaalREPORTind(LBC_EMPTY, UBC_INS);
                protocol_->timerT2stop();
                protocol_->toNsscfInService_DataTransferReady();
            }
            else
            {
                protocol_->toNsscfAlignedReady_DataTransferReady();
            }
        }
        else
        {
            releaseConnection(protocol_, nsscfPOpdu, 1);
            protocol_->sendMaalREPORTind(LBC_LR, UBC_OOS);
            protocol_->sendMaalSTOP_PROVINGind();
            protocol_->timerT2stop();
            protocol_->setUPSnormal();
            protocol_->toNsscfOutOfService_OutgoingDisconnectionPending();
        }
    }
    return;
}

