//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / BISUP
//
//File: bisuptestmain.cpp
//
//Version: $Revision: 1.15 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/16 15:24:32 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Sami Raatikainen
//
//Description:
//      Mainfile for testing NI/BISUP protocol
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 

#include <typeinfo>
#include <iostream.h>
#include <string>

#include "testclient.h"
#include "niadapter.h"
#include "protocol/bisup/niprotocol.h"
#include "protocol/bisup/bisupstrings.h"

#include "pf/system.h"
#include "pf/conduit.h"
#include "pf/factory.h"
#include "pf/protocol.h"
#include "pf/transp.h"
#include "pf/mux.h"
#include "pf/bytes.h"
#include "pf/debug.h"

#include "common/ss7configure.h"
#include "iface/naalif/naaldownprimitives.h"
#include "iface/mtpif/mtpdownprimitives.h"
#include "protocol/mtp3/mtp3protocol.h"
#include "protocol/mtp3/mtp3config.h"
#include "protocol/saal/saalnnilink.h"

#include <OB/CORBA.h>
#include "pf/naming.h"


//------------------------------------------------------------------------

void printUsage(char *name_)
{
    cerr << endl;
    cerr << "Usage: " << name_
         << " [s | c | d] [p PORT] " << endl;
    cerr << "- s = server,  c = client, d = debug trace" << endl;
    cerr << "- PORT  = Port number" << endl;
    cerr << endl;
    cerr << "Default values: PORT = 0" << endl;
    exit(0);
}

void configTestClient(pfConduit &niMuxProxy_, pfUlong id_)
{
    // This is the testClient on the other side. This side
    // starts the test procedure when receiving a request from
    // corba-client.
    // --------------
    // | testClient |
    // --------------
    //       |
    // --------------
    // \ niMux     /
    //  -----------
    //       |
    //     
    
    testClient *testAdapter = new testClient();
    pfConduit testAdapterProxy(testAdapter);
    
    CosNaming_Name name = pfNaming::parseName("bisupClient");
    try
    {
        pfNaming::instance()->bind(name, testAdapter);
    }
    catch (CORBA_UserException &exc)
    {
        (void)exc;
        cerr << "testClient: bind to NS failed" << endl;
        exit(1);
    }
    
    // Set ids
    testAdapterProxy.setId(id_);
    
    // Connect conduits
    testAdapterProxy.connectToA(niMuxProxy_);
    
    pfInstallTransporter installer = 
        pfInstallTransporter::createInstallTransporter(testAdapterProxy);
    installer.setKey(id_);
    installer.useThisKey();
    niMuxProxy_.accept(&installer);
    
    return;
}


// configNIandNiAdapter doesn't have factory nor bisupMux
void configTest1(pfConduit &niMuxProxy_, pfUlong id_,
                 pfUlong PC_, pfUlong DPC_)
{
    // --------------
    // | niAdapter  |
    // --------------
    //       |
    // --------------
    // | niProtocol |
    // --------------
    //       |
    // --------------
    // \ niMux     /
    //  -----------
    //       |

    pfConduit niClientProxy = niAdapter::create();    
    pfConduit niProxy = niProtocol::create(PC_, DPC_);
    
    // Set ids
    niClientProxy.setId(id_);
    niProxy.setId(id_);
    
    // Connect conduits
    niClientProxy.connectToA(niProxy);
    niProxy.connectToB(niClientProxy);
    niProxy.connectToA(niMuxProxy_);
    
    pfInstallTransporter installer = 
        pfInstallTransporter::createInstallTransporter(niProxy);
    installer.setKey(id_);
    installer.useThisKey();
    niMuxProxy_.accept(&installer);
    
    return;
}

void configNIserver(pfConduit &niMuxProxy_, pfUlong id_,
                    pfUlong PC_, pfUlong DPC_)
{
    // --------------         -----
    // | niAdapter  |   <--   | F |
    // --------------         -----
    //      (|)                 |
    // --------------           |
    // \ bisupMux  /------------
    //  -----------
    //       |
    // --------------
    // | niProtocol |
    // --------------
    //       |
    // --------------
    // \ niMux     /
    //  -----------
    //       |

    // Create conduit proxies
    pfConduit niClientProxy = niAdapter::create();

    pfConduit factoryConduit = pfFactory::createFactory(niClientProxy);
    factoryConduit.setId(id_);
    
    pfConduit bisupMuxProxy = pfMux::createMux(1000, bisupMuxReferenceStr);
    pfConduit niProxy = niProtocol::create(PC_, DPC_);
    
    // Set ids
    bisupMuxProxy.setId(id_);
    niProxy.setId(id_);

    // Connect conduits
    factoryConduit.connectToA(bisupMuxProxy);
    bisupMuxProxy.connectToB(factoryConduit);
    bisupMuxProxy.connectToA(niProxy);

    niProxy.connectToB(bisupMuxProxy);
    niProxy.connectToA(niMuxProxy_);

    pfInstallTransporter installer = 
        pfInstallTransporter::createInstallTransporter(niProxy);
    installer.setKey(id_);
    installer.useThisKey();
    niMuxProxy_.accept(&installer);
    
    return;
}


int main(int argc, char *argv[])
{
    const pfKey BISUP = 9;
    pfBoolean client = 0;
    
    pfUlong PORT = 1;
    //pfUlong VCIclient = 101; // for sw
    pfUlong VCIclient = 201; // configured to FORE switch 13.11.98 201->211
    pfUlong VCIserver = 211; // configured to FORE switch 13.11.98 211->201
    pfUlong cliPC = 20;
    pfUlong srvPC = 10;

    int count = 1;
    while (count < argc)
    {
        switch (*argv[count++])
        {
            case 'p':
                PORT = atoi(argv[count++]);
                break;
            case 's':
                break;
            case 'c':
                client = 1;
                break;
            case 'd':
                cout << "DEBUG" << endl;
                debugOutputCout();
                break;
            case '-':
                count = 100;
                break;
            case 'h':
            default:
                printUsage(argv[0]);
                break;
	}
    }


    pfSystem::init(argc, argv);
    
    // Initialize variables
    pfId id = 1;
    pfKey maxValue = 1000;
    
    // SS7 configure object
    ss7Configure configure = ss7ConfigureImplementation::createSS7Configure();

    // PC 10-20 --> port 1, link 1
    //configure.configureRoutingTable(10, 20, 1, 1);
    configure.configureRoutingTable(10, 20, 1);
    
   
    // Create implementations
    saalNNIlink *link = 0;
    if (client != 0)
    {
        debugUser("Creating ATMNNIlink using following values:");
        debugPfUlong(" - PORTTI: ", PORT);
        debugPfUlong(" - VCI: ", VCIclient);
        configure.setPointCode(cliPC);
        link = saalNNIlink::createATMNNIlink(id, PORT, 0, VCIclient);
    }
    else
    {
        debugUser("Creating ATMNNIlink using following values:");
        debugPfUlong(" - PORTTI: ", PORT);
        debugPfUlong(" - VCI: ", VCIserver);
        configure.setPointCode(srvPC);
        link = saalNNIlink::createATMNNIlink(id, PORT, 0, VCIserver);
    }
        
    link->setN1(1);  // Only one proving-PDUs
    pfConduit nsscfProxy = link->getConduit();

    // Create conduit proxies
    string SI("serviceIndicator");
    string AAL("AALid");
    pfConduit niMuxProxy = pfMux::createMux(maxValue, AAL);
    pfConduit userMuxProxy = pfMux::createMux(maxValue, SI);
    pfConduit mtp3Proxy(mtp3Protocol::createProtocol(configure));
    pfConduit aalMuxProxy = pfMux::createMux(maxValue, AAL);
        
    // Set ids
    niMuxProxy.setId(1);
    userMuxProxy.setId(id);
    mtp3Proxy.setId(id);
    aalMuxProxy.setId(id);

    // Connect conduits
    aalMuxProxy.connectToA(mtp3Proxy);
    userMuxProxy.connectToA(mtp3Proxy);

    mtp3Proxy.connectToB(userMuxProxy);
    mtp3Proxy.connectToA(aalMuxProxy);
    
    if (client != 0)
    {
        cout << "\nConfiguring (niTest)client side..." << endl;
        configTestClient(niMuxProxy, id);
    }
    else
    {
        cout << "\nConfiguring server (niProtocol) side..." << endl;
        //configTest1(niMuxProxy, id);
        configNIserver(niMuxProxy, id, srvPC, cliPC);
    }
    
    cout << "\nConfiguring mtp..." << endl;    
    // Connect user parts
    configure.setBISUP();
    mtpConfigTransporter config =
        mtpConfigTransporter::createConfigSideB(BISUP, niMuxProxy);
    mtp3Proxy.accept(&config);
    
    // Connect AAL connections
    mtpConfigTransporter config1 =
        mtpConfigTransporter::createConfigSideA(1, nsscfProxy);
    mtp3Proxy.accept(&config1);
    
    // Set up SAAL connection
    cout << "Setting up SAAL NNI link..." << endl;  
    naalSTARTreq *startMessenger = new naalSTARTreq;
    pfMsgTransporter *startMessage = 
        pfMsgTransporter::createMsgTransporter(startMessenger);
    startMessage->setSender(aalMuxProxy);
    nsscfProxy.accept(startMessage);

    configure.printConfigure(cout);

    try
    {
    	pfSystem::instance()->run();
    }
    catch (...)
    {
        debugUser("Exception catched in main");
    }

    return 0;
}
