//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / testing/testadapter/uni
//
//File: unitest.cpp
//
//Version: $Revision: 1.5 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/10/09 11:43:39 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Jussi Turunen
//      Timo Kokkonen
//
//Description:
//
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History:
//

#include <OB/CORBA.h>
#include <OB/Util.h>

#include <typeinfo>
#include <string>

#include <stdio.h>
#include <stdlib.h>

#ifdef HAVE_FSTREAM
#   include <fstream>
#else
#   include <fstream.h>
#endif

#include "pf/bitstring.h"
#include "pf/debug.h"
#include "pf/exception.h"
#include "pf/bytes.h"
#include "pf/frame.h"

#include "testing/testadapter/adapter/taprimitives.h"
#include "testing/testadapter/adapter/msg.h"
#include "unicoderstrings.h"
#include "unipducoder.h"

void printUsageUNI(string argv0_);
otMessage::SerializedMessage decodeUNIpdu(pfFrame frame_);

// addToFrameXX methods add the XX IE into the frame passed as a parameter
void addToFramePDUheader(pfUlong pduType_, pfFrame &frame_);
void addToFrameCA_IE(pfFrame &frame_); // Cause
void addToFrameCS_IE(pfFrame &frame_); // Call state
void addToFrameAAL_IE(pfFrame &frame_); // ATM adaptation layer parameters
void addToFrameATD_IE(pfFrame &frame_); // ATM traffic descriptor
void addToFrameCI_IE(pfFrame &frame_); // Connection identifier
void addToFrameQOS_IE(pfFrame &frame_); // Quality of service parameter
void addToFrameBHL_IE(pfFrame &frame_); // Broadband high layer information
void addToFrameBBC_IE(pfFrame &frame_); // Broadband bearer capability
void addToFrameBLL_IE(pfFrame &frame_); // Broadband low-layer information
void addToFrameBLSH_IE(pfFrame &frame_); // Broadband locking shift
void addToFrameBNSH_IE(pfFrame &frame_); // Broadband non-locking shift
void addToFrameBSC_IE(pfFrame &frame_); // Broadband sending complete
void addToFrameBRI_IE(pfFrame &frame_); // Broadband repeat indicator
void addToFrameCGN_IE(pfFrame &frame_); // Calling party number
void addToFrameCGS_IE(pfFrame &frame_); // Calling party subaddress
void addToFrameCDN_IE(pfFrame &frame_); // Called party number
void addToFrameCDS_IE(pfFrame &frame_); // Called party subaddress
void addToFrameTNS_IE(pfFrame &frame_); // Transit network selection
void addToFrameRI_IE(pfFrame &frame_); // Restart indicator
void addToFrameUN_IE(pfFrame &frame_); // Unknown IE

otMessage::SerializedMessage sendUNIpdu(char choice_,
                                        CORBA_String_var &identifier_)
{
    pfFrame frame;
    otMessage::SerializedMessage msg;
    
    if (choice_ == 'a') // Alerting PDU
    {
        addToFramePDUheader(B0000_0001, frame);
        
        debugFrame("Alerting-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        identifier_ = CORBA_string_dup(ALERTStr.c_str());
    }
    else if (choice_ == 'b') // Call proceeding PDU
    {
        addToFrameCI_IE(frame);
        addToFramePDUheader(B0000_0010, frame);
        
        debugFrame("Call proceeding-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        identifier_ = CORBA_string_dup(CALL_PROCStr.c_str());
    }
    else if (choice_ == 'c') // Setup PDU
    {
        addToFrameTNS_IE(frame);
        addToFrameCDS_IE(frame);
        addToFrameCDN_IE(frame);
        addToFrameCGS_IE(frame);
        addToFrameCGN_IE(frame);
        addToFrameBSC_IE(frame);
        addToFrameBLL_IE(frame); // 3th BLL
        addToFrameBLL_IE(frame); // 2nd BLL
        addToFrameBLL_IE(frame); // 1st BLL
        addToFrameBRI_IE(frame);
        addToFrameBBC_IE(frame);
        addToFrameBHL_IE(frame);
        addToFrameQOS_IE(frame);
        addToFrameCI_IE(frame);
        addToFrameATD_IE(frame);
        addToFrameAAL_IE(frame);
        addToFramePDUheader(B0000_0101, frame);
        
        debugFrame("Setup-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        
        identifier_ = CORBA_string_dup(SETUPStr.c_str());
    }
    else if (choice_ == 'd') // Connect PDU
    {
        addToFrameBLL_IE(frame);
        addToFrameCI_IE(frame);
        addToFramePDUheader(B0000_0111, frame);
        
        debugFrame("Connect-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        
        identifier_ = CORBA_string_dup(CONNStr.c_str());
    }
    else if (choice_ == 'e') // Connect acknowledge PDU
    {
        addToFramePDUheader(B0000_1111, frame);
        
        debugFrame("Connect acknowledge-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(CONN_ACKStr.c_str());
    }
    else if (choice_ == 'f') // Restart PDU
    {
        addToFrameRI_IE(frame);
        addToFrameCI_IE(frame);
        addToFramePDUheader(B0100_0110, frame);
        
        debugFrame("Restart-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(RESTStr.c_str());
    }
    else if (choice_ == 'g') // Release PDU
    {
        addToFrameCA_IE(frame);
        addToFramePDUheader(B0100_1101, frame);
        
        debugFrame("Release-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        
        identifier_ = CORBA_string_dup(RELStr.c_str());
    }
    else if (choice_ == 'h') // Restart acknowledge PDU
    {
        addToFrameRI_IE(frame);
        addToFrameCI_IE(frame);
        addToFramePDUheader(B0100_1110, frame);
        
        debugFrame("Restart acknowledge-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(REST_ACKStr.c_str());
    }
    else if (choice_ == 'i') // Release complete PDU
    {
        addToFrameCA_IE(frame);
        addToFramePDUheader(B0101_1010, frame);
        
        debugFrame("Release complete-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        
        identifier_ = CORBA_string_dup(REL_COMStr.c_str());
    }
    else if (choice_ == 'j') // Status PDU
    {
        addToFrameCS_IE(frame);
        addToFrameCA_IE(frame);
        addToFramePDUheader(B0111_1101, frame);
        
        debugFrame("Status-pdu created", frame);

        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(STATStr.c_str());
    }
    else if (choice_ == 'k') // Status enquiry PDU
    {
        addToFramePDUheader(B0111_0101, frame);

        debugFrame("Status enquiry-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(STAT_ENQStr.c_str());
    }
    else if (choice_ == 'l') // Unknown PDU
    {
        addToFrameRI_IE(frame);
        addToFrameCI_IE(frame);
        addToFramePDUheader(B1111_1111, frame);
        
        debugFrame("Unknown-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup("Unkown PDU");
    }
    else if (choice_ == 'm') // Alerting + (RI_IE + UN_IE + CI_IE)
    {
        addToFrameRI_IE(frame);
        addToFrameUN_IE(frame);
        addToFrameCI_IE(frame);
        addToFramePDUheader(B0000_0001, frame);
        
        debugFrame("Alerting(RI_IE + UN_IE + CI_IE)-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(ALERTStr.c_str());
    }
    else if (choice_ == 'n') // Alerting + BLSH_IE + BNSH_IE
    {
        addToFrameBLSH_IE(frame);
        addToFrameBNSH_IE(frame);
        addToFramePDUheader(B0000_0001, frame);
        
        debugFrame("Alerting(BLSH_IE + BNSH_IE)-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        
        identifier_ = CORBA_string_dup(ALERTStr.c_str());
    }
    else if (choice_ == 'o') // Alerting + (CS_IE with extra field)
    {
        // Call state IE
        frame.putFirst(B0010_1011); // Extra field
        frame.putFirst(B0010_1011);
        frame.putFirst16bit(2);
        frame.putFirst(B1111_1000);
        frame.putFirst(B0001_0100);
        
        addToFramePDUheader(B0000_0001, frame);

        debugFrame("Alerting(CS_IE with extra field)-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(ALERTStr.c_str());
    }
    else if (choice_ == 'p')
        // Alerting + (CA_IE with extra extensions in header and content)
    {
        // Cause IE
        frame.putFirst(B0010_1111);
        frame.putFirst(B0100_0010);
        frame.putFirst(B1010_0011);
        frame.putFirst(B1011_1000); // extra extension
        frame.putFirst(B0110_0001); // extra extension
        frame.putFirst(B0000_1011);
        frame.putFirst16bit(6);
        frame.putFirst(B1011_1010);
        frame.putFirst(B0111_1000); // extra extension
        frame.putFirst(B0000_1000);
        
        addToFramePDUheader(B0000_0001, frame);
        
        debugFrame("Alerting(CA_IE with extra extensions)-pdu created", frame);

        msg = decodeUNIpdu(frame);
    
        identifier_ = CORBA_string_dup(ALERTStr.c_str());
    }
    else if (choice_ == 'q') // Alerting + (CI_IE(too short) + RI_IE)
    {
        addToFrameRI_IE(frame);
        // CI_IE ... last 3 octets missing
        frame.putFirst(B1111_0000);
        frame.putFirst(B1000_1000);
        frame.putFirst16bit(2);
        frame.putFirst(B1111_1000);
        frame.putFirst(B0101_1010);
        
        addToFramePDUheader(B0000_0001, frame);
        
        debugFrame("Alerting + (CI_IE(too short) + RI_IE)-pdu created", frame);

        msg = decodeUNIpdu(frame);

        identifier_ = CORBA_string_dup(ALERTStr.c_str());
    }
    else if (choice_ == 'r')
    {
        frame.putFirst(B1001_0010); // type oct. 2 (Instruction field)
        frame.putFirst(B0000_0001); // type alerting pdu
        frame.putFirst24bit(0);     // Call reference
        frame.putFirst(B0000_0011); // Call length & spares
        frame.putFirst(B0000_1001); // Protocol Discriminator
        
        debugFrame("Testing too short pdu-header", frame);
        
        msg = decodeUNIpdu(frame);
         
        identifier_ = CORBA_string_dup("Too short PDU header");
    }
    else if (choice_ == 's')
    {
	debugString("Sending Primitive", AAL_EST_REQStr);
        identifier_ = CORBA_string_dup(AAL_EST_REQStr.c_str());
    }
    else if (choice_ == 't')
    {
	debugString("Sending Primitive", AAL_EST_CONFStr);
        identifier_ = CORBA_string_dup(AAL_EST_CONFStr.c_str());
    }
    else if (choice_ == 'u')
    {
	debugString("Sending Primitive", AAL_REL_REQStr);
        identifier_ = CORBA_string_dup(AAL_REL_REQStr.c_str());
    }
    else if (choice_ == 'v')
    {
	debugString("Sending Primitive", AAL_REL_CONFStr);
        identifier_ = CORBA_string_dup(AAL_REL_CONFStr.c_str());
    }
    else if (choice_ == 'w')
    {
	debugString("Sending Primitive", AAL_EST_REQStr);
        string tmp = "NT" + AAL_EST_REQStr;
        identifier_ = CORBA_string_dup(tmp.c_str());
    }
    else if (choice_ == 'x')
    {
	debugString("Sending Primitive", AAL_EST_REQStr);
        //string tmp = "NT" + AAL_EST_REQStr;
        //identifier_ = CORBA_string_dup("NR");
        string tmp = "NR" + AAL_EST_REQStr;
        identifier_ = CORBA_string_dup(tmp.c_str());
    }
    else if (choice_ == 'y') // Setup PDU
    {
        addToFrameTNS_IE(frame);
        addToFrameCDS_IE(frame);
        addToFrameCDN_IE(frame);
        addToFrameCGS_IE(frame);
        addToFrameCGN_IE(frame);
        addToFrameBSC_IE(frame);
        addToFrameBLL_IE(frame); // 3th BLL
        addToFrameBLL_IE(frame); // 2nd BLL
        addToFrameBLL_IE(frame); // 1st BLL
        addToFrameBRI_IE(frame);
        addToFrameBBC_IE(frame);
        addToFrameBHL_IE(frame);
        addToFrameQOS_IE(frame);
        addToFrameCI_IE(frame);
        addToFrameATD_IE(frame);
        addToFrameAAL_IE(frame);
        addToFramePDUheader(B0000_0101, frame);
        
        debugFrame("Setup-pdu created", frame);
        
        msg = decodeUNIpdu(frame);
        string tmp = "NR" + SETUPStr;
        identifier_ = CORBA_string_dup(tmp.c_str());
    }
    else
    {
        printUsageUNI("./executable");
    }

    return msg;
}

void printUsageUNI(string argv0_)
{
//    string usage = "Usage: " + argv0_ + " reference file";

//    debugUser(usage);
    debugUser("a <-> Alerting PDU");
    debugUser("b <-> Call proceeding PDU");
    debugUser("c <-> Setup PDU");
    debugUser("d <-> Connect PDU");
    debugUser("e <-> Connect acknowledge PDU");
    debugUser("f <-> Restart PDU");
    debugUser("g <-> Release PDU");
    debugUser("h <-> Restart acknowledge PDU");
    debugUser("i <-> Release complete PDU");
    debugUser("j <-> Status PDU");
    debugUser("k <-> Status enquiry PDU");
    debugUser("l <-> Unknown PDU");
    debugUser("m <-> Alerting + (RI_IE + UN_IE + CI_IE)");
    debugUser("n <-> Alerting + BLSH_IE + BNSH_IE");
    debugUser("o <-> Alerting + (CS_IE with extra field)");
    debugUser("p <-> Alerting + (CA_IE with extra extensions in header and content)");
    debugUser("q <-> Alerting + (CI_IE(too short) + RI_IE)");
    debugUser("r <-> Testing too short pdu-header");
    debugUser("s <-> AAL_EST_REQ"); 
    debugUser("t <-> AAL_EST_CONF"); 
    debugUser("u <-> AAL_REL_REQ"); 
    debugUser("v <-> AAL_REL_CONF");
    debugUser("w <-> AAL_EST_REQ");
    debugUser("x <-> AAL_EST_REQ");
    
    return;
}

otMessage::SerializedMessage decodeUNIpdu(pfFrame frame_)
{
    uniPDUcoder testcoder;

    otMessage::SerializedMessage testMessage = testcoder.decode(frame_);

    debugUser("Printing created otMessage::SerializedMessage...");
    for (pfUlong i = 0; i < testMessage.length(); ++i)
    {
        otMessage::ElementKind kind = testMessage[i].kind;
        string id = testMessage[i].identifier.in();
        string value = testMessage[i].value.in();
        pfUlong number = testMessage[i].number;
//        debugPfUlong("kind", kind);
        debugString("id", id);
        if (kind == otMessage::Integer ||
            kind == otMessage::Boolean)
        {
            debugPfUlong("number", number);
        }
        else
        {
            debugString("value", value);
        }
    }
    debugUser("otMessage::SerializedMessage printed.");

    return testMessage;
}

void addToFramePDUheader(pfUlong pduType_, pfFrame &frame_)
{
    frame_.putFirst16bit(frame_.length()); // length
    frame_.putFirst(B1001_0010); // type oct. 2 (Instruction field)
    frame_.putFirst(pduType_); // type
    frame_.putFirst24bit(0); // Call reference
    frame_.putFirst(B0000_0011); // Call length & spares
    frame_.putFirst(B0000_1001); // Protocol Discriminator

    return;
}

void addToFrameCA_IE(pfFrame &frame_) // Cause
{
    frame_.putFirst(B0010_1111);
    frame_.putFirst(B0100_0010);
    frame_.putFirst(B1010_0011);
    frame_.putFirst(B1000_1011);
    frame_.putFirst16bit(4);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0000_1000);

    return;
}

void addToFrameCS_IE(pfFrame &frame_) // Call state
{
    frame_.putFirst(B0010_1011);
    frame_.putFirst16bit(1);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0001_0100);

    return;
}

void addToFrameAAL_IE(pfFrame &frame_) // ATM adaptation layer parameters
{
    frame_.putFirst(B0011_0010);
    frame_.putFirst(B1000_0100);
    frame_.putFirst16bit(12345);
    frame_.putFirst16bit(11111);
    frame_.putFirst(B1000_0010);
    frame_.putFirst16bit(22222);
    frame_.putFirst(B1000_0001);
    frame_.putFirst16bit(33333);
    frame_.putFirst(B1000_1100);
    frame_.putFirst(B0010_1011);
    frame_.putFirst16bit(14);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0101_1000);

    return;
}

void addToFrameATD_IE(pfFrame &frame_) // ATM traffic descriptor
{
    frame_.putFirst(B0000_0010);
    frame_.putFirst(B1011_1111);
    frame_.putFirst(B1011_1110);
    frame_.putFirst24bit(1231114);
    frame_.putFirst(B1011_0001);
    frame_.putFirst24bit(1231111);
    frame_.putFirst(B1011_0000);
    frame_.putFirst24bit(1213111);
    frame_.putFirst(B1010_0001);
    frame_.putFirst24bit(1211311);
    frame_.putFirst(B1010_0000);
    frame_.putFirst24bit(1211131);
    frame_.putFirst(B1001_0001);
    frame_.putFirst24bit(1211113);
    frame_.putFirst(B1001_0000);
    frame_.putFirst24bit(1211111);
    frame_.putFirst(B1000_1001);
    frame_.putFirst24bit(1121111);
    frame_.putFirst(B1000_1000);
    frame_.putFirst24bit(1112111);
    frame_.putFirst(B1000_0101);
    frame_.putFirst24bit(1111211);
    frame_.putFirst(B1000_0100);
    frame_.putFirst24bit(1111121);
    frame_.putFirst(B1000_0011);
    frame_.putFirst24bit(1111112);
    frame_.putFirst(B1000_0010);
    frame_.putFirst16bit(51);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0101_1001);    

    return;
}

void addToFrameCI_IE(pfFrame &frame_) // Connection identifier
{
    frame_.putFirst16bit(155);
    frame_.putFirst16bit(43);
    frame_.putFirst(B1000_1000);
    frame_.putFirst16bit(5);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0101_1010);

    return;
}

void addToFrameQOS_IE(pfFrame &frame_) // Quality of service parameter
{
    frame_.putFirst(B1000_0001);
    frame_.putFirst(B0001_1000);
    frame_.putFirst16bit(2);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0101_1100);

    return;
}

void addToFrameBHL_IE(pfFrame &frame_) // Broadband high layer information
{
    frame_.putFirst(B1000_0000);
    frame_.putFirst(B0100_0000);
    frame_.putFirst(B0010_0000);
    frame_.putFirst(B0001_0000);
    frame_.putFirst(B0000_1000);
    frame_.putFirst(B0000_0100);
    frame_.putFirst(B0000_0010);
    frame_.putFirst(B0000_0001);
    frame_.putFirst(B1001_1000);
    frame_.putFirst16bit(9);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0101_1101);

    return;
}

void addToFrameBBC_IE(pfFrame &frame_) // Broadband bearer capability
{
    frame_.putFirst(B1010_0001);
    frame_.putFirst(B1000_1001);
    frame_.putFirst(B0001_0000);
    frame_.putFirst16bit(3);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0101_1110);

    return;
}

void addToFrameBLL_IE(pfFrame &frame_) // Broadband low-layer information
{
    frame_.putFirst(B1111_0010);
    frame_.putFirst(B1100_1011);
    frame_.putFirst(B1010_0001);
    frame_.putFirst(B1000_1001);
    frame_.putFirst(B0001_0000);
    frame_.putFirst16bit(5);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0101_1111);

    return;
}

void addToFrameBLSH_IE(pfFrame &frame_) // Broadband locking shift
{
    frame_.putFirst(B1000_0011);
    frame_.putFirst16bit(1);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0110_0000);

    return;
}

void addToFrameBNSH_IE(pfFrame &frame_) // Broadband non-locking shift
{
    frame_.putFirst(B1000_0100);
    frame_.putFirst16bit(1);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0110_0001);

    return;
}

void addToFrameBSC_IE(pfFrame &frame_) // Broadband sending complete
{
    frame_.putFirst(B1010_0001);
    frame_.putFirst16bit(1);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0110_0010);

    return;
}

void addToFrameBRI_IE(pfFrame &frame_) // Broadband repeat indicator
{
    frame_.putFirst(B1000_0101);
    frame_.putFirst16bit(1);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0110_0011);

    return;
}

void addToFrameCGN_IE(pfFrame &frame_) // Calling party number
{
    frame_.putFirst(B0101_0111);
    frame_.putFirst(B0101_0101);
    frame_.putFirst(B0101_0011);
    frame_.putFirst(B0000_0010);
    frame_.putFirst(B1100_0010);
    frame_.putFirst(B0101_0100);
    frame_.putFirst16bit(6);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0110_1100);

    return;
}

void addToFrameCGS_IE(pfFrame &frame_) // Calling party subaddress
{
    frame_.putFirst(B0101_1010);
    frame_.putFirst(B0000_1111);
    frame_.putFirst(B1001_0110);
    frame_.putFirst(B0011_1100);
    frame_.putFirst(B1100_0011);
    frame_.putFirst(B1101_0000);
    frame_.putFirst16bit(6);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0110_1101);

    return;
}

void addToFrameCDN_IE(pfFrame &frame_) // Called party number
{
    frame_.putFirst(B0101_1010);
    frame_.putFirst(B0000_1111);
    frame_.putFirst(B0011_1100);
    frame_.putFirst(B0100_0011);
    frame_.putFirst(B1101_0100);
    frame_.putFirst16bit(5);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0111_0000);

    return;
}

void addToFrameCDS_IE(pfFrame &frame_) // Called party subaddress
{
    frame_.putFirst(B0000_1111);
    frame_.putFirst(B0011_1100);
    frame_.putFirst(B0100_0011);
    frame_.putFirst(B1101_0000);
    frame_.putFirst16bit(4);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0111_0001);

    return;
}

void addToFrameTNS_IE(pfFrame &frame_) // Transit network selection
{
    frame_.putFirst(B0011_0000);
    frame_.putFirst(B0101_1000);
    frame_.putFirst(B0011_1000);
    frame_.putFirst(B0011_0111);
    frame_.putFirst(B0011_0100);
    frame_.putFirst(B0011_0011);
    frame_.putFirst(B0011_0010);
    frame_.putFirst(B1001_1100);
    frame_.putFirst16bit(8);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0111_1000);

    return;
}

void addToFrameRI_IE(pfFrame &frame_) // Restart indicator
{
    frame_.putFirst(B1000_0111);
    frame_.putFirst16bit(1);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B0111_1001);

    return;
}

void addToFrameUN_IE(pfFrame &frame_) // Unknown IE
{
    frame_.putFirst(B1100_0011);
    frame_.putFirst(B1111_1110);
    frame_.putFirst(B1101_1100);
    frame_.putFirst(B1011_1010);
    frame_.putFirst(B1001_1000);
    frame_.putFirst(B0111_0110);
    frame_.putFirst(B0101_0100);
    frame_.putFirst(B0011_0010);
    frame_.putFirst(B0001_0000);
    frame_.putFirst16bit(9);
    frame_.putFirst(B1111_1000);
    frame_.putFirst(B1111_1111);

    return;
}

otMessage_var readOneRef(char *refFile_, CORBA_ORB_var orb_)
{
    otMessage_var adapter;
    try
    {
        FILE *fp = fopen(refFile_, "r");
        if (fp == 0)
        {
            debugString("can't open ", refFile_);
            exit(1);
        }
	
	char s[1000];
        fscanf(fp, "%s", s);
        fclose(fp);
	
	CORBA_Object_var obj = orb_->string_to_object(s);
	assert(!CORBA_is_nil(obj));
	
	adapter = otMessage::_narrow(obj);
	assert(!CORBA_is_nil(adapter));
    }
    catch (...)
    {
        debugUser("catch");
    }
    return adapter;
}


int main(int argc, char* argv[], char*[])
{
    debugOutputCout();
    if (argc == 1)
    {
        string usage = "Usage: uniclient referencefile.ref";
        debugUser(usage);
        exit(1);
    }

    try
    {
	//
	// Create ORB
	//
	CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);
	
	//
	// Get loop object
	//
        char* refFile = (char *) malloc (30*sizeof(char));
        
        otMessage_var tester;
        otMessage_var IUT;
        
        if (argc == 2)
        {
            strcpy(refFile, argv[1]);
            tester = readOneRef(refFile, orb);
        }
        else if (argc == 3)
        {
            // 2xreadOneRef
            strcpy(refFile, argv[1]);
            tester = readOneRef(refFile, orb);
            strcpy(refFile, argv[2]);
            IUT = readOneRef(refFile, orb);
        }
        else
        {
            // something abt. usage
        }

	//
	// Main loop
	//
        char c;

        debugUser("X exits and U prints usage instructions");
        while (1)
        {
            cout << "send primitive >";
            cin >> c;
            cout << endl;
            if (c == 'X')
            {
                break;
            }
            else if (c == 'U')
            {
                printUsageUNI(argv[0]);
            }
            else if (c >= 'a' && c <= 'z')
            {
                CORBA_String_var identifierXX;// = CORBA_string_dup("PDU");
                otMessage::SerializedMessage
                    messageXX = sendUNIpdu(c, identifierXX);
                tester->send(identifierXX, messageXX);
            }
            else
            {
                continue;
            }
        }
    }
#ifdef __GNUG__
    catch(CORBA_COMM_FAILURE& ex)
#else
    catch(CORBA_SystemException& ex)
#endif
    {
	OBPrintException(ex);
	return 1;
    }
    return 0;
}
