//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / SSCOP protocol
//
//File: sscopstate.cpp
//
//Version: $Revision: 1.28 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/03/11 18:53:55 $
//
//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 "pf/error.h"
#include "sscopstate.h"
#include "sscoppdu.h"
#include "sscopprotocol.h"
#include "sscopinternals.h"
#include "protocol/saal/saal.h"

sscopState :: sscopState(void)
    : pfState(),
      aaDownInputs(),
      cpcsUpInputs()
{
    return;
}


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


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

void sscopState :: aaESTABLISHreqAct(aaESTABLISHreq *, pfProtocol *) const
{
    return;
}


void sscopState :: aaESTABLISHrespAct(aaESTABLISHresp *, pfProtocol *) const
{
    return;
}


void sscopState :: aaRELEASEreqAct(aaRELEASEreq *, pfProtocol *) const
{
    return;
}


void sscopState :: aaDATAreqAct(aaDATAreq *, pfProtocol *) const
{
    return;
}


void sscopState :: aaRESYNCreqAct(aaRESYNCreq *, pfProtocol *) const
{
    return;
}


void sscopState :: aaRESYNCrespAct(aaRESYNCresp *, pfProtocol *) const
{
    return;
}


void sscopState :: aaRECOVERrespAct(aaRECOVERresp *, pfProtocol *) const
{
    return;
}


void sscopState :: aaUNITDATAreqAct(
    aaUNITDATAreq *messenger_,
    pfProtocol *protocol_) const
{
    sscopProtocol *sscop = dynamic_cast<sscopProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(sscop);
    sscop->_unassuredQueue.push_back(messenger_->getMessageUnit());
    sscopUDpduQueuedUp *messenger = new sscopUDpduQueuedUp;
    sscop->accept(messenger);
    return;
}


void sscopState :: aaRETRIEVEreqAct(aaRETRIEVEreq *, pfProtocol *) const
{
    return;
}


//
// Function: sscopState :: maaUNITDATAreqAct
//
// Description:
//     Default action for incoming management data request. Puts the
//     received MAA-UNITDATA.request messenger into management queue
//     and generates an internal event that will handle the request
//     when the event is processed.
//

void sscopState :: maaUNITDATAreqAct(maaUNITDATAreq *, pfProtocol *) const
{
// ++TODO++ Waiting for implementation of MAA-messengers
//    sscopProtocol *sscop = (sscopProtocol *) protocol_;
//    sscop->_managementQueue.push_back(messenger_->getMessageUnit());
//    sscopMDpduQueuedUp *messenger = new sscopMDpduQueuedUp;
//    sscop->accept(messenger);

    return;
}


//
// Function: sscopState :: cpcsUNITDATAindAct
//
// Description:
//     Default action for incoming CPCS data indication primitive.
//     Creates a PDU messenger from the received data primitive.
//     All checks will get done in sscopPDUmessenger::create() and
//     the created PDU is of type sscopINVALID_PDU if any errors
//     occured. The new PDU messenger is put to the head of the
//     SSCOP message queue and control is returned to the scheduler.
//

void sscopState :: cpcsUNITDATAindAct(
    cpcsUNITDATAind *messenger_,
    pfProtocol *protocol_) const
{
    sscopProtocol *sscop = dynamic_cast<sscopProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(sscop);
    sscopPDUmessenger *pdu =
        sscopPDUmessenger::create(messenger_->getInterfaceData(),
                                  sscop->_maxSDUsize,
                                  sscop->_maxUUsize);
    pdu->setSaveMethodToHead();
    protocol_->accept(pdu);
    return;
}


//
// Functions: SSCOP PDU input methods
//
// Description:
//    Default methods for received peer PDUs.
//

void sscopState :: sscopBGNpduAct(sscopBGN_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopBGAKpduAct(sscopBGAK_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopBGREJpduAct(sscopBGREJ_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopENDpduAct(sscopEND_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopENDAKpduAct(sscopENDAK_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopRSpduAct(sscopRS_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopRSAKpduAct(sscopRSAK_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopERpduAct(sscopER_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopERAKpduAct(sscopERAK_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopSDpduAct(sscopSD_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopPOLLpduAct(sscopPOLL_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopSTATpduAct(sscopSTAT_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopUSTATpduAct(sscopUSTAT_PDU *, sscopProtocol *) const
{
    return;
}


void sscopState :: sscopUDpduAct(
    sscopUD_PDU *messenger_,
    sscopProtocol *protocol_) const
{
    debugFrame("TCN", messenger_->getInformation());
    //protocol_->sendAaUNITDATAind(messenger_->getInformation());
    return;
}


void sscopState :: sscopMDpduAct(
    sscopMD_PDU *messenger_,
    sscopProtocol *protocol_) const
{
    protocol_->sendMaaUNITDATAind(messenger_->getInformation());
    return;
}


void sscopState :: sscopINVALIDpduAct(
    sscopINVALID_PDU *messenger_,
    sscopProtocol *protocol_) const
{
    if (messenger_->getErrorCode() == SSCOP_PDU_INVALID_LENGTH)
    {
        protocol_->sendMaaERRORind(SSCOP_ERROR_U);
    }
    return;
}


//
// Functions: SSCOP timer timeout input methods
//
// Description:
//     Default actions for SSCOP timer timeouts.
//

void sscopState :: sscopCCtimeoutAct(sscopProtocol *) const
{
    return;
}


void sscopState :: sscopPOLLtimeoutAct(sscopProtocol *) const
{
    return;
}


void sscopState :: sscopKEEPALIVEtimeoutAct(sscopProtocol *) const
{
    return;
}


void sscopState :: sscopNORESPONSEtimeoutAct(sscopProtocol *) const
{
    return;
}


void sscopState :: sscopIDLEtimeoutAct(sscopProtocol *) const
{
    return;
}


//
// Functions: SSCOP internal event input methods
//
// Description:
//     Default actions for SSCOP internal events.1
//

void sscopState :: sscopSDpduQueuedUpAct(sscopProtocol *) const
{
    return;
}


void sscopState :: sscopUDpduQueuedUpAct(sscopProtocol *protocol_) const
{
    if (protocol_->lowerLayerIsBusy() == 0)
    {
        pfFrame data = protocol_->_unassuredQueue.front();
        protocol_->_unassuredQueue.pop_front();
        protocol_->sendUDpdu(data);
    }
    else
    {
        sscopUDpduQueuedUp *messenger = new sscopUDpduQueuedUp;
        protocol_->accept(messenger);
    }
    return;
}


void sscopState :: sscopMDpduQueuedUpAct(sscopProtocol *protocol_) const
{
    if (protocol_->lowerLayerIsBusy() == 0)
    {
        pfFrame data = protocol_->_managementQueue.front();
        protocol_->_managementQueue.pop_front();
        protocol_->sendMDpdu(data);
    }
    else
    {
        sscopMDpduQueuedUp *messenger = new sscopMDpduQueuedUp;
        protocol_->accept(messenger);
    }

    return;
}
