//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project
//
//File: gsmpadjacencySYNRCVDstate.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 "gsmpadjacencySYNRCVDstate.h"
#include "gsmpadjacencyprotocol.h"
#include "gsmpinternalmessages.h"
#include "pf/error.h"

gsmpAdjacencySYNRCVDstate *gsmpAdjacencySYNRCVDstate::_only = 0;

//
// Function: gsmpAdjacencySYNRCVDstate
//
// Description:
//     Constructor
//

gsmpAdjacencySYNRCVDstate :: gsmpAdjacencySYNRCVDstate(void)
{
    return;
}

//
// Function: ~gsmpAdjacencySYNRCVDstate 
//
// Description:
//     Destructor
//

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

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

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

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

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

//
// Function: gsmpAdjacencyRetryTimeoutAct
//
// Description:
//     Action if Adjcency Protocol Retry timeout occurs
//

void gsmpAdjacencySYNRCVDstate :: gsmpAdjacencyRetryTimeoutAct(
    gsmpAdjacencyProtocol *protocol_)
{
    protocol_->resyncFailed();
    return;
}

//
// Function: gsmpAdjacencyProtocolSYNmessageAct
//
// Description:
//     Action for Adjacency Protocol SYN Message
//

void gsmpAdjacencySYNRCVDstate :: gsmpAdjacencyProtocolSYNmessageAct(
    gsmpAdjacencyProtocolSYNmessage *message_,
    pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    protocol->updateLastReceivedData(message_);
    protocol->updatePeerVerifier(message_);
    protocol->sendAdjacencyProtocolSYNACKmessage();
    return;
}

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

void gsmpAdjacencySYNRCVDstate :: gsmpAdjacencyProtocolSYNACKmessageAct(
    gsmpAdjacencyProtocolSYNACKmessage *message_,
    pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    protocol->updateLastReceivedData(message_);
    if (protocol->conditionC(message_) != 0)
    {
        protocol->updatePeerVerifier(message_);
        protocol->sendAdjacencyProtocolACKmessage();
        protocol->toAdjacencyESTABstate();
        protocol->startTimer();
        protocol->startResyncTimer();
        protocol->stopRetryTimer();
        
        // Send gsmpLinkEstablished to GSMP
        protocol->sendGsmpLinkEstablished();
    }
    else // if ((protocol->conditionC(message_)) == 0)
    {
        protocol->sendAdjacencyProtocolRSTACKmessage();
    }
    return;
}

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

void gsmpAdjacencySYNRCVDstate :: gsmpAdjacencyProtocolACKmessageAct(
    gsmpAdjacencyProtocolACKmessage *message_,
    pfProtocol *protocol_)
{
    gsmpAdjacencyProtocol *protocol =
        dynamic_cast<gsmpAdjacencyProtocol *>(protocol_);
    THROW_IF_DYNAMIC_CAST_FAILED(protocol);
    protocol->updateLastReceivedData(message_);
    if ((protocol->conditionB(message_) &&
         protocol->conditionC(message_)) != 0)
    {
        protocol->sendAdjacencyProtocolACKmessage();
        protocol->toAdjacencyESTABstate();
        protocol->startResyncTimer();
        protocol->stopRetryTimer();

        // Send gsmpLinkEstablished to GSMP
        protocol->sendGsmpLinkEstablished();
    }
    else // if ((protocol->B(message_) && protocol->C(message_)) == 0) 
    {
        protocol->sendAdjacencyProtocolRSTACKmessage();
    }
    return;
}

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

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

//
// Function: sendNonAdjacencyMessage
//
// Description:
//     This method checks the result field from incoming GSMP Protocol Message.
//     Because link is not established, message will be discarded

void gsmpAdjacencySYNRCVDstate :: sendNonAdjacencyMessage(
    gsmpMessage *message_,
    pfProtocol *protocol_)
{
    return;
}
