//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project
//
//File: 
//
//Version: $Revision: 1.1 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/08/03 11:40:43 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//
//
//Description:
//      See corresponding header file
//
//Copyright:
//
//
//Licence:
//
//
//History: 

#include "protocol/saal/connection.h"
#include "iface/cpcsif/cpcsupprimitives.h"
#include "iface/cpcsif/cpcsdownprimitives.h"
#include "gsnprotocol.h"
#include "gsnstate.h"

//
// Function: gsnProtocol
//
// Description:
//   Default Constructor - unnecessary?

gsnProtocol :: gsnProtocol(void)
    : _inputVPI(0),
      _inputVCI(0),
      _inputPort(0),
      _outputVPI(0),
      _outputVCI(0),
      _outputPort(0)
{
    // Huomaa, että esim. gsmpprotocol.h:ssa siirrytään suoraan idle-tilaan,
    // kun protokollan konstruktoria kutsutaan
    // Luodaanko adapterit ja avataanko yhteys tässä?

    return;
}

//
// Function: gsnProtocol
//
// Description:
//   Constructor initializes class data members
//   Adapters are also created here
//

gsnProtocol :: gsnProtocol(
    pfUlong inputVPI_,
    pfUlong inputVCI_,
    pfUlong inputPort_,
    pfUlong outputVPI_,
    pfUlong outputVCI_,
    pfUlong outputPort_)
    : _inputVPI(inputVPI_),
      _inputVCI(inputVCI_),
      _inputPort(inputPort_),
      _outputVPI(outputVPI_),
      _outputVCI(outputVCI_),
      _outputPort(outputPort_)
{
    _sideA = openConnection(inputVPI_,
                            inputVCI_,
                            inputPort_,
                            _inputConnection);
    _sideB = openConnection(outputVPI_,
                            outputVCI_,
                            outputPort_,
                            _outputConnection);

    pfConduit gsnProxy(this);

    _sideA.connectToA(gsnProxy);
    _sideB.connectToB(gsnProxy);

    changeState(gsnState::instance());
    
    return;
}

//
// Function: gsnProtocol
//
// Description:
//   Copy constructor
//

gsnProtocol :: gsnProtocol(const gsnProtocol &other_)
    : pfProtocol(other_),
      _inputVPI(other_._inputVPI),
      _inputVCI(other_._inputVPI),
      _inputPort(other_._inputPort),
      _outputVPI(other_._outputVPI),
      _outputVCI(other_._outputVCI),
      _outputPort(other_._outputPort)
{
    return;
}

gsnProtocol :: ~gsnProtocol(void)
{
    delete _inputConnection;
    delete _outputConnection;
    return;
}

//
// Function: createGsnProtocol
//
// Description:  
//     Katsottu esim. gsmpprotocol.h:sta. *Ei* toteutettu throw exceptionia
//

pfConduit gsnProtocol :: createGsnProtocol(
    pfUlong inputVCI_,
    pfUlong inputVPI_,
    pfUlong inputPort_,
    pfUlong outputVPI_,
    pfUlong outputVCI_,
    pfUlong outputPort_)
{
    
    gsnProtocol *protocol = new gsnProtocol(inputVPI_,
                                           inputVCI_,
                                           inputPort_,
                                           outputVPI_,
                                           outputVCI_,
                                           outputPort_);

    pfConduit conduit = pfConduit(protocol);
    return conduit;
}

//
// Function: cloneImplementation
//
// Description:  
//     Katsottu esim. gsmpprotocol.h:sta. *Ei* toteutettu throw exceptionia
//

pfProtocol *gsnProtocol :: cloneImplementation(void)
{
    pfProtocol *newProtocol = new gsnProtocol(*this);

    return newProtocol;
}

//
// Function: switchData
//
// Description:  
//  vaihtaa datan annetusta cpcsUNITDATAind parametrista lähtevään
//  cpcsUNITDATAreq muuttujaan
//

cpcsUNITDATAreq *gsnProtocol :: switchData(cpcsUNITDATAind *messenger_) const
{
    cpcsUNITDATAreq *messenger = new cpcsUNITDATAreq;

    messenger->setInterfaceData(messenger_->getInterfaceData());
    messenger->setLossPriority(messenger_->getLossPriority());
    messenger->setCongestionIndication(messenger_->getCongestionIndication());
    messenger->setCPCS_UU(messenger_->getCPCS_UU());

    return messenger;
}

//
// Function: openConnection
//
// Description:
//   Avaa saalConnection yhteyden ja palauttaa proxyn siihen
//   Pitäisikö nyt pistää luokkaan datajäseniksi input- ja output
//   saalConnection -tyyppiset muuttujat, jotta päästäisiin käsiksi
//   ko. adaptereihin closeConnection -vaiheessa?
//

pfConduit gsnProtocol :: openConnection(pfUlong port_,
                                        pfUlong VPI_,
                                        pfUlong VCI_,
                                        saalConnection *saal_)    
{
    saal_ = saalConnection::createCPCSConnection(port_);
    saal_->openATMConnection(port_, VPI_, VCI_, SAAL_MAX_SDU_SIZE);

    pfConduit cpcsProxy = saal_->getConduit();
    return cpcsProxy;
}

//
// Function: release
//
// Description:
//   Method to disconnect cpcs-proxies.
//   _sideA/B.disconnect() -method is invoked to disconnect protocol.
//   closeConnection() -method is invoked from the saalConnection to
//   close and destroy its proxies.
//   

void gsnProtocol :: release(void)
{

    _sideA.disconnect();
    _sideB.disconnect();
    _inputConnection->closeConnection();
    _outputConnection->closeConnection();
    
    return;
}





