//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project
//
//File: gsmpadjacencyESTABstate.cpp
//
//State: $State: Exp $
//
//Version: $Revision: 1.12 $
//
//Date: $Date: 1998/12/16 16:57:24 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
// 
//Author:
//      Harri Sunila
//
//Description:
//      See corresponding header file
//
//Copyright:    
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999 
//      
//Licence:
//     
//
//History:
//
//

#include "gsmpadjacencyESTABstate.h"
#include "gsmpadjacencyprotocol.h"
#include "gsmpinternalmessages.h"
#include "pf/error.h"
#include "pf/debug.h"

gsmpAdjacencyESTABstate *gsmpAdjacencyESTABstate::_only = 0;

//
// Function: gsmpAdjacencyESTABstate
//
// Description:
//     Constructor
//

gsmpAdjacencyESTABstate :: gsmpAdjacencyESTABstate(void)
{
    return;
}

//
// Function: ~gsmpAdjacencyESTABstate
//
// Description:
//     Destructor
//

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

//
// Function: instance
//
// Description:  
//

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

//
// Function: gsmpAdjacencySYNCtimeoutAct
//
// Description:
//     Action if SYNC timeout occurs
//

void gsmpAdjacencyESTABstate :: gsmpAdjacencySYNCtimeoutAct(
    gsmpAdjacencyProtocol *protocol_)
{
    protocol_->startTimer();
    protocol_->releaseACKlock();
    protocol_->sendAdjacencyProtocolACKmessage();
    return;
}

//
// Function: gsmpAdjacencyResyncTimeoutAct
//
// Description:
//     Action if the synchronisation has been lost.
//

void gsmpAdjacencyESTABstate :: gsmpAdjacencyResyncTimeoutAct(
    gsmpAdjacencyProtocol *protocol_)
{
    debugUser("Adjacency Protocol: Lost of syncronization detected");
    resetTheLink(protocol_);
    protocol_->startRetryTimer();
    return;
}

//
// Function: gsmpAdjacencyProtocolSYNmessageAct
//
// Description:
//     Action for Adjacency Protocol SYN Message
//
  
void gsmpAdjacencyESTABstate :: gsmpAdjacencyProtocolSYNmessageAct(
    gsmpAdjacencyProtocolSYNmessage *message_,
    pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    protocol->stopResyncTimer();
    protocol->updateLastReceivedData(message_);
    protocol->startResyncTimer();
    protocol->sendAdjacencyProtocolACKmessage();
    return;
}

//
// Function: gsmpAdjacencyProtocolSYNACKmessageAct
//
// Description:
//     Action for Adjacency Protocol SYNACK Message
//

void gsmpAdjacencyESTABstate :: gsmpAdjacencyProtocolSYNACKmessageAct(
    gsmpAdjacencyProtocolSYNACKmessage *message_,
    pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    protocol->stopResyncTimer();
    protocol->updateLastReceivedData(message_);
    protocol->startResyncTimer();
    protocol->sendAdjacencyProtocolACKmessage();
    return;
}

//
// Function: gsmpAdjacencyProtocolACKmessageAct
//
// Description:
//     Action for Adjacency Protocol ACK Message
//

void gsmpAdjacencyESTABstate :: gsmpAdjacencyProtocolACKmessageAct(
    gsmpAdjacencyProtocolACKmessage *message_,
    pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    protocol->stopResyncTimer();
    protocol->updateLastReceivedData(message_);
    if ((protocol->conditionB(message_) &&
         protocol->conditionC(message_)) != 0)
    {
        protocol->sendAdjacencyProtocolACKmessage();
    }
    else // if ((protocol->B(message_) && protocol->C(message_)) == 0)
    {
        protocol->sendAdjacencyProtocolRSTACKmessage();
    }
    protocol->startResyncTimer();
    return;
}

//
// Function: gsmpAdjacencyProtocolRSTACKmessageAct
//
// Description:
//     Action for Adjacency Protocol RSTACK Message
//

void gsmpAdjacencyESTABstate :: gsmpAdjacencyProtocolRSTACKmessageAct(
    gsmpAdjacencyProtocolRSTACKmessage *message_,
    pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    protocol->stopResyncTimer();
    protocol->updateLastReceivedData(message_);
    if ((protocol->conditionA(message_) &&
         protocol->conditionC(message_)) != 0)
    {
        // Send gsmpLinkNotEstablished
        protocol->sendGsmpLinkNotEstablished();
        resetTheLink(protocol);
        protocol->startRetryTimer();
    }
    return;
}

//
// Function: sendNonAdjacencyMessage
//
// Description:
//     This method checks the result field from incoming GSMP Protocol Message.
//     If the result is GSMP_SUCCESS or GSMP_FAILURE, which implies the message
//     is a response, message will be send upwards, otherwise the message is a
//     request and will be send to the CPCS-Adapter
//


void gsmpAdjacencyESTABstate :: sendNonAdjacencyMessage(gsmpMessage *message_,
                                                        pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    if (message_->isResponse() != 0)
    {
        // send upwards
        protocol->toB(message_);
    }
    else
    {
        // send downwards
        protocol->sendGsmpProtocolMessage(message_);
    }
    return;
}
