//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / SAAL
// 
//File: saallink.cpp
//
//Version: $Revision: 1.10 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/11/19 15:01:28 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Timo Pärnänen
//
//Description:
//      See corresponding header file.
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 

#include "saallink.h"
#include "pf/device.h"
#include "pf/frame.h"
#include "pf/debug.h"

#include "protocol/saal/saal.h"
#include "protocol/cpcs/cpcsaadapter.h"
#include "protocol/cpcs/cpcsuadapter.h"

//
//Function: constructors
//
//Description:
//     Initialises the class members. Note that the constructor is
//     protected; it is intended to be called only by the create methods.
//
//     See also comments in header file and destructor (below).
//

saalLink :: saalLink(void)
    : _linkNumber(0),
      _bufferSize(SAAL_MAX_SDU_SIZE),
      _management(0),
      _cpcsProxy()
{
    _sscop = new sscopProtocol(this);
    _sscopProxy = pfConduit(_sscop);
    return;
}

saalLink :: saalLink(const saalLink &other_)
    : _linkNumber(other_._linkNumber),
      _bufferSize(other_._bufferSize),
      _cpcsProxy()
{   
    _sscop = new sscopProtocol(*other_._sscop, this);
    _sscopProxy = pfConduit(_sscop);
    return;
}

saalLink :: ~saalLink(void)
{
    _cpcsProxy.disconnect();
    _sscopProxy.disconnect();
    return;
}


void saalLink :: openATMConnection(int port_,
                                   int vpi_,
                                   int vci_)
{
   debugUser("-- Open ATM connection --");
   debugPfUlong("port", port_);
   debugPfUlong("VPI", vpi_);
   debugPfUlong("VCI", vci_);
    _cpcsProxy = cpcsATMAdapter::createATMConnection(port_,
                                                     vpi_,
                                                     vci_,
                                                     _bufferSize);
    return;
}

void saalLink :: openUDPConnection(string hostname_,
                                   int localPort_,
                                   int remotePort_)
{
    _cpcsProxy = cpcsUDPAdapter::createUDPConnection(hostname_,
                                                     localPort_,
                                                     remotePort_,
                                                     _bufferSize);
    return;
}

void saalLink :: setBufferSize(int bufferSize_)
{
    _bufferSize = bufferSize_;
    return;
}

//
// Functions: Set methods for SSCOP parameters
//
// Description:
//     These methods provide the interface to SSCOP protocol parameters.
//

void saalLink :: setMaxSDUsize(pfUlong SDUsize_)
{
    _sscop->setMaxSDUsize(SDUsize_);
    return;
}

void saalLink :: setMaxUUsize(pfUlong UUsize_)
{
    _sscop->setMaxUUsize(UUsize_);
    return;
}

void saalLink :: setMaxCC(pfUlong CC_)
{
    _sscop->setMaxCC(CC_);
    return;
}

void saalLink :: setMaxPD(pfUlong PD_)
{
    _sscop->setMaxPD(PD_);
    return;
}

void saalLink :: setCCtimeout(pfUlong msec_)
{
    _sscop->setCCtimeout(msec_);
    return;
}

void saalLink :: setKEEP_ALIVEtimeout(pfUlong msec_)
{
    _sscop->setKEEP_ALIVEtimeout(msec_);
    return;
}

void saalLink :: setNO_RESPONSEtimeout(pfUlong msec_)
{
    _sscop->setNO_RESPONSEtimeout(msec_);
    return;
}

void saalLink :: setPOLLtimeout(pfUlong msec_)
{
    _sscop->setPOLLtimeout(msec_);
    return;
}

void saalLink :: setIDLEtimeout(pfUlong msec_)
{
    _sscop->setIDLEtimeout(msec_);
    return;
}

//
// Functions: Imput methods for MAA-primitives
//
// Description:
//     These primitives are sent by SSCOP managed by this
//     instance of the saal UNI or NNI link.
//

void saalLink :: maaERRORindAct(sscopError code_, pfUlong count_)
{
    //++TODO++
    // Delegate error managament issues to _management object
    //
    debugUser("[SAAL Layer Management] Received MAA-ERROR.indication");
    debugUser("      Parameters: Error code      ");
    switch (code_)
    {
        case SSCOP_ERROR_A:
            debugUser("A (SD PDU)");
            break;
        case SSCOP_ERROR_B:
            debugUser("B (BGN PDU)");
            break;
        case SSCOP_ERROR_C:
            debugUser("C (BGAK PDU)");
            break;
        case SSCOP_ERROR_D:
            debugUser("D (BGREJ PDU)");
            break;
        case SSCOP_ERROR_E:
            debugUser("E (END PDU)");
            break;
        case SSCOP_ERROR_F:
            debugUser("F (ENDAK PDU)");
            break;
        case SSCOP_ERROR_G:
            debugUser("G (POLL PDU)");
            break;
        case SSCOP_ERROR_H:
            debugUser("H (STAT PDU)");
            break;
        case SSCOP_ERROR_I:
            debugUser("I (USTAT PDU)");
            break;
        case SSCOP_ERROR_J:
            debugUser("J (RS)");
            break;
        case SSCOP_ERROR_K:
            debugUser("K (RSAK PDU)");
            break;
        case SSCOP_ERROR_L:
            debugUser("L (ER)");
            break;
        case SSCOP_ERROR_M:
            debugUser("M (ERAK)");
            break;
        case SSCOP_ERROR_O:
            debugUser("O (VT(CC)>=MaxCC)");
            break;
        case SSCOP_ERROR_P:
            debugUser("P (Timer_NO_REPONSE expiry)");
            break;
        case SSCOP_ERROR_Q:
            debugUser("Q (SD or POLL, N(S) error)");
            break;
        case SSCOP_ERROR_R:
            debugUser("R (STAT N(PS) error)");
            break;
        case SSCOP_ERROR_S:
            debugUser("S (STAT N(R) or list elements error)");
            break;
        case SSCOP_ERROR_T:
            debugUser("T (USTAT N(R) or list elements error)");
            break;
        case SSCOP_ERROR_U:
            debugUser("U (PDU length violation)");
            break;
        case SSCOP_ERROR_V:
            debugUser("V (SD PDUs must be retransmitted)");
            break;
        case SSCOP_ERROR_W:
            debugUser("W (Lack of credit)");
            break;
        case SSCOP_ERROR_X:
            debugUser("X (Credit obtained)");
            break;
    }
    debugPfUlong("                  Count           ", count_);
    return;
}

void saalLink :: maaUNITDATAindAct(const pfFrame &frame_)
{
    //++TODO++
    // Delegate error managament issues to _management object
    //    
    debugUser("[SAAL Layer Management] Received MAA-UNITDATA.indication");
    debugFrame("      Frame: ", frame_);
    return;
}

void saalLink :: setLinkNumber(pfId linkNumber_)
{
    _linkNumber = linkNumber_;
    _sscopProxy.setId(linkNumber_);
    _cpcsProxy.setId(linkNumber_);
    return;
}

void saalLink :: connectProtocols(void)
{
    _sscopProxy.connectToA(_cpcsProxy);
    _cpcsProxy.connectToA(_sscopProxy);
    return;
}
