//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / SSCOP protocol
//
//File: sscopstate4.cpp
//
//Version: $Revision: 1.18 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/03/11 18:53:56 $
//
//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 "sscopstate4.h"
#include "sscoppdu.h"
#include "sscopprotocol.h"
#include "iface/aaif/aadownprimitives.h"
#include "pf/frame.h"
#include "pf/timer.h"
#include "pf/error.h"

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

sscopOutgoingDisconnectionPending *
sscopOutgoingDisconnectionPending :: _only = 0;

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


sscopOutgoingDisconnectionPending :: sscopOutgoingDisconnectionPending(void)
    : sscopState()
{
    return;
}

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


//
// Functions: AA primitive input methods
//
// Description:
//     These methods define actions in SSCOP state 4 for incoming
//     AA-signals from the above layer (UNI SSCF or NNI SSCF for
//     the time being)
//

void sscopOutgoingDisconnectionPending :: aaESTABLISHreqAct(
    aaESTABLISHreq *messenger_,
    pfProtocol *protocol_) const
{
    sscopProtocol *sscop = dynamic_cast<sscopProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(sscop);
    sscop->_timerCC.stop();
    sscop->clearTransmitter();
    sscop->_clearBuffers = messenger_->getBufferRelease();
    sscop->_VT_CC = 1;
    sscop->_VT_SQ++;
    sscop->initializeVR_MR();
    sscop->sendBGNpdu(messenger_->getSSCOP_UU());
    sscop->_timerCC.start();
    sscop->changeToOutgoingConnectionPendingState();
    return;
}

void sscopOutgoingDisconnectionPending :: aaRETRIEVEreqAct(
    aaRETRIEVEreq *messenger_,
    pfProtocol *protocol_) const
{
    sscopProtocol *sscop = dynamic_cast<sscopProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(sscop);
    sscop->dataRetrieval(messenger_->getRetrievalNumber());
    return;
}


//
// Functions: SSCOP PDU input methods
//
// Description:
//     Actions in SSCOP state 4 for received PDUs
//

void sscopOutgoingDisconnectionPending :: sscopBGNpduAct(
    sscopBGN_PDU *messenger_,
    sscopProtocol *protocol_) const
{
    if (protocol_->detectRetransmission(messenger_->getN_SQ()) == 0)
    {
        protocol_->_timerCC.stop();
        protocol_->_VT_MS = messenger_->getN_MR();
        protocol_->sendAaRELEASEconf();
        protocol_->sendAaESTABLISHind(messenger_->getSSCOP_UU());
        protocol_->changeToIncomingConnectionPendingState();
    }
    else
    {
        pfFrame emptyFrame;
        protocol_->sendBGAKpdu(emptyFrame);
        protocol_->resendLastENDpdu();
    }
    return;
}

void sscopOutgoingDisconnectionPending :: sscopBGREJpduAct(
    sscopBGREJ_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->_timerCC.stop();
    protocol_->sendAaRELEASEconf();
    protocol_->changeToIdleState();
    return;
}

void sscopOutgoingDisconnectionPending :: sscopENDpduAct(
    sscopEND_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->_timerCC.stop();
    protocol_->sendENDAKpdu();
    protocol_->sendAaRELEASEconf();
    protocol_->changeToIdleState();
    return;
}

void sscopOutgoingDisconnectionPending :: sscopENDAKpduAct(
    sscopENDAK_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->_timerCC.stop();
    protocol_->sendAaRELEASEconf();
    protocol_->changeToIdleState();
    return;
}


//
// Functions: Timeout input methods
//
// Description:
//     Actions in SSCOP state 4 for timer timeouts
//

void sscopOutgoingDisconnectionPending :: sscopCCtimeoutAct(
    sscopProtocol *protocol_) const
{
    if (protocol_->_VT_CC >= protocol_->_maxCC)
    {
        protocol_->sendErrorReleaseEND(SSCOP_ERROR_O);
        protocol_->sendAaRELEASEconf();
        protocol_->changeToIdleState();
    }
    else
    {
        protocol_->_VT_CC++;
        protocol_->resendLastENDpdu();
        protocol_->_timerCC.start();
    }
    return;
}
