//Editor-Info: -*- C++ -*-
//
//Subject: GSMP
//
//File: gsmpadjacencyprotocolmessage.h
//
//Version: $Revision: 1.6 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/16 16:57:24 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Harri Sunila
//
//Description:
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//      
//Licence:
//     
//
//History:
//

#include "gsmpadjacencyprotocolmessage.h"
#include "gsmpexceptions.h"
#include "pf/error.h"

//
// Function: gsmpAdjacencyProtocolMessage
//
// Description:
//     Default constructor
//

gsmpAdjacencyProtocolMessage :: gsmpAdjacencyProtocolMessage(void)
    : gsmpMessage(),
      _senderName(),
      _receiverName(),
      _senderPort(0),
      _receiverPort(0),
      _senderInstance(0),
      _receiverInstance(0)
{
    _messageType = GSMP_ADJACENCY_MESSAGE;
    _result = GSMP_ADJACENCY_RESULT;
    return;
}

//
// Function: gsmpAdjacencyProtocolMessage 
//
// Description: 
//     Constructor
//

gsmpAdjacencyProtocolMessage :: gsmpAdjacencyProtocolMessage(
    string &senderName_,
    string &receiverName_,
    pfUlong senderPort_,
    pfUlong receiverPort_,
    pfUlong senderInstance_,
    pfUlong receiverInstance_)
    : gsmpMessage(),
      _senderName(senderName_),
      _receiverName(receiverName_),
      _senderPort(senderPort_),
      _receiverPort(receiverPort_),
      _senderInstance(senderInstance_),
      _receiverInstance(receiverInstance_)
{
    _messageType = GSMP_ADJACENCY_MESSAGE;
    _result = GSMP_ADJACENCY_RESULT;
    return;
}

//
// Function: gsmpAdjacencyProtocolMessage
//
// Description:  
//     Copy constructor

gsmpAdjacencyProtocolMessage::gsmpAdjacencyProtocolMessage(
    const gsmpAdjacencyProtocolMessage &other_)
    : gsmpMessage(other_),
      _senderName(other_._senderName),
      _receiverName(other_._receiverName),
      _senderPort(other_._senderPort),
      _receiverPort(other_._receiverPort),
      _senderInstance(other_._senderInstance),
      _receiverInstance(other_._receiverInstance)
{
    return;
}

//
// Function: ~gsmpAdjacencyProtocolMessage 
//
// Description:  
//     Destructor
//

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

//
// Function: clone
//
// Description:  
//

gsmpAdjacencyProtocolMessage *gsmpAdjacencyProtocolMessage :: clone(void)
{
    gsmpAdjacencyProtocolMessage *message = 
        new gsmpAdjacencyProtocolMessage(*this);
    return message;
}

//
// Function: encodeFrame
//
// Description:
//     Encode the information of the message into the _frame
//

pfFrame gsmpAdjacencyProtocolMessage :: encodeFrame(void)
{
    pfUlong i;
    _frame.clear();
    _frame.putLast(_version);
    _frame.putLast(_messageType);
    _frame.putLast(_result);
    _frame.putLast(_code);
    try
    {
        if (_senderName.length() != gsmpMessage::GSMP_SWITCH_NAME_LENGTH)
        {
            throw gsmpInvalidLengthException(PF_EX_INFO);
        }
        else
        {
            for (i = 0; i < gsmpMessage::GSMP_SWITCH_NAME_LENGTH; i++)
            {
                _frame.putLast(_senderName[i]);
            }
        }
        if (_receiverName.length() != gsmpMessage::GSMP_SWITCH_NAME_LENGTH)
        {
            for (i = 0; i < gsmpMessage::GSMP_SWITCH_NAME_LENGTH; i++)
            {
                _frame.putLast(0);
            }
        }
        else
        {
            for (i = 0; i < gsmpMessage::GSMP_SWITCH_NAME_LENGTH; i++)
            {
                _frame.putLast(_receiverName[i]);
            }
        }
    }
    catch (...)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    _frame.putLast32bit(_senderPort);
    _frame.putLast32bit(_receiverPort);
    _frame.putLast32bit(_senderInstance);
    _frame.putLast32bit(_receiverInstance);
    return _frame;
}

//
// Function: decodeFrame
//
// Description:
//     Decode the frame to an adjacency protocol message

void gsmpAdjacencyProtocolMessage :: decodeFrame(pfFrame &frame_)
{
    pfUlong i;
    _frame = frame_;
    _version = frame_.getFirst();
    _messageType = frame_.getFirst();
    _result = frame_.getFirst();
    _code = frame_.getFirst();
    string name("empty!");  // String-class feature. String length is constant.
    for (i = 0; i < gsmpMessage::GSMP_SWITCH_NAME_LENGTH; i++)
    {
        name[i] = frame_.getFirst();
    }
    _senderName = name;
    for (i = 0; i < gsmpMessage::GSMP_SWITCH_NAME_LENGTH; i++)
    {
        name[i] = frame_.getFirst();
    }
    _receiverName = name;
    _senderPort = frame_.getFirst32bit();
    _receiverPort = frame_.getFirst32bit();
    _senderInstance = frame_.getFirst32bit();
    _receiverInstance = frame_.getFirst32bit();
    
    // If frame is not empty, some kind of decoding error has occured

    if (frame_.length() != 0)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    return;
}

//
// Functions: Get
//
// Description:
//     These methods return the data of the message

string gsmpAdjacencyProtocolMessage :: getSenderName(void) const
{
    return _senderName;
}

string gsmpAdjacencyProtocolMessage :: getReceiverName(void) const
{
    return _receiverName;
}

pfUlong gsmpAdjacencyProtocolMessage :: getSenderPort(void) const
{
    return _senderPort;
}

pfUlong gsmpAdjacencyProtocolMessage :: getReceiverPort(void) const
{
    return _receiverPort;
}

pfUlong gsmpAdjacencyProtocolMessage :: getSenderInstance(void) const
{
    return _senderInstance;
}
pfUlong gsmpAdjacencyProtocolMessage :: getReceiverInstance(void) const
{
    return _receiverInstance;
}

//
// Class: gsmpAdjacencyProtocolSYNmessage
//
// Description:
//     Class for GSMP Adjacency Protocol SYN messages  
//

gsmpAdjacencyProtocolSYNmessage :: gsmpAdjacencyProtocolSYNmessage(void)
    : gsmpAdjacencyProtocolMessage()
{
    _code = gsmpAdjacencyProtocolMessage::SYN;
    return;
}

gsmpAdjacencyProtocolSYNmessage :: gsmpAdjacencyProtocolSYNmessage(
    string &senderName_,
    string &receiverName_,
    pfUlong senderPort_,
    pfUlong receiverPort_,
    pfUlong senderInstance_,
    pfUlong receiverInstance_)
    : gsmpAdjacencyProtocolMessage(senderName_,
				   receiverName_,
				   senderPort_,
				   receiverPort_,
				   senderInstance_,
				   receiverInstance_)
{
    _code = gsmpAdjacencyProtocolMessage::SYN;
    return;
}

gsmpAdjacencyProtocolSYNmessage :: gsmpAdjacencyProtocolSYNmessage(
    const gsmpAdjacencyProtocolSYNmessage &other_)
    : gsmpAdjacencyProtocolMessage(other_)
{
    return;
}

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

//
// Function: clone 
//
// Description:
//

gsmpAdjacencyProtocolSYNmessage *gsmpAdjacencyProtocolSYNmessage :: clone(void)
{
    gsmpAdjacencyProtocolSYNmessage *message = 
        new gsmpAdjacencyProtocolSYNmessage(*this);
    return message;
}

//
// Function: apply
//
// Description:  
//

void gsmpAdjacencyProtocolSYNmessage :: apply(pfState *state_,
					      pfProtocol *protocol_)
{
    gsmpAdjacencyState *state = dynamic_cast<gsmpAdjacencyState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpAdjacencyProtocolSYNmessageAct(this, protocol_); 
    return;
}

//
// Class: gsmpAdjacencyProtocolSYNACKmessage
//
// Description:
//     Class for GSMP Adjacency Protocol SYNACK messages  
//

gsmpAdjacencyProtocolSYNACKmessage :: gsmpAdjacencyProtocolSYNACKmessage(void)
    : gsmpAdjacencyProtocolMessage()
{
    _code = gsmpAdjacencyProtocolMessage::SYNACK;
    return;
}

gsmpAdjacencyProtocolSYNACKmessage :: gsmpAdjacencyProtocolSYNACKmessage(
    string &senderName_,
    string &receiverName_,
    pfUlong senderPort_,
    pfUlong receiverPort_,
    pfUlong senderInstance_,
    pfUlong receiverInstance_)
    : gsmpAdjacencyProtocolMessage(senderName_,
				   receiverName_,
				   senderPort_,
				   receiverPort_,
				   senderInstance_,
				   receiverInstance_)
{
    _code = gsmpAdjacencyProtocolMessage::SYNACK;
    return;
}

gsmpAdjacencyProtocolSYNACKmessage :: gsmpAdjacencyProtocolSYNACKmessage(
    const gsmpAdjacencyProtocolSYNACKmessage &other_)
    : gsmpAdjacencyProtocolMessage(other_)
{
    return;
}

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

//
// Function: clone 
//
// Description:  
//

gsmpAdjacencyProtocolSYNACKmessage
*gsmpAdjacencyProtocolSYNACKmessage :: clone(void)
{
    gsmpAdjacencyProtocolSYNACKmessage *message = 
        new gsmpAdjacencyProtocolSYNACKmessage(*this);
    return message;
}

//
// Function: apply
//
// Description:  
//

void gsmpAdjacencyProtocolSYNACKmessage :: apply(pfState *state_,
					      pfProtocol *protocol_)
{
    gsmpAdjacencyState *state = dynamic_cast<gsmpAdjacencyState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpAdjacencyProtocolSYNACKmessageAct(this, protocol_); 
    return;
}

//
// Class: gsmpAdjacencyProtocolACKmessage
//
// Description:
//     Class for GSMP Adjacency Protocol ACK messages  
//

gsmpAdjacencyProtocolACKmessage :: gsmpAdjacencyProtocolACKmessage(void)
    : gsmpAdjacencyProtocolMessage()
{
    _code = gsmpAdjacencyProtocolMessage::ACK;
    return;
}

gsmpAdjacencyProtocolACKmessage :: gsmpAdjacencyProtocolACKmessage(
    string &senderName_,
    string &receiverName_,
    pfUlong senderPort_,
    pfUlong receiverPort_,
    pfUlong senderInstance_,
    pfUlong receiverInstance_)
    : gsmpAdjacencyProtocolMessage(senderName_,
				   receiverName_,
				   senderPort_,
				   receiverPort_,
				   senderInstance_,
				   receiverInstance_)
{
    _code = gsmpAdjacencyProtocolMessage::ACK;
    return;
}

gsmpAdjacencyProtocolACKmessage :: gsmpAdjacencyProtocolACKmessage(
    const gsmpAdjacencyProtocolACKmessage &other_)
    : gsmpAdjacencyProtocolMessage(other_)
{
    return;
}

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

//
// Function: clone 
//
// Description:  
//

gsmpAdjacencyProtocolACKmessage *gsmpAdjacencyProtocolACKmessage :: clone(void)
{
    gsmpAdjacencyProtocolACKmessage *message = 
        new gsmpAdjacencyProtocolACKmessage(*this);
    return message;
}

//
// Function: apply
//
// Description:  
//

void gsmpAdjacencyProtocolACKmessage :: apply(pfState *state_,
					      pfProtocol *protocol_)
{
    gsmpAdjacencyState *state = dynamic_cast<gsmpAdjacencyState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpAdjacencyProtocolACKmessageAct(this, protocol_); 
    return;
}

//
// Class: gsmpAdjacencyProtocolRSTACKmessage
//
// Description:
//     Class for GSMP Adjacency Protocol RSTACK messages  
//

gsmpAdjacencyProtocolRSTACKmessage :: gsmpAdjacencyProtocolRSTACKmessage(void)
    : gsmpAdjacencyProtocolMessage()
{
    _code = gsmpAdjacencyProtocolMessage::RSTACK;
    return;
}

gsmpAdjacencyProtocolRSTACKmessage :: gsmpAdjacencyProtocolRSTACKmessage(
    string &senderName_,
    string &receiverName_,
    pfUlong senderPort_,
    pfUlong receiverPort_,
    pfUlong senderInstance_,
    pfUlong receiverInstance_)
    : gsmpAdjacencyProtocolMessage(senderName_,
				   receiverName_,
				   senderPort_,
				   receiverPort_,
				   senderInstance_,
				   receiverInstance_)
{
    _code = gsmpAdjacencyProtocolMessage::RSTACK;
    return;
}

gsmpAdjacencyProtocolRSTACKmessage :: gsmpAdjacencyProtocolRSTACKmessage(
    const gsmpAdjacencyProtocolRSTACKmessage &other_)
    : gsmpAdjacencyProtocolMessage(other_)
{
    return;
}

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

//
// Function: clone 
//
// Description:  
//

gsmpAdjacencyProtocolRSTACKmessage *
gsmpAdjacencyProtocolRSTACKmessage :: clone(void)
{
    gsmpAdjacencyProtocolRSTACKmessage *message = 
        new gsmpAdjacencyProtocolRSTACKmessage(*this);
    return message;
}

//
// Function: apply
//
// Description:  
//

void gsmpAdjacencyProtocolRSTACKmessage :: apply(pfState *state_,
					      pfProtocol *protocol_)
{
    gsmpAdjacencyState *state = dynamic_cast<gsmpAdjacencyState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpAdjacencyProtocolRSTACKmessageAct(this, protocol_); 
    return;
}
