//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / UNI
//
//File: unistate.cpp
//
//Version: $Revision: 1.15 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/22 14:36:58 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Jari Katajavuori
//      Sami Raatikainen (based on version 1.21)
//
//Description:
//      See corresponding header file (unistate.h).
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 

#include "unistate.h"
#include "iface/sigif/sigdownprimitives.h"
#include "iface/sigif/sigupprimitives.h"
#include "protocol/uni/unidefs.h"
#include "protocol/uni/unistrings.h"
#include "uniprotocol.h"
#include "unipdu.h"
#include "protocol/uni/uniprimitives.h"
#include "ie/callstate.h"
#include "pf/error.h"

uniState :: uniState(void)
    : uniUpRSNandRRNInputs(),
      uniUpInputs(),
      uniMessageInputs(),
      uniPMPInputs(),
      uniTimeoutInputs()
{
    return;
}

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

uniProtocol *uniState :: protocolCast(pfProtocol *protocol_) const
{
    uniProtocol *protocol = dynamic_cast<uniProtocol*>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    return protocol;
}


//
// Method: uni*Act
//
// Description:
//      Inputs inherited from uniUpRSNandRRNInputs (primitives)
//

//++TODO++ REMOVE THESE
void uniState :: uniRESET_ERRORindAct(uniRESET_ERRORind *message_,
                                      pfProtocol *protocol_)
{
    //uniProtocol *protocol = protocolCast(protocol_);
    //protocol->sendRESET_ERRORindToCC(message_);
    return;
}

void uniState :: uniRESETconfAct(uniRESETconf *message_,
                                 pfProtocol *protocol_)
{
    //uniProtocol *protocol = protocolCast(protocol_);
    //protocol->sendRESETconfToCC(message_);
    return;
}

void uniState :: uniRESETindAct(uniRESETind *message_,
                                pfProtocol *protocol_)
{
    //uniProtocol *protocol = protocolCast(protocol_);
    //protocol->sendRESETindToCC(message_);
    return;
}

//
// Method: uniLINK_*Act
//
// Description:
//      Inputs inherited from uniUpInputs (primitives)
//

void uniState :: uniLINK_ESTABLISHconfAct(uniLINK_ESTABLISHconf *,
                                          pfProtocol *)
{
    return;
}

void uniState :: uniLINK_ESTABLISHindAct(uniLINK_ESTABLISHind *,
                                         pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->statusEnquiry();
    return;
}

void uniState :: uniLINK_ESTABLISHerrorAct(uniLINK_ESTABLISHerror *,
                                           pfProtocol *)
{
    return;
}

void uniState :: uniLINK_RELEASEconfAct(uniLINK_RELEASEconf *,
                                        pfProtocol *)
{
    return;
}

void uniState :: uniLINK_RELEASEindAct(uniLINK_RELEASEind *,
                                       pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->clearCall(uniCauseValue_DestinationOutOfOrder);
    return;
}

//
// Method: uni*pduAct
//
// Description:
//      Inputs inherited from uniMessageInputs
//

//++TODO++ REMOVE THESE, some of them already removed, only on header side

void uniState :: uniNOTIFYpduAct(uniNOTIFYpdu *message_,
                                 pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    if (protocol->getBoolean(uniQ2931ConnectionFlagStr) == 0)
    {
        protocol->reportIncompatibleMessage(message_);
    }
    else
    {
        //++TODO++
    }
    return;
}

void uniState :: uniSTATUSpduAct(uniSTATUSpdu *message_,
                                 pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    pfUlong cs =
        message_->getStorage(uniCallStateStr).getInteger(uniCallState_StateStr);
    pfUlong cause =
        message_->getStorage(uniCauseStr).getInteger(uniCause_ValueStr);
    if (cs == ieCallState::callState_Null)
    {
        protocol->clearCall(cause);
    }
    else
    {        
        if (cause == uniCauseValue_ResponseToSTATUS_ENQUIRY)
        {
            protocol->stopTimer(uniT322Str);
        }
        
        if (protocol->isCompatibleState(cs) == 0)
        {
            protocol->startReleaseProcess(
                uniCauseValue_MessageNotCompatibleWithCallState);
        }
        else
        {
            if ((cause == uniCauseValue_MandatoryIEIsMissing) ||
                (cause == uniCauseValue_MessageTypeNonexistent) ||
                (cause == uniCauseValue_IENonexistent) ||
                (cause == uniCauseValue_InvalidIEContents) ||
                (cause == uniCauseValue_MessageNotCompatibleWithCallState))
            {
                protocol->startReleaseProcess(cause);
            }
        }
    }
    return;
}

void uniState :: uniSTATUS_ENQUIRYpduAct(uniSTATUS_ENQUIRYpdu *message_,
                                         pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->sendSTATUSpduToCoOrd(message_);
    
    return;
}

void uniState :: uniADD_PARTYpduAct(uniADD_PARTYpdu *message_,
                                    pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->reportIncompatibleMessage(message_);
    return;
}

void uniState :: uniADD_PARTY_ACKpduAct(uniADD_PARTY_ACKpdu *message_,
                                        pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->reportIncompatibleMessage(message_);
    return;
}

void uniState :: uniADD_PARTY_REJECTpduAct(uniADD_PARTY_REJECTpdu *message_,
                                           pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->reportIncompatibleMessage(message_);    
    return;
}

void uniState :: uniDROP_PARTYpduAct(uniDROP_PARTYpdu *message_,
                                     pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->reportIncompatibleMessage(message_);
    return;
}

void uniState :: uniDROP_PARTY_ACKpduAct(uniDROP_PARTY_ACKpdu *message_,
                                         pfProtocol *protocol_)
{
    uniProtocol *protocol = protocolCast(protocol_);
    protocol->reportIncompatibleMessage(message_);
    return;
}

//
// Methods: uni*PARTY*Act
//
// Description:
//      Inputs inherited from uniPMPInputs (primitives)
//

void uniState :: uniADD_PARTYreqAct(uniADD_PARTYreq *, pfProtocol *)
{
    return;
}

void uniState :: uniADD_PARTYrespAct(uniADD_PARTYresp *, pfProtocol *)
{
    return;
}

void uniState :: uniADD_PARTYerrorAct(uniADD_PARTYerror *, pfProtocol *)
{
    return;
}

void uniState :: uniDROP_PARTYreqAct(uniDROP_PARTYreq *, pfProtocol *)
{
    return;
}

void uniState :: uniDROP_PARTYrespAct(uniDROP_PARTYresp *, pfProtocol *)
{
    return;
}

void uniState :: uniSTATUSreqAct(uniSTATUSreq *, pfProtocol *)
{
    return;
}

void uniState :: uniSTATUSrespAct(uniSTATUSresp *, pfProtocol *)
{
    return;
}

//
// Methods: uni*timeoutAct
//
// Description:
//      Timer inputs
//

void uniState :: uniT310timeoutAct(pfProtocol *)
{
    return;
}

void uniState :: uniT313timeoutAct(pfProtocol *)
{
    return;
}

void uniState :: uniT322timeoutAct(pfProtocol *protocol_)
{    
    uniProtocol *protocol = protocolCast(protocol_);
    pfUlong timeouts = protocol->getInteger(uniT322TimeoutsStr);
    timeouts++;
    if (timeouts > uniMaxStatusEnquiriesSent)
    {
        protocol->clearCall(uniCauseValue_TemporaryFailure);
    }
    else
    {
        protocol->sendSTATUS_ENQUIRYpduToCoOrd();
        protocol->setInteger(uniT322TimeoutsStr, timeouts);
        protocol->startTimer(uniT322Str);
    }
    return;
}

void uniState :: uniTREMOVEDtimeoutAct(pfProtocol *)
{
    return;
}




