//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / UNI
//
//File: unirrnstate.cpp
//
//Version: $Revision: 1.12 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/14 06:56:32 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Jari Katajavuori
//
//Description:
//      RRN (Reset Response) protocol states. 
//
//Copyright:
//
//
//Licence:
//
//
//History: 

#include "unirrnstate.h"

#include "pf/protocol.h"

#include "unidefs.h"
#include "unistrings.h"
#include "unirrnprotocol.h"
#include "unierrorinfo.h"

//
// Class: uniRRNState
//
// Method: contructor & destructor
//
// Description:
//      

uniRRNState :: uniRRNState(void)
    : uniDownRRNInputs(),
      uniRRNMessageInputs(),
      uniStatusMessageInputs(),
      uniRRNTimeoutInputs(),
      pfState()
{
    return;
}

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

//
// Method: uni*Act
//
// Description:
//      Dummy actions.
//

void uniRRNState :: uniRESETrespAct(uniRESETresp *,
                                    pfProtocol *)
{
    return;
}

void uniRRNState :: uniRESET_ERRORrespAct(uniRESET_ERRORresp *,
                                          pfProtocol *)
{
    return;
}

void uniRRNState :: uniRESTARTpduAct(uniRESTARTpdu *,
                                     pfProtocol *)
{
    return;
}

void uniRRNState :: uniSTATUSpduAct(uniSTATUSpdu *,
                                    pfProtocol *)
{
    return;
}

void uniRRNState :: uniT317timeoutAct(pfProtocol *)
{
    return;
}

//------------------------------------------------------------------
// Class: uniRRNNullState
//

uniRRNNullState *uniRRNNullState :: _only = 0;

//
// Method: instance
//
// Description:
//      This static method returns the only instance of the current class.
//

uniRRNNullState *uniRRNNullState :: instance(void)
{
    if (_only == 0)
    {
        _only = new uniRRNNullState;
    }
    return _only;
}

//
// Method: contructor & destructor
//
// Description:
//

uniRRNNullState :: uniRRNNullState(void)
    : uniRRNState()
{
    return;
}

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

//
// Method: uniRESTARTpduAct
//
// Description:
//      RESTART pdu received. Inform CC.
//

void uniRRNNullState :: uniRESTARTpduAct(
    uniRESTARTpdu *message_,
    pfProtocol *protocol_)
{
    uniRRNProtocol *protocol = (uniRRNProtocol *)protocol_;
#if 0
    protocol->sendRESETind(message_);
    protocol->startTimer(uniT317Str);
    protocol->changeToRestartState();
#else
#include <autoptr.h>
    auto_ptr<uniRESETresp> message(uniRESETresp::create());
    message->copyIfPresent(*message_, uniRestartIndicatorStr); 
    message->copyIfPresent(*message_, uniConnectionIdentifierStr); 
    protocol->sendRESTART_ACKpdu(message.get());
#endif
    return;
}

//------------------------------------------------------------------
// Class: uniRRNRestartState
//

uniRRNRestartState *uniRRNRestartState :: _only = 0;

//
// Method: instance
//
// Description:
//      This static method returns the only instance of the current class.
//

uniRRNRestartState *uniRRNRestartState :: instance(void)
{
    if (_only == 0)
    {
        _only = new uniRRNRestartState;
    }
    return _only;
}

//
// Method: contructor & destructor
//
// Description:
//

uniRRNRestartState :: uniRRNRestartState(void)
    : uniRRNState()
{
    return;
}

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

//
// Method: uniRESETrespAct
//
// Description:
//      Response from CC received, Reset performed.
//

void uniRRNRestartState :: uniRESETrespAct(
    uniRESETresp *message_,
    pfProtocol *protocol_)
{
    uniRRNProtocol *protocol = dynamic_cast<uniRRNProtocol *>(protocol_);
    protocol->stopTimer(uniT317Str);
    protocol->sendRESTART_ACKpdu(message_);
    protocol->changeToNullState();
    return;
}

//
// Method: uniRESET_ERRORrespAct
//
// Description:
//      RESET_ERRORresp message informs that reset can't be performed.
//      Inform opposite (requesting) party with STATUS pdu.
//

void uniRRNRestartState :: uniRESET_ERRORrespAct(
    uniRESET_ERRORresp *message_,
    pfProtocol *protocol_)
{
    uniRRNProtocol *protocol = dynamic_cast<uniRRNProtocol *>(protocol_);
    // ++ TODO ++ Status option support?
    uniErrorInfo errorInfo(uniCauseValue_IdentifiedChannelDoesNotExist);
    uniSTATUSpdu *message =
        uniSTATUSpdu::buildReply(message_, errorInfo, uniState_Restart);
    protocol->toA(message);
    return;
}

//
// Method: uniRESTARTpdu
//
// Description:
//      Too many RESTARTs. RRN can handle only one in time.
//

void uniRRNRestartState :: uniRESTARTpduAct(
    uniRESTARTpdu *message_,
    pfProtocol *protocol_)
{
    uniRRNProtocol *protocol = dynamic_cast<uniRRNProtocol *>(protocol_);
    uniErrorInfo errorInfo(uniCauseValue_MessageNotCompatibleWithCallState);
    uniSTATUSpdu *message =
        uniSTATUSpdu::buildReply(message_, errorInfo, uniState_Restart);
    protocol->toA(message);
    return;
}

//
// Method: uniSTATUSpduAct
// 
// Description:
//      

void uniRRNRestartState :: uniSTATUSpduAct(
    uniSTATUSpdu *,
    pfProtocol *protocol_)
{
    uniRRNProtocol *protocol = dynamic_cast<uniRRNProtocol *>(protocol_);
    if (0 /*if CS not compatible*/)
    {
        protocol->sendRESET_ERRORind(
            uniResetError_PeerIncompatibleState,
            uniState_Restart);
    }
    return;
}

//
// Method: uniT317timeoutAct
//
// Description:
//      RESET not confirmed yet, inform upper protocols of giving up.
//

void uniRRNRestartState :: uniT317timeoutAct(
    pfProtocol *protocol_)
{
    uniRRNProtocol *protocol = dynamic_cast<uniRRNProtocol *>(protocol_);
    protocol->sendRESET_ERRORind(uniResetError_NoResetConfirm,
                                 uniState_Restart);
    protocol->changeToNullState();
    return;
}

