//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / SSCOP protocol
//
//File: sscopstate6.cpp
//
//Version: $Revision: 1.10 $
//
//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 "sscopstate6.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: sscopIncomingResynchronizationPending :: _only
// Function: sscopIncomingResynchronizationPending :: instance()
//
// Description:
//     Implements the singleton pattern used for actual states
//

sscopIncomingResynchronizationPending *
sscopIncomingResynchronizationPending :: _only = 0;

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


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

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


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

void sscopIncomingResynchronizationPending :: aaRELEASEreqAct(
    aaRELEASEreq *messenger_,
    pfProtocol *protocol_) const
{
    sscopProtocol *sscop = dynamic_cast<sscopProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(sscop);
    sscop->_VT_CC = 1;
    sscop->sendENDpdu(messenger_->getSSCOP_UU(), SSCOP_RELEASE_USER);
    sscop->_timerCC.start();
    sscop->changeToOutgoingDisconnectionPendingState();
    return;
}

void sscopIncomingResynchronizationPending :: aaRESYNCrespAct(
    aaRESYNCresp *,
    pfProtocol *protocol_) const
{
    sscopProtocol *sscop = dynamic_cast<sscopProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(sscop);
    sscop->initializeVR_MR();
    sscop->sendRSAKpdu();
    sscop->clearTransmitter();
    sscop->initializeStateVariables();
    sscop->setDataTransferTimers();
    sscop->changeToDataTransferReadyState();
    return;
}

void sscopIncomingResynchronizationPending :: 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 6 for received PDUs
//

void sscopIncomingResynchronizationPending :: sscopBGNpduAct(
    sscopBGN_PDU *messenger_,
    sscopProtocol *protocol_) const
{
    if (protocol_->detectRetransmission(messenger_->getN_SQ()) != 0)
    {
        protocol_->sendErrorReleaseEND(SSCOP_ERROR_B);
    }
    else
    {
        protocol_->_VT_MS = messenger_->getN_MR();
        pfFrame sscop_uu;
        protocol_->sendAaRELEASEind(sscop_uu, SSCOP_RELEASE_USER);
        protocol_->sendAaESTABLISHind(messenger_->getSSCOP_UU());
        protocol_->changeToIncomingConnectionPendingState();
    }
    return;
}

void sscopIncomingResynchronizationPending :: sscopBGAKpduAct(
    sscopBGAK_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_C);
    return;
}

void sscopIncomingResynchronizationPending :: sscopBGREJpduAct(
    sscopBGREJ_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_D, 0, 1);
    protocol_->changeToIdleState();
    return;
}

void sscopIncomingResynchronizationPending :: sscopENDpduAct(
    sscopEND_PDU *messenger_,
    sscopProtocol *protocol_) const
{
    protocol_->sendENDAKpdu();
    protocol_->sendAaRELEASEind(messenger_->getSSCOP_UU(),
                                SSCOP_RELEASE_USER);
    protocol_->changeToIdleState();
    return;
}

void sscopIncomingResynchronizationPending :: sscopENDAKpduAct(
    sscopENDAK_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_F, 0, 1);
    protocol_->changeToIdleState();
    return;
}

void sscopIncomingResynchronizationPending :: sscopRSpduAct(
    sscopRS_PDU *messenger_,
    sscopProtocol *protocol_) const
{
    if (protocol_->detectRetransmission(messenger_->getN_SQ()) == 0)
    {
        protocol_->sendErrorReleaseEND(SSCOP_ERROR_J);
    }
    return;
}

void sscopIncomingResynchronizationPending :: sscopRSAKpduAct(
    sscopRSAK_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_K);
    return;
}

void sscopIncomingResynchronizationPending :: sscopERpduAct(
    sscopER_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_L);
    return;
}

void sscopIncomingResynchronizationPending :: sscopERAKpduAct(
    sscopERAK_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_M);
    return;
}

void sscopIncomingResynchronizationPending :: sscopSDpduAct(
    sscopSD_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_A, 0, 1, 1);
    protocol_->changeToIdleState();
    return;
}

void sscopIncomingResynchronizationPending :: sscopPOLLpduAct(
    sscopPOLL_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_G, 0, 1, 1);
    protocol_->changeToIdleState();
    return;
}

void sscopIncomingResynchronizationPending :: sscopSTATpduAct(
    sscopSTAT_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_H, 0, 1, 1);
    protocol_->changeToIdleState();
    return;
}

void sscopIncomingResynchronizationPending :: sscopUSTATpduAct(
    sscopUSTAT_PDU *,
    sscopProtocol *protocol_) const
{
    protocol_->sendErrorReleaseEND(SSCOP_ERROR_I, 0, 1, 1);
    protocol_->changeToIdleState();
    return;
}
