//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project
//
//File: nnilink.cpp
//
//Version: $Revision: 1.11 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/11/19 12:34:46 $
//
//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 <autoptr.h>
#include "saalnnilink.h"
#include "pf/debug.h"
#include "protocol/sscop/sscopprotocol.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).
//

saalNNIlink :: saalNNIlink(void)
    : saalLink()
{   
    _nsscf = new nsscfProtocol(this);
    _nsscfProxy = pfConduit(_nsscf);
    return;
}

saalNNIlink :: saalNNIlink(const saalNNIlink &other_)
    : saalLink(other_)
{   
    _nsscf = new nsscfProtocol(*other_._nsscf, this);
    _nsscfProxy = pfConduit(_nsscf);
    return;
}

//
//Function: destructor
//
//Description:
//    ++TODO++
//

saalNNIlink :: ~saalNNIlink(void)
{
    // nsscf implementation is deleted automatically, when
    // destructor of nsscfProxy is called.
    _nsscfProxy.disconnect();
    return;
}


//
//Function: createNNIConnection
//
//Description:
//    Creates a SAAL connection for NNI by instantiating protocols
//    of SSCF for NNI and SSCOP and connects them together. The SSCOP
//    parameters are set to the NNI default values.
//

saalNNIlink *saalNNIlink :: createATMNNIlink(pfId linkNumber_,
                                             int port_,
                                             int vpi_,
                                             int vci_,
                                             int bufferSize_)
{
    auto_ptr<saalNNIlink> newSaal(new saalNNIlink());
    newSaal->setBufferSize(bufferSize_);
    newSaal->setLinkNumber(linkNumber_);
    newSaal->setNNIprotocols();
    newSaal->openATMConnection(port_, vpi_, vci_);
    newSaal->connectProtocols();
    return newSaal.release();
}

saalNNIlink *saalNNIlink :: createUDPNNIlink(pfId linkNumber_,
                                             const string &hostname_,
                                             int localPort_,
                                             int remotePort_,
                                             int bufferSize_)
{
    auto_ptr<saalNNIlink> newSaal(new saalNNIlink());
    newSaal->setBufferSize(bufferSize_);
    newSaal->setLinkNumber(linkNumber_);
    newSaal->setNNIprotocols();
    newSaal->openUDPConnection(hostname_, localPort_, remotePort_);
    newSaal->connectProtocols();
    return newSaal.release();
}

saalNNIlink *saalNNIlink :: createPrototype(void)
{
    saalNNIlink *newSaal = new saalNNIlink();
    return newSaal;
}

saalNNIlink *saalNNIlink :: clonePrototype(pfId linkNumber_,
                                           int port_,
                                           int vpi_,
                                           int vci_)
{
    auto_ptr<saalNNIlink> newSaal(new saalNNIlink(*this));
    newSaal->setLinkNumber(linkNumber_);
    newSaal->setNNIprotocols();
    newSaal->openATMConnection(port_, vpi_, vci_);
    newSaal->connectProtocols();
    return newSaal.release();
}

//
// Functions: Set methods for NNI-SSCF parameters
//
// Description:
//     These methods provide the interface to NNI-SSCF protocol parameters.
//

void saalNNIlink :: setT1timeout(pfUlong msec_)
{
    _nsscf->setT1timeout(msec_);
    return;
}

void saalNNIlink :: setT2timeout(pfUlong msec_)
{
    _nsscf->setT2timeout(msec_);
    return;
}

void saalNNIlink :: setT3timeout(pfUlong msec_)
{
    _nsscf->setT3timeout(msec_);
    return;
}

void saalNNIlink :: setN1(pfUlong count_)
{
    _nsscf->setN1(count_);
    return;
}

//
// Functions: Imput methods for MAAL-primitives
//
// Description:
//     These primitives are sent by NSSCF managed by this
//     instance of the saalNNIlink.
//

//++TODO++
// Delegate error managament issues to _management object
//
void saalNNIlink :: maalPROVINGindAct(void)
{
    debugUser("[SAAL Layer Management] Received MAAL-PROVING.indication");
    return;
}


void saalNNIlink :: maalSTOP_PROVINGindAct(void)
{
    debugUser("[SAAL Layer Management] Received MAAL-STOP_PROVING.indication");
    return;
}


void saalNNIlink :: maalREPORTindAct(
    nsscfLBC lbc_ ,
    nsscfUBC ubc_,
    nsscfReason reason_,
    nsscfPDU sscop_uu_)
{
    debugUser("[SAAL Layer Management] Received MAAL-REPORT.indication");
    debugUser("      Parameters: Lower boundary  ");
    switch (lbc_)
    {
        case LBC_EMPTY:
            debugUser("-    (Empty)");
            break;
        case LBC_LR:
            debugUser("LR   (Local Release)");
            break;
        case LBC_RR:
            debugUser("RR   (Remote Release)");
            break;
        case LBC_SR:
            debugUser("SR   (SSCOP Release)");
            break;
    }
    debugUser("                  Upper boundary  ");
    switch (ubc_)
    {
        case UBC_EMPTY:
            debugUser("-    (Empty)");
            break;
        case UBC_ALN:
            debugUser("ALN  (Alignment)");
            break;
        case UBC_INS:
            debugUser("INS  (In Service)");
            break;
        case UBC_OOS:
            debugUser("OOS  (Out Of Service)");
            break;
    }
    debugUser("                  Reason          ");
    switch (reason_)
    {
        case R_EMPTY:
            debugUser("-    (Empty)");
            break;
        case R_ANS:
            debugUser("ANS  (Alignment Not Succesful)");
            break;
        case R_CC:
            debugUser("CC   (Congestion Control)");
            break;
        case R_CD:
            debugUser("CD   (Congestion Detected)");
            break;
        case R_PE:
            debugUser("PE   (Protocol Error)");
            break;
        case R_PDUT:
            debugUser("PDUT (PDU Transmitted)");
            break;
        case R_SREC:
            debugUser("SREC (SSCOP Recover)");
            break;
        case R_SSCOP_UU:
            debugUser("UU   (SSCOP User-to-User Information)");
            break;
        case R_UDR:
            debugUser("UDR  (UNITDATA Received)");
            break;
    }
//    debugFrame("                  SSCOP-UU        ", sscop_uu_);
    return;
}

pfConduit saalNNIlink :: getConduit(void)
{
    return _nsscfProxy;
}

void saalNNIlink :: setLinkNumber(pfId linkNumber_)
{
    saalLink::setLinkNumber(linkNumber_);
    _nsscfProxy.setId(linkNumber_);
    return;
}

void saalNNIlink :: setNNIprotocols(void)
{
    setMaxSDUsize(NNI_SSCOP_MAX_SDU_SIZE);
    setMaxUUsize(NNI_SSCOP_MAX_UU_SIZE);
    setMaxCC(NNI_SSCOP_MAX_CC);
    setMaxPD(NNI_SSCOP_MAX_PD);
    setCCtimeout(NNI_SSCOP_TIMER_CC_TIMEOUT);
    setKEEP_ALIVEtimeout(NNI_SSCOP_TIMER_KEEP_ALIVE_TIMEOUT);
    setNO_RESPONSEtimeout(NNI_SSCOP_TIMER_NO_RESPONSE_TIMEOUT);
    setPOLLtimeout(NNI_SSCOP_TIMER_POLL_TIMEOUT);
    setIDLEtimeout(NNI_SSCOP_TIMER_IDLE_TIMEOUT);

    return;
}

void saalNNIlink :: connectProtocols(void)
{
    _nsscfProxy.connectToA(_sscopProxy);
    _sscopProxy.connectToB(_nsscfProxy);
    saalLink::connectProtocols();
    return;
}
