//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / UNI
//
//File: unistate_n0.cpp
//
//Version: $Revision: 1.17 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/14 06:56:33 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Jari Katajavuori
//
//Description:
//      State Null (N0)
//
//Copyright:
//
//
//Licence:
//
//
//History: 

#include "unistate_n0.h"

#include "iface/sigif/sigdownprimitives.h"
#include "iface/sigif/sigupprimitives.h"

#include "unidefs.h"
#include "unistrings.h"
#include "uniprotocol.h"
#include "unipdu.h"
#include "uniprimitives.h"

uniNetworkNull *uniNetworkNull :: _only = 0;

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

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

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

void uniNetworkNull :: sigSETUPreqAct(sigSETUPreq *message_,
                                      pfProtocol *protocol_)
{
    uniProtocol *protocol = dynamic_cast<uniProtocol*>(protocol_);

#if 0
    // Choose mode: if Connection Identifier is present, this
    // must act like a network party.
    if (message_->isAvailable(uniConnectionIdentifierStr) != 0)
    {
        protocol->setNetworkMode();
    }
    else
    {
        protocol->setUserMode();
    }
#endif
    
    protocol->sendSETUPpduToCoOrd(message_); 
    protocol->setInteger(uniT303TimeoutsStr, 0);
    protocol->startTimer(uniT303Str);
    protocol->changeToCallPresentState();
    return;
};

void uniNetworkNull :: uniSETUPpduAct(uniSETUPpdu *message_,
                                      pfProtocol *protocol_)
{
    uniProtocol *protocol = dynamic_cast<uniProtocol*>(protocol_);
    protocol->verifyMessage(message_, uniState_CallInitiated);

#if 0
    // Choose mode: if Connection Identifier is present, the
    // other party is network, this acts like user.
    if (message_->isAvailable(uniConnectionIdentifierStr) != 0)
    {
        protocol->setUserMode();
    }
    else
    {
        protocol->setNetworkMode();
    }
#endif

    if (message_->isMultipointMessage() != 0)
    {
        if (message_->getInteger(uniEndpointReferenceStr) ==
            uniZeroEndpointReferenceAtTSide)
        {
            protocol->createMultipointConduits();
            protocol->saveSetupData(message_);
            protocol->sendSETUPindToCC(message_);
            protocol->changeToCallInitiatedState();
        }
        else
        {
            // ++TODO++ error: the first endpoint reference must be zero 
        }
    }
    else
    {
        protocol->createPointToPointConduits();
        protocol->sendSETUPindToCC(message_);
        protocol->changeToCallInitiatedState();
    }
    return;
}

void uniNetworkNull :: sigRELEASErespAct(sigRELEASEresp *,
                                         pfProtocol *protocol_)
{
    // When RELEASEresp is received, cc is ready for exit.
    uniProtocol *protocol = dynamic_cast<uniProtocol*>(protocol_);
    protocol->finalClearing();
    return;
}

// Following methods resets some inputs. This is because there is several
// inputs which are allowed anywhere except N0.

void uniNetworkNull :: sigRELEASEreqAct(sigRELEASEreq *,
                                        pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniCALL_PROCEEDINGpduAct(uniCALL_PROCEEDINGpdu *,
                                                pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniCONNECTpduAct(uniCONNECTpdu *,
                                        pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniCONNECT_ACKpduAct(uniCONNECT_ACKpdu *,
                                            pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniRELEASEpduAct(uniRELEASEpdu *,
                                        pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniRELEASE_COMPLETEpduAct(uniRELEASE_COMPLETEpdu *,
                                                 pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniSTATUSpduAct(uniSTATUSpdu *message_,
                                       pfProtocol *protocol_)
{
    uniProtocol *protocol = dynamic_cast<uniProtocol*>(protocol_);
    pfUlong cs =
        message_->getStorage(uniCallStateStr).getInteger(uniCallState_StateStr);
    if (cs != uniState_Null)
    {
        protocol->sendRELEASE_COMPLETEpduToCoOrd(
            uniCauseValue_MessageNotCompatibleWithCallState);
    }
    return;
}

void uniNetworkNull :: uniADD_PARTYpduAct(uniADD_PARTYpdu *,
                                          pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniADD_PARTY_ACKpduAct(uniADD_PARTY_ACKpdu *,
                                              pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniADD_PARTY_REJECTpduAct(uniADD_PARTY_REJECTpdu *,
                                                 pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniDROP_PARTYpduAct(uniDROP_PARTYpdu *,
                                           pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniDROP_PARTY_ACKpduAct(uniDROP_PARTY_ACKpdu *,
                                               pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniT322timeoutAct(pfProtocol *)
{
    return;
}

void uniNetworkNull :: uniTREMOVEDtimeoutAct(pfProtocol *protocol_)
{
    uniProtocol *protocol = dynamic_cast<uniProtocol*>(protocol_);
    protocol->setBooleanTrue(uniAllowFinalClearingStr);
    protocol->finalClearing();
    return;
}

