//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / UNI
//
//File: unipdu.cpp 
//
//Version: $Revision: 1.87 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/02/02 08:38:30 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Jari Katajavuori
//
//Description:
//
//
//Copyright:
//
//
//Licence:
//
//
//History: 

#include "unipdu.h"
#include "pf/error.h"
#include "pf/tools.h"
#include "unidefs.h"
#include "unistrings.h"
#include "uniexceptions.h"
#include "unicoordprotocol.h"
#include "uniprotocol.h"

uniPdu :: uniPdu(void)
    : pfMessenger(),
      pfBitHandler(),
      _mandatory(),
      _optional(),
      _errorInfo(0)
{
    defineFrame(uniFrameStr);
    defineInteger(uniMuxReferenceStr);
    defineInteger(uniCallReferenceFlagStr);
    defineInteger(uniCallReferenceStr);
    defineInteger(uniMessageTypeStr);
    defineInteger(uniMessageLengthStr);
    return;
}

uniPdu :: uniPdu(const uniPdu &other_)
    : pfMessenger(other_),
      pfBitHandler(other_),
      _mandatory(other_._mandatory),
      _optional(other_._optional),
      _errorInfo(0)
{
    uniErrorInfo *old = other_._errorInfo.get();
    if (old != 0)
    {
        errorInfoType tmp(new uniErrorInfo(*old));
        _errorInfo = tmp;
    }
    return;
}

uniPdu :: ~uniPdu(void)
{
    return;
}

//
// Method: clone
//
// Description:
//     Makes an identical copy of the original instance.
//

pfMessenger *uniPdu :: clone(void)
{
    uniPdu *newPdu = new uniPdu(*this);
    return newPdu;
}

//
// Method: create
//
// Description:
//     Creates a new instance decoding variables from the given frame_
//

uniPdu *uniPdu :: create(pfFrame &frame_, uniCoOrdProtocol *protocol_)
{
    uniPdu *message;

    if (frame_.length() < uniPduMinimumSize)
    {
        throw uniDiscardMessageException(PF_EX_INFO);
    }
    
    pfUlong messageType = frame_.read(uniMessageTypePosition);

    switch (messageType)
    {
        case uniMsgAlerting :
            message = uniALERTINGpdu::create();
            break;
            
        case uniMsgCallProceeding :
            message = uniCALL_PROCEEDINGpdu::create();
            break;

        case uniMsgConnect :
            message = uniCONNECTpdu::create();
            break;

        case uniMsgConnectAck :
            message = uniCONNECT_ACKpdu::create();
            break;

        case uniMsgSetup :
            message = uniSETUPpdu::create();
            break;

        case uniMsgRelease :
            message = uniRELEASEpdu::create();
            break;

        case uniMsgReleaseComplete :
            message = uniRELEASE_COMPLETEpdu::create();
            break;

        case uniMsgRestart :
            message = uniRESTARTpdu::create();
            break;

        case uniMsgRestartAck :
            message = uniRESTART_ACKpdu::create();
            break;

        case uniMsgNotify :
            message = uniNOTIFYpdu::create();
            break;
            
        case uniMsgStatus :
            message = uniSTATUSpdu::create();
            break;

        case uniMsgStatusEnquiry :
            message = uniSTATUS_ENQUIRYpdu::create();
            break;

        case uniMsgAddParty :
            message = uniADD_PARTYpdu::create();
            break;

        case uniMsgAddPartyAck :
            message = uniADD_PARTY_ACKpdu::create();
            break;

        case uniMsgAddPartyReject :
            message = uniADD_PARTY_REJECTpdu::create();
            break;

        case uniMsgDropParty :
            message = uniDROP_PARTYpdu::create();
            break;

        case uniMsgDropPartyAck :
            message = uniDROP_PARTY_ACKpdu::create();
            break;
            
        default:
            // Message type not implemented. Decode common
            // fields only.
        {
            message = new uniPdu;
            message->start(frame_);
            message->decodeCommonFields();

            uniErrorInfo info(uniCauseValue_MessageTypeNonexistent);
            info.setMessageType(messageType);

            // If Action Indicator was specified, proceed as indicated
            if (message->isVariableDefined(uniUnrecognizedMsgActionStr) != 0)
            {
                pfUlong indAct = 
                    message->getInteger(uniUnrecognizedMsgActionStr);
                switch (indAct) 
                {
                    case B0000_0000 : // Clear call
                        protocol_->sendRELEASE_COMPLETEpduToUNI(
                            message, uniCauseValue_NormalUnspecified);
                        protocol_->sendRELEASE_COMPLETEreplyToAAL(
                            message, uniCauseValue_NormalUnspecified);
                        break;
                    case B0000_0001 : // Discard and ignore
                        break;
                    case B0000_0010 : // Discard and report status
                        protocol_->sendStatus(message, info);
                        break;
                    case B0000_0011 : // Reserved (Discard)
                        break;
                }
            }
            else 
            {
                protocol_->sendStatus(message, info);
            }
            throw uniDiscardMessageException(PF_EX_INFO);
        }
    }

    message->setUNIFrame(frame_);

    try 
    {
        message->decode();
    }
    catch (uniDiscardMessageException &discardException)
    {
        if (discardException.getSendStatus() != 0)
        {
            uniErrorInfo errorInfo(uniCauseValue_NormalUnspecified);
            protocol_->sendStatus(message, errorInfo);
        }
        throw;
    }

    uniErrorInfo *errorInfo = message->getErrorInfo();

    if (errorInfo != 0)
    {
        debugUser("Error info got. Executing specific procedures..");
        pfUlong cause = errorInfo->getCause();
        bool fatal = errorInfo->isFatalError();
        switch (cause)
        {
            case uniCauseValue_MandatoryIEIsMissing :
                message->uniMandatoryIEMissingAct(protocol_, *errorInfo);
                break;

            case uniCauseValue_InvalidIEContents :
                if (fatal != 0)
                {
                    message->uniMandatoryIEContentErrorAct(protocol_,
                                                           *errorInfo);
                }
                break;
        }
        debugUser("Error info processed.");
    }
                
    return message;
}

//
// Method: setCallReference
// 
// Description:
//     Sets a Call Reference variable getting the value from
//     the key given to the protocol_ instance.
//

void uniPdu :: setCallReference(uniProtocol *protocol_)
{
    pfKey key = 0;
    
    if (protocol_ != 0)
    {
        key = protocol_->getKey();
    }

    // The flag is the MSb of the key
    pfUlong flag = key >> uniCallReferenceFlagBitPosition;
    // Reference does not contain the flag -> filter it out
    pfUlong reference = key & (~uniCallReferenceFlagBitMask); 
    // Originating end sets flag to zero, but terminating conduit
    // have an id with flag set to one. We are to take a complement.
    pfUlong muxReference = key ^ uniCallReferenceFlagBitMask;
    setInteger(uniCallReferenceFlagStr, flag);
    setInteger(uniCallReferenceStr, reference);
    setInteger(uniMuxReferenceStr, muxReference);
            
    return;
}

//
// Method: setMuxReference
//
// Description:
//     Mux Reference is a variable which is used while propagating
//     a message through the mux conduit. It is like an address and is
//     different from the Call Reference by the MSb.
//

void uniPdu :: setMuxReference(void)
{
    pfUlong flag = getInteger(uniCallReferenceFlagStr);
    pfUlong reference = getInteger(uniCallReferenceStr);

    // Complement the flag and set it as an MSb of muxReference
    pfUlong muxReference =
        ((1-flag) << uniCallReferenceFlagBitPosition) | reference; 

    setInteger(uniMuxReferenceStr, muxReference);
    return;
}

//
// Method: isMultipointMessage
//
// Description:
//      Returns true if current pdu contains endpoint reference.
//

bool uniPdu :: isMultipointMessage(void)
{
    bool result = isAvailable(uniEndpointReferenceStr);
    return result;
}

//
// Method: setEndpointReference
//
// Description:
//      Sets endpoint reference value.
//

void uniPdu :: setEndpointReference(pfUlong endpointReference_)
{
    if (isVariableDefined(uniEndpointReferenceStr) == 0)
    {
        defineInteger(uniEndpointReferenceStr);
    }
    setInteger(uniEndpointReferenceStr, endpointReference_);

    return;
}

//
// Method: setUNIFrame
//
// Description:
//    

void uniPdu :: setUNIFrame(pfFrame &frame_)
{
    pfStorage::setFrame(uniFrameStr, frame_);
    return;
}

pfFrame uniPdu :: getUNIFrame(void)
{
    pfFrame result = pfStorage::getFrame(uniFrameStr);
    return result;
}

//
// Method: decreaseIfInExtension
//
// Description:
//      Decreases a given variable by amount, if pfBitHandler
//      frame pointer is inside an extension block
//

void uniPdu :: decreaseIfInExtension(pfLong &variable_, pfLong amount_)
{
    if (isInExtension() != 0)
    {
        variable_ -= amount_;
    }
    return;
}

//
// Method: globalCallReferenceProcedures
//
// Description:
//

void uniPdu :: globalCallReferenceProcedures(uniCoOrdProtocol *protocol_)
{
    protocol_->sendSTATUSreplyToAAL(
        this, uniCauseValue_InvalidCallReferenceValue);
    return;
}

//
// Method: noProtocolCallReferenceProcedures
//
// Description:
//

void uniPdu :: noProtocolCallReferenceProcedures(uniCoOrdProtocol *protocol_)
{
    protocol_->sendRELEASE_COMPLETEreplyToAAL(
        this, uniCauseValue_InvalidCallReferenceValue); 
    return;
}

//
// Method: protocolRelatedCallReferenceProcedures
//
// Description:
//

void uniPdu :: protocolRelatedCallReferenceProcedures(
    uniCoOrdProtocol *protocol_)
{
    protocol_->toB(this);
    return;
}

//
// Method: 
//
// Description:
//

void uniPdu :: uniMandatoryIEMissingAct(uniCoOrdProtocol *protocol_,
                                        uniErrorInfo &errorInfo_)
{
    protocol_->sendStatus(this, errorInfo_);
    throw uniDiscardMessageException(PF_EX_INFO);
    return;
}

void uniPdu :: uniMandatoryIEContentErrorAct(uniCoOrdProtocol *protocol_,
                                             uniErrorInfo &errorInfo_)
{
    protocol_->sendStatus(this, errorInfo_);
    throw uniDiscardMessageException(PF_EX_INFO);
    return;
}

//
// Method: getErrorInfo
// 
// Description:
//      Gets error info instance
//

uniErrorInfo *uniPdu :: getErrorInfo(void)
{
    return _errorInfo.get();
}

//
// Method: decode
//
// Description:
//

void uniPdu :: decode(void)
{
    pfFrame frame = getUNIFrame();
    start(frame);

    if (isVariableDefined(uniDEBUGStr) != 0)
    {
        debugUser("DECODING....");
        debugString("Frame contents: ", frame.toString());
    }
    
    decodeCommonFields();
    decodeIEs();

    if (isVariableDefined(uniDEBUGStr) != 0)
    {
        debugUser("Message Contents:");
        print();
        debugUser("END DECODING.");
    }
    
    return;
}

//
// Method: encode
//
// Description:
//      Encode default pdu and return encoded frame.
//

pfFrame uniPdu :: encode(void)
{
    pfFrame frame;
    start(frame);

    if (isVariableDefined(uniDEBUGStr) != 0)
    {
        debugUser("ENCODING...");
        print();
    }
    
    setInteger(uniMessageLengthStr, 0);

    encodeIEs();
    encodeCommonFields();
    
    frame = pfBitHandler::getFrame();
    setUNIFrame(frame);

    if (isVariableDefined(uniDEBUGStr) != 0)
    {
        frame.useHex();
        debugString("Frame contents: ", frame.toString());
        debugUser("END ENCODING.");
    }
    
    return frame;
}

//
// Method: defineX
//
// Description:
//      Defines specific IE in a message inserting it into specified
//      typeset (mandatory or optional). These methods also define
//      all subfields specific for an IE.
//

pfStorage &uniPdu :: defineAALParameters(void)
{
    defineStorage(uniAALParametersStr);
    pfStorage storage;
    //pfStorage &storage = (*this)[uniAALParametersStr];
    storage.defineInteger(uniAALP_TypeStr);
    storage.defineInteger(uniAALP_SubtypeStr);
    storage.defineInteger(uniAALP_CBRRateStr);
    storage.defineInteger(uniAALP_MultiplierStr);
    storage.defineInteger(uniAALP_SourceClockRecoveryStr);
    storage.defineInteger(uniAALP_ErrorCorrectionMethodStr);
    storage.defineInteger(uniAALP_DataTransferBlocksizeStr);
    storage.defineInteger(uniAALP_PartiallyFilledStr);
    storage.defineInteger(uniAALP_ForwardMaxSDUSizeStr);
    storage.defineInteger(uniAALP_BackwardMaxSDUSizeStr);
    storage.defineInteger(uniAALP_MIDRangeLowStr);
    storage.defineInteger(uniAALP_MIDRangeHighStr);
    storage.defineInteger(uniAALP_SSCSTypeStr);
    storage.defineInteger(uniAALP_UserDefinedInfoStr);

    setStorage(uniAALParametersStr, storage);
    pfStorage &storageRef = (*this)[uniAALParametersStr];
    
    return storageRef;
}

pfStorage &uniPdu :: defineATMTrafficDescriptor(void)
{
    defineStorage(uniATDStr);
    pfStorage &storage = (*this)[uniATDStr];

    storage.defineInteger(uniATD_ForwardPeakCellRateCLP0Str);
    storage.defineInteger(uniATD_BackwardPeakCellRateCLP0Str);
    storage.defineInteger(uniATD_ForwardPeakCellRateCLP1Str);
    storage.defineInteger(uniATD_BackwardPeakCellRateCLP1Str);
    storage.defineInteger(uniATD_ForwardSustainableCLP0Str);
    storage.defineInteger(uniATD_BackwardSustainableCLP0Str);
    storage.defineInteger(uniATD_ForwardSustainableCLP1Str);
    storage.defineInteger(uniATD_BackwardSustainableCLP1Str);
    storage.defineInteger(uniATD_ForwardMaxBurstSizeCLP0Str);
    storage.defineInteger(uniATD_BackwardMaxBurstSizeCLP0Str);
    storage.defineInteger(uniATD_ForwardMaxBurstSizeCLP1Str);
    storage.defineInteger(uniATD_BackwardMaxBurstSizeCLP1Str);
    storage.defineBoolean(uniATD_BestEffortStr);
    storage.defineBoolean(uniATD_TaggingBackwardStr);
    storage.defineBoolean(uniATD_TaggingForwardStr);
    storage.defineInteger(uniATD_ForwardCombinationStr);
    storage.defineInteger(uniATD_BackwardCombinationStr);
    
    return storage;
}

pfStorage &uniPdu :: defineBroadbandHighLayerInfo(void)
{
    defineStorage(uniBroadbandHighLayerInfoStr);
    pfStorage &storage = (*this)[uniBroadbandHighLayerInfoStr];
    storage.defineInteger(uniBHLI_TypeStr);
    storage.defineFrame(uniBHLI_InfoStr);
    
    return storage;
}

pfStorage &uniPdu :: defineBroadbandBearerCapability(void)
{
    defineStorage(uniBroadbandBearerCapabilityStr);
    pfStorage &storage = (*this)[uniBroadbandBearerCapabilityStr];
    storage.defineInteger(uniBBC_BearerClassStr);
    storage.defineInteger(uniBBC_TrafficTypeStr);
    storage.defineInteger(uniBBC_TimingRequirementsStr);
    storage.defineInteger(uniBBC_SusceptibilityToClippingStr);
    storage.defineInteger(uniBBC_UserPlaneConnectionConfigurationStr);
    
    return storage;
}

pfStorage &uniPdu :: defineBroadbandLowLayerInfo(char num_)
{
    string ieName = uniBroadbandLowLayerInfoStr + num_;

    defineStorage(ieName);
    pfStorage &storage = getStorage(ieName);
      
    storage.defineInteger(uniBLLI_Layer1UserInfoStr);
    storage.defineInteger(uniBLLI_Layer2UserInfoStr);
    storage.defineInteger(uniBLLI_Layer2ModeStr);
    storage.defineInteger(uniBLLI_WindowSizeStr);
    storage.defineInteger(uniBLLI_Layer2ProtocolInfoStr);
    storage.defineInteger(uniBLLI_Layer3UserInfoStr);
    storage.defineInteger(uniBLLI_Layer3ModeStr);
    storage.defineInteger(uniBLLI_DefaultPacketSizeStr);
    storage.defineInteger(uniBLLI_PacketWindowSizeStr);
    storage.defineInteger(uniBLLI_Layer3ProtocolInfoStr);
    storage.defineInteger(uniBLLI_IPIStr);
    storage.defineInteger(uniBLLI_OUIStr);
    storage.defineInteger(uniBLLI_PIDStr);
    
    return storage;
}

pfStorage &uniPdu :: defineBroadbandLockingShift(void)
{
    defineStorage(uniBroadbandLockingShiftStr);
    pfStorage &storage = (*this)[uniBroadbandLockingShiftStr];

    return storage;
}

pfStorage &uniPdu :: defineBroadbandNonlockingShift(void)
{
    defineStorage(uniBroadbandNonlockingShiftStr);
    pfStorage &storage = (*this)[uniBroadbandNonlockingShiftStr];

    return storage;
}

pfStorage &uniPdu :: defineBroadbandSendingComplete(void)
{
    defineStorage(uniBroadbandSendingCompleteStr);
    pfStorage &storage = (*this)[uniBroadbandSendingCompleteStr];
    storage.defineBoolean(uniBSC_FlagStr);
    
    return storage;
}

pfStorage &uniPdu :: defineCalledPartyNumber(void)
{
    pfStorage *storage;

    if (isVariableDefined(uniCalledPartyNumberStr) == 0)
    {
        defineStorage(uniCalledPartyNumberStr);
        storage = &((*this)[uniCalledPartyNumberStr]);
        storage->defineInteger(uniCalledPartyNumber_TypeStr);
        storage->defineInteger(uniCalledPartyNumber_PlanStr);
        storage->defineString(uniCalledPartyNumber_DigitsStr);
    }
    else
    {
        storage = &((*this)[uniCalledPartyNumberStr]);
    }
    
    return *storage;
}

pfStorage &uniPdu :: defineCalledPartySubaddress(void)
{
    defineStorage(uniCalledPartySubaddressStr);
    pfStorage &storage = (*this)[uniCalledPartySubaddressStr];
    storage.defineInteger(uniCalledPS_TypeStr);
    storage.defineInteger(uniCalledPS_OddEvenStr);
    storage.defineString(uniCalledPS_DigitsStr);
    
    return storage;
}

pfStorage &uniPdu :: defineCallingPartyNumber(void)
{
    defineStorage(uniCallingPartyNumberStr);
    pfStorage &storage = (*this)[uniCallingPartyNumberStr];
    storage.defineInteger(uniCallingPartyNumber_TypeStr);
    storage.defineInteger(uniCallingPartyNumber_PlanStr);
    storage.defineString(uniCallingPartyNumber_DigitsStr);
    storage.defineInteger(uniCallingPartyNumber_PresentIndStr);
    storage.defineInteger(uniCallingPartyNumber_ScreeningIndStr);
    
    return storage;
}

pfStorage &uniPdu :: defineCallingPartySubaddress(void)
{
    defineStorage(uniCallingPartySubaddressStr);
    pfStorage &storage = (*this)[uniCallingPartySubaddressStr];
    storage.defineInteger(uniCallingPS_TypeStr);
    storage.defineInteger(uniCallingPS_OddEvenStr);
    storage.defineString(uniCallingPS_DigitsStr);
    
    return storage;
}

pfStorage &uniPdu :: defineCallState(void)
{
    defineStorage(uniCallStateStr);
    pfStorage &storage = (*this)[uniCallStateStr];
    storage.defineInteger(uniCallState_StateStr);
    
    return storage;
}

pfStorage &uniPdu :: defineCause(void)
{
    pfBoolean define2nd = 0;

    pfStorage cause;
    cause.defineInteger(uniCause_LocationStr);
    cause.defineInteger(uniCause_ValueStr);
    cause.defineInteger(uniCause_ClassStr);

    if (isVariableDefined(uniCauseStr) == 0)
    {
        defineStorage(uniCauseStr);
        setStorage(uniCauseStr, cause);
    }
    else if (isVariableDefined(uniCause2Str) == 0)
    {
        defineStorage(uniCause2Str);
        setStorage(uniCause2Str, cause);
        define2nd = 1;
    }

    pfStorage &storage = getStorage(uniCauseStr);
    if (define2nd != 0)
    {
        storage = getStorage(uniCause2Str);
    }
    
    return storage;
}

pfStorage &uniPdu :: defineConnectionIdentifier(void)
{
    defineStorage(uniConnectionIdentifierStr);
    pfStorage &storage = (*this)[uniConnectionIdentifierStr];
    storage.defineInteger(uniConnectionIdentifier_PrefExStr);
    storage.defineInteger(uniConnectionIdentifier_VPAssosiatedStr);
    storage.defineInteger(uniConnectionIdentifier_VPCIStr);
    storage.defineInteger(uniConnectionIdentifier_VCIStr);
    
    return storage;
}

pfStorage &uniPdu :: defineEndpointState(void)
{
    defineStorage(uniEndpointStateStr);
    pfStorage &storage = (*this)[uniEndpointStateStr];
    storage.defineInteger(uniEndpointState_PartyStateStr);
    
    return storage;
}

pfStorage &uniPdu :: defineQoSParameters(void)
{
    defineStorage(uniQoSParametersStr);
    pfStorage &storage = (*this)[uniQoSParametersStr];
    storage.defineInteger(uniQoS_ForwardStr);
    storage.defineInteger(uniQoS_BackwardStr);
    
    return storage;
}

pfStorage &uniPdu :: defineRestartIndicator(void)
{
    defineStorage(uniRestartIndicatorStr);
    pfStorage &storage = (*this)[uniRestartIndicatorStr];
    storage.defineInteger(uniRestartIndicator_ClassStr);
    
    return storage;
}

pfStorage &uniPdu :: defineTransitNetworkSelection(void)
{
    defineStorage(uniTransitNetworkSelectionStr);
    pfStorage &storage = (*this)[uniTransitNetworkSelectionStr];
    storage.defineString(uniTNS_NetworkIdentificationStr);
    
    return storage;
}

//---- private
//
// Method: encodeIEs
//
// Description:
//
// Throws: uniEncodeFailedException
//

uniPdu::IETypeSet uniPdu :: encodeIEs(void)
{
    IETypeSet encodedOptionals;
    IETypeIter iter;

    for (iter = _mandatory.begin(); iter != _mandatory.end(); iter++)
    {
        encodeIE(*iter);
    }    
    
    for (iter = _optional.begin(); iter != _optional.end(); iter++)
    {
        try
        {
            encodeIE(*iter);
            encodedOptionals.insert(*iter);
        }
        catch (uniEncodeFailedException &)
        {
            // These encodings are not necessary so exception
            // should not propagate any further.
        }
    }
        
    return encodedOptionals;
}

//
// Method: encodeIE
//
// Description:
//
// Throws: uniEncodeFailedException
//

void uniPdu :: encodeIE(IEType type_)
{
    try
    {
        switch (type_)
        {
            case uniIEAALParameters :
                encodeAALParameters();
                break;

            case uniIEATMTrafficDescriptor :
                encodeATMTrafficDescriptor();
                break;

            case uniIEBBearerCapability :
                encodeBroadbandBearerCapability();
                break;

            case uniIEBLowLayerInfo :
                encodeBroadbandLowLayerInfo();
                break;

            case uniIEBHighLayerInfo :
                encodeBroadbandHighLayerInfo();
                break;

            case uniIEBSendingComplete :
                encodeBroadbandSendingComplete();
                break;
                
            case uniIECallingPartyNumber :
                encodeCallingPartyNumber();
                break;

            case uniIECallingPartySubaddress :
                encodeCallingPartySubaddress();
                break;
                
            case uniIECalledPartyNumber :
                encodeCalledPartyNumber();
                break;

            case uniIECalledPartySubaddress :
                encodeCalledPartySubaddress();
                break;

            case uniIECallState :
                encodeCallState();
                break;
                
            case uniIECause :
                encodeCause();
                break;

            case uniIEConnectionIdentifier :
                encodeConnectionIdentifier();
                break;

            case uniIEEndpointReference :
                encodeEndpointReference();
                break;
                
            case uniIEEndpointState :
                encodeEndpointState();
                break;

            case uniIEQoSParameters :
                encodeQoSParameters();
                break;

            case uniIERestartIndicator :
                encodeRestartIndicator();
                break;

            case uniIETransitNetworkSelection :
                encodeTransitNetworkSelection();
                break;
                
            default :
                throw uniEncodeFailedException(PF_EX_INFO);
        }
    }
    catch (pfNameUndefinedException &)
    {
        throw uniEncodeFailedException(PF_EX_INFO);
    }

    return;
}
//
// Method: encodeCommonFields
//
// Description:
//      Encodes common fields
//

void uniPdu :: encodeCommonFields(void)
{
    try
    {
        putBits(16, getInteger(uniMessageLengthStr));
        putBits(2, 0); // IF action indicator
        putSpare(2);
        putBits(1, 0); // Message IF not significant
        putSpare(2);
        putBits(1, 1);
        putBits(8, getInteger(uniMessageTypeStr));
        putBits(23, getInteger(uniCallReferenceStr));
        putBits(1, getInteger(uniCallReferenceFlagStr));
        putBits(8, 3); // Call reference length
        putBits(8, uniProtocolDiscriminator);
    }
    catch (pfNameUndefinedException &)
    {
        throw uniEncodeFailedException(PF_EX_INFO);
    }
    return;
}

//
// Methods: IE encoding methods
//
// Description:
//      Encodes individual IE. Encoding is done in an 'inverse'
//      order! If needed variables are not defined, a
//      pfNameUndefinedException will be thrown and no encoding
//      will be updated into a frame. This is why mandatory variables
//      are collected from the pdu before any encoding.  
//

void uniPdu :: encodeAALParameters(void)
{
    pfStorage &storage = (*this)[uniAALParametersStr];
    pfUlong aalType = storage.getInteger(uniAALP_TypeStr);
    pfUlong subtype, cbrRate;
    
    pfUlong ieLength = 0;

    switch (aalType)
    {
        case B0000_0001 : // AAL Type 1
            
            subtype = storage.getInteger(uniAALP_SubtypeStr);
            cbrRate = storage.getInteger(uniAALP_CBRRateStr);

            if (storage.isAvailable(uniAALP_PartiallyFilledStr) != 0)
            {
                putBits(8, storage.getInteger(uniAALP_PartiallyFilledStr));
                putBits(8, B1000_1011);
                ieLength += 2;
            }
            if (storage.isAvailable(uniAALP_DataTransferBlocksizeStr) != 0)
            {                
                putBits(16, storage.getInteger(uniAALP_DataTransferBlocksizeStr));
                putBits(8, B1000_1010);
                ieLength += 3;
            }
            if (storage.isAvailable(uniAALP_ErrorCorrectionMethodStr) != 0)
            {               
                putBits(8, storage.getInteger(uniAALP_ErrorCorrectionMethodStr));
                putBits(8, B1000_1001);
                ieLength += 2;
            }
            if (storage.isAvailable(uniAALP_SourceClockRecoveryStr) != 0)
            {
                putBits(8, storage.getInteger(uniAALP_SourceClockRecoveryStr));
                putBits(8, B1000_1000);
                ieLength += 2;
            }
            if ((storage.isAvailable(uniAALP_MultiplierStr) != 0) &&
                ((cbrRate == B0100_0000) || (cbrRate == B0100_0001)))
            {
                putBits(16, storage.getInteger(uniAALP_MultiplierStr));
                putBits(8, B1000_0111);
                ieLength += 3;
            }

            putBits(8, cbrRate);
            putBits(8, B1000_0110);
            putBits(8, subtype);
            putBits(8, B1000_0101);
            ieLength += 4;

            break;
            
        case B0000_0011 : // AAL Type 3/4

            if (storage.isAvailable(uniAALP_SSCSTypeStr) != 0)
            {
                putBits(8, storage.getInteger(uniAALP_SSCSTypeStr));
                putBits(8, B1000_0100);
                ieLength += 2;
            }
            if ((storage.isAvailable(uniAALP_MIDRangeLowStr) != 0) &&
                (storage.isAvailable(uniAALP_MIDRangeHighStr) != 0))
            {
                putBits(16, storage.getInteger(uniAALP_MIDRangeHighStr));
                putBits(16, storage.getInteger(uniAALP_MIDRangeLowStr));
                putBits(8, B1000_0010);
                ieLength += 5;
            }
            if ((storage.isAvailable(uniAALP_ForwardMaxSDUSizeStr) != 0) &&
                (storage.isAvailable(uniAALP_BackwardMaxSDUSizeStr) != 0))
            {
                putBits(16, storage.getInteger(uniAALP_BackwardMaxSDUSizeStr));
                putBits(8, B1000_0001);
                putBits(16, storage.getInteger(uniAALP_ForwardMaxSDUSizeStr));
                putBits(8, B1000_1100);
                ieLength += 6;
            }
            break;
                
        case B0000_0101 : // AAL Type 5

            if (storage.isAvailable(uniAALP_SSCSTypeStr) != 0)
            {
                putBits(8, storage.getInteger(uniAALP_SSCSTypeStr));
                putBits(8, B1000_0100);
                ieLength += 2;
            }
            if ((storage.isAvailable(uniAALP_ForwardMaxSDUSizeStr) != 0) &&
                (storage.isAvailable(uniAALP_BackwardMaxSDUSizeStr) != 0))
            {
                putBits(16, storage.getInteger(uniAALP_BackwardMaxSDUSizeStr));
                putBits(8, B1000_0001);
                putBits(16, storage.getInteger(uniAALP_ForwardMaxSDUSizeStr));
                putBits(8, B1000_1100);
                ieLength += 6;
            }
            break;
            
        case B0001_0000 : // User Defined AAL

            if (storage.isAvailable(uniAALP_UserDefinedInfoStr) != 0)
            {
                putBits(32, storage.getInteger(uniAALP_UserDefinedInfoStr));
                ieLength += 4;
            }
    }
    putBits(8, aalType);
    ieLength++;
    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIEAALParameters);
    ieLength += 4;
    
    addMessageLength(ieLength);
    
    return;
}

void uniPdu :: encodeATMTrafficDescriptor(void)
{
    pfStorage &storage = (*this)[uniATDStr];
    pfUlong ieLength = 0;

    if (storage.isAvailable(uniATD_BestEffortStr) != 0)
    {
        pfUlong forwardPCR =
            storage.getInteger(uniATD_ForwardPeakCellRateCLP1Str);
        pfUlong backwardPCR =
            storage.getInteger(uniATD_BackwardPeakCellRateCLP1Str);

        putBits(8, B1011_1110); // Best Effort Indicator
        putBits(24, backwardPCR);
        putBits(8, B1000_0101); // Backward PCR Identifier 0+1
        putBits(24, forwardPCR);
        putBits(8, B1000_0100); // Forward PCR Identifier 0+1
        ieLength += 9;
    }
    else
    {
        pfBoolean taggingF = 0;
        pfBoolean taggingB = 0;
        
        pfUlong forwardPCR1 =
            storage.getInteger(uniATD_ForwardPeakCellRateCLP1Str);
        putBits(24, forwardPCR1);
        putBits(8, B1000_0100); // Forward PCR 0+1
        ieLength += 4;
        
        if (storage.isAvailable(uniATD_ForwardPeakCellRateCLP0Str) != 0)
        {
            pfUlong forwardPCR0 =
                storage.getInteger(uniATD_ForwardPeakCellRateCLP0Str);
            putBits(24, forwardPCR0);
            putBits(8, B1000_0010); // FPCR 0
            ieLength += 4;
            
            if ((storage.isAvailable(uniATD_TaggingForwardStr) != 0) &&
                (storage.getBoolean(uniATD_TaggingForwardStr) != 0))
            {
                taggingF = 1;
            }           
        } else if (storage.isAvailable(
            uniATD_ForwardSustainableCLP0Str) != 0)
        {
            pfUlong forwardSCR0 =
                storage.getInteger(uniATD_ForwardSustainableCLP0Str);
            pfUlong forwardMBS0 =
                storage.getInteger(uniATD_ForwardMaxBurstSizeCLP0Str);
            putBits(24, forwardSCR0);
            putBits(8, B1000_1000); // FSCR 0
            putBits(24, forwardMBS0);
            putBits(8, B1010_0000); // FMBS 0
            ieLength += 8;
            
            if ((storage.isAvailable(uniATD_TaggingForwardStr) != 0) &&
                (storage.getBoolean(uniATD_TaggingForwardStr) != 0))
            {
                taggingF = 1;
            }                       
        } else if (storage.isAvailable(
            uniATD_ForwardSustainableCLP1Str) != 0)
        {
            pfUlong forwardSCR1 =
                storage.getInteger(uniATD_ForwardSustainableCLP0Str);
            pfUlong forwardMBS1 =
                storage.getInteger(uniATD_ForwardMaxBurstSizeCLP0Str);
            putBits(24, forwardSCR1);
            putBits(8, B1001_0000); // FSCR 0+1
            putBits(24, forwardMBS1);
            putBits(8, B1011_0000); // FMBS 0+1
            ieLength += 8;
        }

        // Backwards
        if ((storage.isAvailable(uniATD_BackwardPeakCellRateCLP1Str) != 0) &&
            (storage.isAvailable(uniEndpointReferenceStr) == 0))
        {
            pfUlong backwardPCR1 =
                storage.getInteger(
                    uniATD_BackwardPeakCellRateCLP1Str);
            putBits(24, backwardPCR1);
            putBits(8, B1000_0101);
            ieLength += 4;
            
            if (storage.isAvailable(uniATD_BackwardPeakCellRateCLP0Str) != 0)
            {
                pfUlong backwardPCR0 =
                  storage.getInteger(uniATD_BackwardPeakCellRateCLP0Str);
                putBits(24, backwardPCR0);
                putBits(8, B1000_0011); // BPCR 0
                ieLength += 4;
                
                if ((storage.isAvailable(uniATD_TaggingBackwardStr) != 0) &&
                    (storage.getBoolean(uniATD_TaggingBackwardStr) != 0))
                {
                    taggingB = 1;
                }           
            } else if (storage.isAvailable(uniATD_BackwardSustainableCLP0Str) != 0)
            {
                pfUlong backwardSCR0 =
                    storage.getInteger(uniATD_BackwardSustainableCLP0Str);
                pfUlong backwardMBS0 =
                    storage.getInteger(uniATD_BackwardMaxBurstSizeCLP0Str);
                putBits(24, backwardSCR0);
                putBits(8, B1000_1001); // BSCR 0
                putBits(24, backwardMBS0);
                putBits(8, B1010_0001); // BMBS 0
                ieLength += 8;
                
                if ((storage.isAvailable(uniATD_TaggingBackwardStr) != 0) &&
                    (storage.getBoolean(uniATD_TaggingBackwardStr) != 0))
                {
                    taggingB = 1;
                }                       
            } else if (storage.isAvailable(uniATD_BackwardSustainableCLP1Str) != 0)
            {
                pfUlong backwardSCR1 =
                    storage.getInteger(uniATD_BackwardSustainableCLP0Str);
                pfUlong backwardMBS1 =
                    storage.getInteger(uniATD_BackwardMaxBurstSizeCLP0Str);
                putBits(24, backwardSCR1);
                putBits(8, B1001_0001); // BSCR 0+1
                putBits(24, backwardMBS1);
                putBits(8, B1011_0001); // BMBS 0+1
                ieLength += 8;
            } 
        }

        if ((taggingF != 0) || (taggingB != 0))
        {
            putBits(1, taggingF);
            putBits(1, taggingB);
            putSpare(6);
            putBits(8, B1011_1111); // Tagging requested
        }

        if ((storage.isAvailable(uniATD_BestEffortStr) != 0) &&
            (storage.getBoolean(uniATD_BestEffortStr) != 0))
        {
            putBits(8, B1011_1110); // Best Effort
        }
    }
    
    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIEATMTrafficDescriptor);

    addMessageLength(ieLength + 4);

    return;
}

void uniPdu :: encodeBroadbandBearerCapability(void)
{
    pfStorage &storage = (*this)[uniBroadbandBearerCapabilityStr];
    pfUlong ieLength = 0;

    pfUlong bclass = storage.getInteger(uniBBC_BearerClassStr);
    pfUlong ttype, requirements;

    if (bclass == BCOB_X)
    {
        ttype = storage.getInteger(uniBBC_TrafficTypeStr);
        requirements = storage.getInteger(uniBBC_TimingRequirementsStr);
    }
    
    pfUlong clipping = storage.getInteger(uniBBC_SusceptibilityToClippingStr);
    pfUlong conf = storage.getInteger(
        uniBBC_UserPlaneConnectionConfigurationStr);

    putBits(2, conf);
    putSpare(3);
    putBits(2, clipping);
    putExtension(1);
    if (bclass == BCOB_X)
    {
        putBits(2, requirements);
        putBits(3, ttype);
        putSpare(2);
        putExtension(1); 
        putBits(5, bclass);
        putSpare(2);
        putExtension(0);
        ieLength = 3;
    }
    else
    {
        putBits(5, bclass);
        putSpare(2);
        putExtension(1);
        ieLength = 2;
    }
        
    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIEBBearerCapability);

    addMessageLength(ieLength + 4);

    return;
}

void uniPdu :: encodeBroadbandHighLayerInfo(void)
{
    pfStorage &storage = (*this)[uniBroadbandHighLayerInfoStr];
    pfLong ieLength = 0;

    pfFrame info = storage.getFrame(uniBHLI_InfoStr);
    while ((info.length() > 0) && (ieLength < 8))
    {
        putBits(8, info.getLast());
        ieLength++;
    }   
    putBits(7, B0000_0001); // user specific
    putExtension(1);
    ieLength++;
    
    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIEBHighLayerInfo);
    
    addMessageLength(ieLength + 4);
    
    return;
}

void uniPdu :: encodeBroadbandLowLayerInfo(void)
{
    char index = '1';
    pfUlong numOfBLLIs = 0;
    
    while (index < '4')
    {
        string ieName = uniBroadbandLowLayerInfoStr + index; 
        if (isVariableDefined(ieName) != 0)
	{
	    encodeOneBLLI(ieName);
	    numOfBLLIs++;
	}
	index++;
    }

    // Include repeat indicator if several BLLIs encoded. 
    if (numOfBLLIs > 1)
    {
        encodeBroadbandRepeatIndicator();
    }   
    return;
}

void uniPdu :: encodeOneBLLI(string ieName_)
{
    pfStorage &storage = getStorage(ieName_);
    pfUlong ieLength = 0;
    
    if (storage.isAvailable(uniBLLI_Layer3UserInfoStr) != 0)
    {
        pfUlong layer3UserInfo = storage.getInteger(
            uniBLLI_Layer3UserInfoStr);        

        pfByte nextExtension = 1;
        
        switch (layer3UserInfo)
        {
            case B0000_0110 : // X.25
            case B0000_0111 : // ISO/IEC 8208
            case B0000_1000 : // X.223/ISO 8878

                if (storage.isAvailable(uniBLLI_Layer3ModeStr) != 0)
                {
                    if (storage.isAvailable(
                        uniBLLI_DefaultPacketSizeStr) != 0)
                    {
                        if (storage.isAvailable(
                            uniBLLI_PacketWindowSizeStr) != 0)
                        {
                            putBits(7, storage.getInteger(
                                uniBLLI_PacketWindowSizeStr));
                            putExtension(nextExtension);
                            nextExtension = 0;
                            ieLength++;
                        }
                        putBits(4, storage.getInteger(
                            uniBLLI_DefaultPacketSizeStr));
                        putSpare(3);
                        putExtension(nextExtension);
                        nextExtension = 0;
                        ieLength++;
                    }
                    putSpare(5);
                    putBits(2, storage.getInteger(uniBLLI_Layer3ModeStr));
                    putExtension(nextExtension);
                    nextExtension = 0;
                    ieLength++;
                }
                break;
                
            case B0001_0000 : // User Specified

                if (storage.isAvailable(uniBLLI_Layer3ProtocolInfoStr) != 0)
                {
                    putBits(7, storage.getInteger(uniBLLI_Layer3ProtocolInfoStr));
                    putExtension(0); // putExtension(1); 
                    nextExtension = 0;
                    ieLength++;
                }
                break;
                
            case B0000_1011 : // ISO/IEC TR 9577

                if (storage.isAvailable(uniBLLI_IPIStr) != 0)
                {
                    pfUlong ipi = storage.getInteger(uniBLLI_IPIStr);  
                    if (ipi == B1000_0000)
                    {
                        pfUlong oui = storage.getInteger(uniBLLI_PIDStr);
                        pfUlong pid = storage.getInteger(uniBLLI_OUIStr);
                        putBits(16, pid);
                        putBits(24, oui);
                        putSpare(5);
                        putBits(2, 0); // SNAP ID
                        putExtension(1);
                        ieLength += 3;
                    }
                    putSpare(6);
                    putBits(1, ipi & 1);
                    putExtension(1);
                    putBits(7, ipi >> 1);
                    putExtension(0);
                    nextExtension = 0;
                    ieLength += 2;
                }
                break;
        }            
        putBits(5, layer3UserInfo);
        putBits(2, 3); // Layer 3 id
        putExtension(nextExtension);
        ieLength++;
    }

    if (storage.isAvailable(uniBLLI_Layer2UserInfoStr) != 0)
    {
        pfUlong layer2UserInfo = storage.getInteger(
            uniBLLI_Layer2UserInfoStr);
        
        pfByte nextExtension = 1;
        switch (layer2UserInfo)
        {
            case B0000_0110 : // X.25 LL
            case B0000_0111 : // X.25 ML
            case B0000_1001 : // HDLC ARM
            case B0000_1010 : // HDLC NRM
            case B0000_1011 : // HDLC ABM
            case B0000_1110 : // X.75
            case B0001_0001 : // ISO 7776 DTE-DTE
                
                if (storage.isAvailable(uniBLLI_Layer2ModeStr) != 0)
                {
                    if (storage.isAvailable(uniBLLI_WindowSizeStr) != 0)
                    {                    
                        putBits(7, storage.getInteger(uniBLLI_WindowSizeStr));
                        putExtension(nextExtension);
                        nextExtension = 0;
                        ieLength++;
                    }
                    putBits(2, 0); // Q.933 not used
                    putSpare(3);
                    putBits(2, storage.getInteger(uniBLLI_Layer2ModeStr));
                    putExtension(nextExtension);
                    ieLength++;
                }
                break;

            case B0001_0000 : // User specified

                if (storage.isAvailable(uniBLLI_Layer2ProtocolInfoStr) != 0)
                {
                    putBits(7, storage.getInteger(
                        uniBLLI_Layer2ProtocolInfoStr));
                    putExtension(1);
                    nextExtension = 0;
                    ieLength++;
                }
                break;
        }
        putBits(5, layer2UserInfo);
        putBits(2, 2); // Layer 2 id
        putExtension(nextExtension);
        ieLength++;
    }

    if (storage.isAvailable(uniBLLI_Layer1UserInfoStr) != 0)
    {
        pfUlong layer1UserInfo = storage.getInteger(
            uniBLLI_Layer1UserInfoStr);

        putBits(5, layer1UserInfo);
	putBits(2, 1); // Layer 1 id
	putExtension(1);
	ieLength++;
    }

    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIEBLowLayerInfo);
    ieLength += 4;

    addMessageLength(ieLength);

    return;
}

void uniPdu :: encodeBroadbandRepeatIndicator(void)
{
    putBits(4, B0000_0010);
    putSpare(3);
    putExtension(1);
    putBits(16, 1); // Length
    putBits(8, standardInstructionField);
    putBits(8, uniIEBRepeatIndicator);

    addMessageLength(5);
    
    return;
}

void uniPdu :: encodeBroadbandSendingComplete(void)
{
    pfStorage &storage = (*this)[uniBroadbandSendingCompleteStr];

    if (storage.getBoolean(uniBSC_FlagStr) != 0)
    {
        putBits(7, B0010_0001);
        putExtension(1);

        putBits(16, 1);
        putBits(8, standardInstructionField);
        putBits(8, uniIEBSendingComplete);

        addMessageLength(5);
    }

    return;
}

void uniPdu :: encodeCalledPartyNumber(void)
{
    pfStorage &storage = (*this)[uniCalledPartyNumberStr];
    pfUlong ieLength = 0;

    pfUlong type = storage.getInteger(uniCalledPartyNumber_TypeStr);
    pfUlong plan = storage.getInteger(uniCalledPartyNumber_PlanStr);
    string digits = storage.getString(uniCalledPartyNumber_DigitsStr);

    if (plan == B0000_0010)
    {
        // NSAP encoding
        ieLength += toolEncodeNSAP(digits);
    }
    else
    {
        // IA5 encoding
        ieLength += toolEncodeISDN(digits);
    }
    
    putBits(4, plan);
    putBits(3, type);
    putExtension(1);
    ieLength++;
    
    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIECalledPartyNumber);
    ieLength += 4;
    
    addMessageLength(ieLength);

    return;
}

void uniPdu :: encodeCalledPartySubaddress(void)
{
    pfStorage &storage = (*this)[uniCalledPartySubaddressStr];
    pfUlong ieLength = 0;

    pfUlong ntype = storage.getInteger(uniCalledPS_TypeStr);
    pfUlong oddEven = storage.getInteger(uniCalledPS_OddEvenStr);
    string digits = storage.getString(uniCalledPS_DigitsStr);
    
    ieLength += toolEncodeNSAP(digits);
    putSpare(3);
    putBits(1, oddEven);
    putBits(3, ntype);
    putExtension(1);
    ieLength++;
        
    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIECalledPartySubaddress);
    ieLength += 4;
    
    addMessageLength(ieLength);

    return;
}

void uniPdu :: encodeCallingPartyNumber(void)
{
    pfStorage &storage = (*this)[uniCallingPartyNumberStr];
    pfUlong ieLength = 0;
    pfUlong extension = 1;
    
    pfUlong type = storage.getInteger(uniCallingPartyNumber_TypeStr);
    pfUlong plan = storage.getInteger(uniCallingPartyNumber_PlanStr);
    string digits = storage.getString(uniCallingPartyNumber_DigitsStr);
    
    if (plan == B0000_0010)
    {
        // NSAP encoding
        ieLength += toolEncodeNSAP(digits);
    }
    else
    {
        // IA5 encoding
        ieLength += toolEncodeISDN(digits);
    }

    if ((storage.isAvailable(uniCallingPartyNumber_PresentIndStr) != 0) &&
        (storage.isAvailable(uniCallingPartyNumber_ScreeningIndStr) != 0))
    {
        putBits(2, storage.getInteger(uniCallingPartyNumber_ScreeningIndStr));
        putSpare(3);
        putBits(2, storage.getInteger(uniCallingPartyNumber_PresentIndStr));
        putExtension(1);
        extension = 0;
        ieLength++;
    }
    
    putBits(4, plan);
    putBits(3, type);
    putExtension(extension);
    ieLength++;
    
    putBits(16, ieLength);
    putBits(8, B1000_0000);
    putBits(8, uniIECallingPartyNumber);
    ieLength += 4;
    
    addMessageLength(ieLength);

    return;
}    

void uniPdu :: encodeCallingPartySubaddress(void)
{
    pfStorage &storage = (*this)[uniCallingPartySubaddressStr];
    pfUlong ieLength = 0;

    pfUlong ntype = storage.getInteger(uniCallingPS_TypeStr);
    pfUlong oddEven = storage.getInteger(uniCallingPS_OddEvenStr);
    string digits = storage.getString(uniCallingPS_DigitsStr);
    
    ieLength += toolEncodeNSAP(digits);
    putSpare(3);
    putBits(1, oddEven);
    putBits(3, ntype);
    putExtension(1);
    ieLength++;
        
    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIECallingPartySubaddress);
    ieLength += 4;
    
    addMessageLength(ieLength);

    return;
}

void uniPdu :: encodeCallState(void)
{
    pfStorage &storage = (*this)[uniCallStateStr];
    pfUlong callState = storage.getInteger(uniCallState_StateStr);

    putBits(6, callState);
    putSpare(2);
    putBits(16, 1); // length
    putBits(8, standardInstructionField);
    putBits(8, uniIECallState);

    addMessageLength(5);
    
    return;
}

void uniPdu :: encodeCause(void)
{
    encodeOneCause((*this)[uniCauseStr]);
    
    return;
}

void uniPdu :: encodeConnectionIdentifier(void)
{
    pfStorage &storage = (*this)[uniConnectionIdentifierStr];
    pfUlong vpci = storage.getInteger(uniConnectionIdentifier_VPCIStr);
    pfUlong vci = storage.getInteger(uniConnectionIdentifier_VCIStr);

    // ++TODO++ should we check if vpci or vci is too long
    putBits(16, vci);
    putBits(8, vpci);
    putBits(8, 0);
    putBits(3, B0000_0000); // Exlusive VPCI; exclusive VCI
    putBits(2, B0000_0001); // VP Associated Signaling
    putSpare(2);
    putExtension(1); 
    putBits(16, 5);
    putBits(8, standardInstructionField);
    putBits(8, uniIEConnectionIdentifier);

    addMessageLength(9);

    return;
}

void uniPdu :: encodeEndpointReference(void)
{
    pfUlong refId = getInteger(uniEndpointReferenceStr);
    
    putBits(16, refId); // Flag + id
    putBits(8, 0); // Type : locally defined integer
    putBits(16, 3); // Length : 3
    putBits(8, standardInstructionField);
    putBits(8, uniIEEndpointReference);

    addMessageLength(7);
    
    return;
}

void uniPdu :: encodeEndpointState(void)
{
    pfStorage &storage = (*this)[uniEndpointStateStr];
    pfUlong party = storage.getInteger(uniEndpointState_PartyStateStr);
    
    putBits(6, party);
    putSpare(2);
    putBits(16, 1);
    putBits(8, standardInstructionField);
    putBits(8, uniIEEndpointState);

    addMessageLength(5);
    
    return;
}

void uniPdu :: encodeQoSParameters(void)
{
    // changing this method
    pfStorage &storage = (*this)[uniQoSParametersStr];
    pfUlong classForward = storage.getInteger(uniQoS_ForwardStr);
    pfUlong classBackward = storage.getInteger(uniQoS_BackwardStr);
   
    pfUlong coding = specificInstructionField;
    if ((classForward == 0) && (classBackward == 0))
    {
        coding = standardInstructionField;
    }

    putBits(8, classBackward);
    putBits(8, classForward);
    putBits(16, 2);
    putBits(8, coding);
    putBits(8, uniIEQoSParameters);

    addMessageLength(6);

    return;
}

void uniPdu :: encodeRestartIndicator(void)
{
    pfStorage &storage = (*this)[uniRestartIndicatorStr];
    
    putBits(3, storage.getInteger(uniRestartIndicator_ClassStr));
    putSpare(4);
    putExtension(1);
 
    putBits(16, 1);
    putBits(8, standardInstructionField);
    putBits(8, uniIERestartIndicator);
 
    addMessageLength(5);
 
    return;
}

void uniPdu :: encodeTransitNetworkSelection(void)
{
    pfUlong ieLength = 0;

    pfStorage &storage = (*this)[uniTransitNetworkSelectionStr];
    string digits = storage.getString(uniTNS_NetworkIdentificationStr);

    ieLength += toolEncodeISDN(digits);

    putBits(4, B0000_0001);
    putBits(3, B0000_0010);
    putExtension(1);
    ieLength++;

    putBits(16, ieLength);
    putBits(8, standardInstructionField);
    putBits(8, uniIETransitNetworkSelection);
    ieLength += 4;

    addMessageLength(ieLength);

    return;
}

//
// Method: encodeOneCause
//
// Description:
//

void uniPdu :: encodeOneCause(pfStorage &storage_)
{
    pfUlong location = storage_.getInteger(uniCause_LocationStr);
    pfUlong cause = storage_.getInteger(uniCause_ValueStr);
    pfUlong coding = standardInstructionField;

    if (cause == uniCauseValue_UserRejectsAllCallsWithCLIR)
    {
        coding = specificInstructionField;
    }

    pfUlong ieLength = 0;

    // Diagnostics 
    if (storage_.isAvailable(uniCause_IETypeListStr) != 0)
    {
        pfFrame types = storage_.getFrame(uniCause_IETypeListStr);
        while (types.length() > 0)
        {
            putBits(8, types.getFirst());
            ieLength++;
        }
    }
    else if (storage_.isAvailable(uniCause_MessageTypeStr) != 0)
    {
        putBits(8, storage_.getInteger(uniCause_MessageTypeStr));
        ieLength++;
    }
    else if (storage_.isAvailable(uniCause_IETypeStr) != 0)
    {
        putBits(8, storage_.getInteger(uniCause_IETypeStr));
        ieLength++;
    }
    else if ((storage_.isAvailable(uniCause_VPCIStr) != 0) &&
             (storage_.isAvailable(uniCause_VCIStr) != 0))
    {
        putBits(16, storage_.getInteger(uniCause_VCIStr));
        putBits(16, storage_.getInteger(uniCause_VPCIStr));
        ieLength += 4;
    }

    // Main 
    putBits(7, cause);
    putExtension(1);
    putBits(4, location); 
    putSpare(3);
    putExtension(1);
    ieLength += 2;

    putBits(16, ieLength);
    putBits(8, coding);
    putBits(8, uniIECause);
    ieLength += 4;

    addMessageLength(ieLength);
    
    return;
}

//
// Method: decodeIEs
//
// Description:
//      Decodes variable length information elements.
//      Allowed and required types of IEs should be listed
//      in typeSet_ parameter (see description of decodeMessage).
//      Looping proceeds until all messages are decoded or an error
//      occurs.
//

void uniPdu :: decodeIEs(void)
{
    // All mandatory IEs must be included. Checking is done by removing
    // mandatory IE type identifiers from the set, one by one.
    IETypeSet mandatory = _mandatory;

    // Frame for invalid mandatory and optional ies
    pfFrame invalidMandatoryIEs;
    pfFrame invalidOptionalIEs;
    pfFrame unrecognizedIEs;

    while (frameLength() > 0)
    {
        try {
            IEType elementType = decodeIE();
            mandatory.erase(elementType);            
        }
        catch (uniIEFieldErrorException &fieldError)
        {
            fieldError.printInfo();

            IEType ieType = IEType(fieldError.getType());
            if (ieType != uniIEUndefined)
            {
                if (isMandatoryIE(ieType) != 0)
                {
                    debugPfUlong("Invalid Mandatory IE Contents", ieType);
                    invalidMandatoryIEs.putLast(ieType);
                }
                else
                {
                    debugPfUlong("Invalid Optional IE Contents", ieType);
                    invalidOptionalIEs.putLast(ieType);
                }
                mandatory.erase(ieType);
            }
        }
        catch (uniUnrecognizedIEException &unrecException)
        {
            IEType ie = unrecException.getType();
            debugPfUlong("Unrecognized ie", ie);
            unrecognizedIEs.putLast(ie);
        }
        catch (uniDiscardIEException)
        {
            debugUser("Discarding IE");
        }
        catch (pfNameAlreadyDefinedException)
        {
            debugUser("Discarding duplicate IE");
            skipIE();
        }
        catch (pfException &undefException)
        {
            undefException.printInfo();
        }
    }
    
    if (mandatory.empty() == 0)
    {
        pfFrame missingMandatories;
        while (mandatory.empty() == 0)
        {
            pfUlong ieType = *(mandatory.begin());
            missingMandatories.putLast(ieType);
            mandatory.erase(mandatory.begin());
            debugPfUlong("Missing Mandatory IE Error", ieType);
        }
        errorInfoType tmp(new uniErrorInfo(
            uniCauseValue_MandatoryIEIsMissing));
        _errorInfo = tmp; 
        _errorInfo->setIEList(missingMandatories);
        _errorInfo->setFatalError();
    }
    else if (invalidMandatoryIEs.length() != 0)
    {
        errorInfoType tmp(new uniErrorInfo(
            uniCauseValue_InvalidIEContents));
        _errorInfo = tmp;
        _errorInfo->setIEList(invalidMandatoryIEs);
        _errorInfo->setFatalError();
    }
    else if (invalidOptionalIEs.length() != 0)
    {
        errorInfoType tmp(new uniErrorInfo(
            uniCauseValue_InvalidIEContents));
        _errorInfo = tmp;
        _errorInfo->setIEList(invalidOptionalIEs);
    }
    else if (unrecognizedIEs.length() != 0)
    {
        errorInfoType tmp(new uniErrorInfo(
            uniCauseValue_IENonexistent));
        _errorInfo = tmp;
        _errorInfo->setIEList(unrecognizedIEs);
    }

    return;
}

//
// Method: decodeIE
//
// Description:
//      Decodes one (next) information element and returns
//      its type. 
//
           
uniPdu::IEType uniPdu :: decodeIE(void)
{    
    if (pfUlong(frameLength()) < uniIEMinimumSize)
    {
        debugUser("Frame too short for IE");
        skip(frameLength()*8); // Skip rest of the frame
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    IEType elementIdentifier = IEType(getBits(8));

    debugPfUlong("Decoding ie", elementIdentifier);
    
    skip(1); // ext == 1
    pfUlong standard = getBits(2);
    pfUlong IEFlag = getBits(1);
    skip(1); // reserved
    pfUlong IEActionInd = getBits(3);

    // Check possible errors
    if ((standard != 0) && (standard != 3))
    {
        debugPfUlong("Invalid IE standard", standard);
        throw uniIEFieldErrorException(PF_EX_INFO, elementIdentifier);
    }

    if (IEFlag != 0)
    {
        switch (IEActionInd)
        {
            case B0000_0000 : // clear call
                debugUser("Clear Call by IET-action field (not impl.)");
                // Not implemented yet
                break;

            case B0000_0001 : // Discard IE and proceed
                debugUser("Discard IE and Proceed");
                skipIE();
                throw uniDiscardIEException(PF_EX_INFO);
                break;

            case B0000_0010 : // Discard IE, proceed and report status
                debugUser("Discard IE, Proceed, Report");
                skipIE();
                {
                    errorInfoType tmp(new uniErrorInfo(
                        uniCauseValue_NormalUnspecified));
                    _errorInfo = tmp;
                }
                throw uniDiscardIEException(PF_EX_INFO);
                break;

            case B0000_0101 : // Discard message and ignore
                debugUser("Discard Message and Ignore");
                throw uniDiscardMessageException(PF_EX_INFO);
                break;

            case B0000_0110 : // Discard message and report status
                debugUser("Discard Message and Report");
                {
                    errorInfoType tmp(new uniErrorInfo(
                        uniCauseValue_NormalUnspecified));
                    _errorInfo = tmp;
                }
                throw uniDiscardMessageException(PF_EX_INFO, true);
                break;

            default :
                skipIE();
                throw uniIEFieldErrorException(PF_EX_INFO, elementIdentifier);
        }
    }
    
    if ((_mandatory.find(elementIdentifier) == _mandatory.end()) &&
        (_optional.find(elementIdentifier) == _optional.end()))
    {
        skipIE();
        // unrecognized ie occured, save identifier
        throw uniDiscardIEException(PF_EX_INFO);
    }
    else
    {
        try
        {
            switch (elementIdentifier)
            {
                case uniIEAALParameters :
                    decodeAALParameters();
                    break;
                    
                case uniIEATMTrafficDescriptor :
                    decodeATMTrafficDescriptor();
                    break;
                    
                case uniIEBBearerCapability :
                    decodeBroadbandBearerCapability();
                    break;
                    
                case uniIEBLockingShift :
                    decodeBroadbandLockingShift();
                    break;
                    
                case uniIEBLowLayerInfo :
                    decodeBroadbandLowLayerInfo();
                    break;
                    
                case uniIEBHighLayerInfo :
                    decodeBroadbandHighLayerInfo();
                    break;
                    
                case uniIEBNonlockingShift :
                    decodeBroadbandNonlockingShift();
                    break;
                    
                case uniIEBRepeatIndicator :
                    decodeBroadbandRepeatIndicator();
                    break;
                    
                case uniIEBSendingComplete :
                    decodeBroadbandSendingComplete();
                    break;
                    
                case uniIECallingPartyNumber :
                    decodeCallingPartyNumber();
                    break;

                case uniIECallingPartySubaddress :
                    decodeCallingPartySubaddress();
                    break;
                    
                case uniIECalledPartyNumber :
                    decodeCalledPartyNumber();
                    break;
                    
                case uniIECalledPartySubaddress :
                    decodeCalledPartySubaddress();
                    break;
                    
                case uniIECallState :
                    decodeCallState();
                    break;
                    
                case uniIECause :
                    decodeCause();
                    break;
                    
                case uniIEConnectionIdentifier :
                    decodeConnectionIdentifier();
                    break;
                    
                case uniIEEndpointReference :
                    decodeEndpointReference();
                    break;
                    
                case uniIEEndpointState :
                    decodeEndpointState();
                    break;
                    
                case uniIEQoSParameters :
                    decodeQoSParameters();
                    break;
                    
                case uniIERestartIndicator :
                    decodeRestartIndicator();
                    break;
                    
                case uniIETransitNetworkSelection :
                    decodeTransitNetworkSelection();
                    break;
                    
                default:
                    skipIE();
                    debugPfUlong("ERROR: Unexpected ie type accepted.",
                                 elementIdentifier);
                    elementIdentifier = uniIEUndefined;
            }
        }
        catch (uniIEFieldErrorException &fieldError)
        {
            fieldError.setType(elementIdentifier);
            throw;
        }
    }
    
    return elementIdentifier;
}

//
// Method: decodeCommonFields
//
// Description:
//      Decodes Q.2931 message header.
//
// Throws:
//      uniDiscardMessageException
//

void uniPdu :: decodeCommonFields(void)    
{
    // Check if the message is of right type (ie. protocol
    // discriminator matches)
    
    pfByte discriminator = getBits(8);
    if (discriminator != uniProtocolDiscriminator)
    {
        debugPfUlong("Invalid Protocol Discriminator", discriminator);
        throw uniDiscardMessageException(PF_EX_INFO);
    }

    // Call reference
    pfByte referenceLength = getBits(8);
    if (referenceLength != 3)
    {
        throw uniDiscardMessageException(PF_EX_INFO);
    }
    setInteger(uniCallReferenceFlagStr, getBits(1));
    setInteger(uniCallReferenceStr, getBits(23));
    setMuxReference();
    
    // Message type

    setInteger(uniMessageTypeStr, getBits(8));
    getBits(1); // get ext
    skip(2); // spare
    pfUlong flag = getBits(1); // get flag
    skip(2); // spare
    // action indicator (see. 5.4.4.1, Note 1)
    pfUlong indicator = getBits(2); 
    
    if (flag != 0)
    {
        defineInteger(uniUnrecognizedMsgActionStr);
        setInteger(uniUnrecognizedMsgActionStr, indicator);
    }                

    // Message length

    setInteger(uniMessageLengthStr, getBits(16));

    return;
}

//
// Method: IE decoding methods
//
// Description:
//      These methods decode one of several different
//      variable length information elements. 
//

void uniPdu :: decodeAALParameters(void)
{
    pfStorage &storage = defineAALParameters();

    pfLong ieLength = checkIELength(1, 17);

    pfUlong aalType = getBits(8);
    storage.setInteger(uniAALP_TypeStr, aalType);
    ieLength--;

    switch (aalType)
    {
        case B0000_0001 : // AAL Type 1
            
            while (ieLength > 0)
            {
                pfUlong identifier = getBits(8);
                ieLength--;
                switch (identifier)
                {
                    case B1000_0101 : // Subtype
                        storage.setInteger(uniAALP_SubtypeStr, getBits(8));
                        ieLength--;
                        break;
                        
                    case B1000_0110 : // CBR Rate
                        storage.setInteger(uniAALP_CBRRateStr, getBits(8));
                        ieLength--;
                        break;
                        
                    case B1000_0111 : // Multiplier
                        storage.setInteger(uniAALP_MultiplierStr,
                                           getBits(16));
                        ieLength -= 2;
                        break;
                        
                    case B1000_1000 : // Source Clock Freq. Recovery
                        storage.setInteger(uniAALP_SourceClockRecoveryStr,
                                           getBits(8));
                        ieLength--;
                        break;
                        
                    case B1000_1001 : // Error Correction Method
                        storage.setInteger(uniAALP_ErrorCorrectionMethodStr,
                                           getBits(8));
                        ieLength--;
                        break;
                        
                    case B1000_1010 : // Struc. Data Transfer
                        storage.setInteger(uniAALP_DataTransferBlocksizeStr,
                                           getBits(16));
                        ieLength -= 2;
                        break;
                        
                    case B1000_1011 : // Partially Filled
                        storage.setInteger(uniAALP_PartiallyFilledStr,
                                           getBits(8));
                        ieLength--;
                        break;
                        
                } // switch
            } // while
            break;
            
        case B0000_0011 : // AAL Type 3/4
        case B0000_0101 : // AAL Type 5
            
            while (ieLength > 0)
            {
                pfUlong identifier = getBits(8);
                ieLength--;
                switch (identifier)
                {
                    case B1000_1100 : // Forward Max CPCS-SDU Size
                        storage.setInteger(
                            uniAALP_ForwardMaxSDUSizeStr, getBits(16));
                        ieLength -= 2;
                        break;
                        
                    case B1000_0001 : // Backward Max CPCS-SDU Size
                        storage.setInteger(
                            uniAALP_BackwardMaxSDUSizeStr, getBits(16));
                        ieLength -= 2;
                        break;
                        
                    case B1000_0010 : // MID Range
                        storage.setInteger(
                            uniAALP_MIDRangeLowStr, getBits(16));
                        storage.setInteger(
                            uniAALP_MIDRangeHighStr, getBits(16));
                        ieLength -= 4;
                        break;
                        
                    case B1000_0100 : // SSCS Type
                        storage.setInteger(uniAALP_SSCSTypeStr, getBits(8));
                        ieLength--;
                        break;                            
                }   
            }
                    
        case B0001_0000 : // User specified AAL Type
            
            if (ieLength > 0)
            {
                setInteger(uniAALP_UserDefinedInfoStr, getBits(32));
                ieLength -= 4;
            }
            break;
    }    
    
    return;
}

void uniPdu :: decodeATMTrafficDescriptor(void)
{
    pfStorage &storage = defineATMTrafficDescriptor();
    pfLong ieLength = checkIELength(0, 26);

    // Initialize combination bit patterns. 
    // These variables contain information of which elements 
    // are present in ie and which are not. Bit pattern method
    // speeds up checking allowed parameter combinations.
    pfUlong fcombination = TD_Unspecified;
    pfUlong bcombination = TD_Unspecified;    
    
    // Decode all present parameters  
    while (ieLength > 0)
    {
        pfUlong identifier = getBits(8);
        ieLength--;

        switch (identifier)
        {
            case B1000_0010 : // Forward Peak Cell Rate CLP = 0
                storage.setInteger(uniATD_ForwardPeakCellRateCLP0Str,
                                   getBits(24));
                ieLength -= 3;
                fcombination |= TD_PCR_CLP0_MASK;
                break;

            case B1000_0011 : // Backward Peak Cell Rate CLP = 0
                storage.setInteger(uniATD_BackwardPeakCellRateCLP0Str,
                                   getBits(24));
                ieLength -= 3;
                bcombination |= TD_PCR_CLP0_MASK;
                break;

            case B1000_0100 : // Forward Peak Cell Rate CLP = 0 + 1
                storage.setInteger(uniATD_ForwardPeakCellRateCLP1Str,
                                   getBits(24));
                ieLength -= 3;
                fcombination |= TD_PCR_CLP1_MASK;
                break;

            case B1000_0101 : // Backward Peak Cell Rate CLP = 0 + 1
                storage.setInteger(uniATD_BackwardPeakCellRateCLP1Str,
                                   getBits(24));
                ieLength -= 3;
                bcombination |= TD_PCR_CLP1_MASK;
                break;

            case B1000_1000 : // Forward Sustainable Cell Rate CLP = 0 
                storage.setInteger(uniATD_ForwardSustainableCLP0Str,
                                   getBits(24));
                ieLength -= 3;
                fcombination |= TD_SCR_CLP0_MASK;
                break;

            case B1000_1001 : // Backward Sustainable Cell Rate CLP = 0 
                storage.setInteger(uniATD_BackwardSustainableCLP0Str,
                                   getBits(24));
                ieLength -= 3;
                bcombination |= TD_SCR_CLP0_MASK;
                break;

            case B1001_0000 : // Forward Sustainable Cell Rate CLP = 0 + 1 
                storage.setInteger(uniATD_ForwardSustainableCLP1Str,
                                   getBits(24));
                ieLength -= 3;
                fcombination |= TD_SCR_CLP1_MASK;
                break;

            case B1001_0001 : // Backward Sustainable Cell Rate CLP = 0 + 1
                storage.setInteger(uniATD_BackwardSustainableCLP1Str,
                                   getBits(24));
                ieLength -= 3;
                bcombination |= TD_SCR_CLP1_MASK;
                break;

            case B1010_0000 : // Forward Maximum Burst Size CLP = 0 
                storage.setInteger(uniATD_ForwardMaxBurstSizeCLP0Str,
                                   getBits(24));
                ieLength -= 3;
                fcombination |= TD_MBS_CLP0_MASK;
                break;

            case B1010_0001 : // Backward Maximum Burst Size CLP = 0 
                storage.setInteger(uniATD_BackwardMaxBurstSizeCLP0Str,
                                   getBits(24));
                ieLength -= 3;
                bcombination |= TD_MBS_CLP0_MASK;
                break;

            case B1011_0000 : // Forward Maximum Burst Size CLP = 0 + 1 
                storage.setInteger(uniATD_ForwardMaxBurstSizeCLP1Str,
                                   getBits(24));
                ieLength -= 3;
                fcombination |= TD_MBS_CLP1_MASK;
                break;

            case B1011_0001 : // Backward Maximum Burst Size CLP = 0 + 1
                storage.setInteger(uniATD_BackwardMaxBurstSizeCLP1Str,
                                   getBits(24));
                ieLength -= 3;
                bcombination |= TD_MBS_CLP1_MASK;
                break;

            case B1011_1110 : // Best Effort
                storage.setBooleanTrue(uniATD_BestEffortStr);
                fcombination |= TD_BE_MASK;
                bcombination |= TD_BE_MASK;
                break;

            case B1011_1111 : // Traffic Management Options
                skip(6);

                if (getBits(1) != 0)
                {
                    storage.setBooleanTrue(uniATD_TaggingBackwardStr);
                    bcombination |= TD_TAG_MASK;
                }
                else
                {
                    storage.setBooleanFalse(uniATD_TaggingBackwardStr);
                }
                if (getBits(1) != 0)
                {
                    storage.setBooleanTrue(uniATD_TaggingForwardStr);
                    fcombination |= TD_TAG_MASK;
                }
                else
                {
                    storage.setBooleanFalse(uniATD_TaggingForwardStr);
                }
                ieLength--;
                break;

          default:
              throw uniIEFieldErrorException(PF_EX_INFO);
              break;
        }
    }

    storage.setInteger(uniATD_ForwardCombinationStr, fcombination);
    storage.setInteger(uniATD_BackwardCombinationStr, bcombination);

    return;
}

void uniPdu :: decodeBroadbandBearerCapability(void)
{
    pfStorage &storage = defineBroadbandBearerCapability();
    checkIELength(2, 3);

    getExtension();
    skipInExtension(2); // spare
    pfUlong bclass = getBitsInExtension(5);
    getExtension();

    skipInExtension(2); // spare
    pfUlong ttype = getBitsInExtension(3);
    pfUlong treq = getBitsInExtension(2);

    // Check bearer class and optional parameters compatibility
    pfUlong check = ttype + treq;
        
    if (((bclass == BCOB_X) && ((check == 1) || (check == 3))) ||
        ((bclass != BCOB_X) && (isInExtension() != 0)))
    {
        // In case BCOB_X either 
        // 1) ttype == CBR and treq != Yes,
        // 2) ttype != CBR and treq == Yes
        // which indicates wrong combination. 
        // If class BCOB_A or BCOB_C, parameters should not 
        // exist.
        bclass = Unspecified;
    }

    storage.setInteger(uniBBC_TrafficTypeStr, ttype);
    storage.setInteger(uniBBC_TimingRequirementsStr, treq);
    storage.setInteger(uniBBC_BearerClassStr, bclass);
    endExtension();
   
    getExtension();
    storage.setInteger(uniBBC_SusceptibilityToClippingStr,
                       getBitsInExtension(2));
    skipInExtension(3); // spare
    storage.setInteger(uniBBC_UserPlaneConnectionConfigurationStr,
                       getBitsInExtension(2));
    endExtension();

    return;
}

void uniPdu :: decodeBroadbandHighLayerInfo(void)
{
    pfStorage &storage = defineBroadbandHighLayerInfo();
    pfLong ieLength = checkIELength(1, 9);

    getExtension();
    //++TODO++ Erase "if" statement after storage can handle undefines 
    if (isInExtension() != 0)
    {
        storage.setInteger(uniBHLI_TypeStr, getBitsInExtension(7));
    }
    decreaseIfInExtension(ieLength);
    endExtension();
    
    pfFrame info;
    while (ieLength > 0)
    {
        info.putLast(getBits(8));
        ieLength--;
    }   
    storage.setFrame(uniBHLI_InfoStr, info);

    return;
}

void uniPdu :: decodeBroadbandLockingShift(void)
{
    defineBroadbandLockingShift();
    decodeUnimplemented();
    return;
}

void uniPdu :: decodeBroadbandLowLayerInfo(void)
{    
    char ieNumber = '1';
    while ((ieNumber < '4') && 
	   (isVariableDefined(uniBroadbandLowLayerInfoStr + 
			      ieNumber) != 0))
    {
        ieNumber++;
    }

    if ((ieNumber == '4') ||
	((ieNumber > '1') && 
	 (isAvailable(uniBroadbandRepeatIndicatorStr) == 0)))
    {
        skipIE();
	throw uniDiscardIEException(PF_EX_INFO);
    }

    pfStorage &storage = defineBroadbandLowLayerInfo(ieNumber);
    pfLong ieLength = checkIELength(0, 13);

    while (ieLength > 0)
    {
        getExtension();
        pfUlong layerId = getBitsInExtension(2);
        pfUlong userInfo = getBitsInExtension(5);
        decreaseIfInExtension(ieLength);

        // Declarations for switch blocks
        pfUlong ipi;
        
        switch (layerId)
        {            
            case 1 :
                endExtension();
                storage.setInteger(uniBLLI_Layer1UserInfoStr,
                                   userInfo);
                break;
            
            case 2 :
                storage.setInteger(uniBLLI_Layer2UserInfoStr,
                                   userInfo);
                switch (userInfo)
                {
                    case B0000_0110 : // X.25 LL
                    case B0000_0111 : // X.25 ML
                    case B0000_1001 : // HDLC ARM
                    case B0000_1010 : // HDLC NRM
                    case B0000_1011 : // HDLC ABM
                    case B0000_1110 : // X.75
                    case B0001_0001 : // ISO 7776 DTE-DTE
                    
                        getExtension();
                        storage.setInteger(uniBLLI_Layer2ModeStr,
                                           getBitsInExtension(2));
                        skipInExtension(3);
                        skipInExtension(2); // Q.233 not used
                        decreaseIfInExtension(ieLength);
                        getExtension();
                        storage.setInteger(uniBLLI_WindowSizeStr,
                                           getBitsInExtension(7));
                        decreaseIfInExtension(ieLength);
                        endExtension();
                        break;
                        
                    case B0001_0000 : // User Specified
                        
                        getExtension();
                        storage.setInteger(uniBLLI_Layer2ProtocolInfoStr,
                                           getBitsInExtension(7));
                        decreaseIfInExtension(ieLength);
                        endExtension();
                        break;

                    default:
                        skip(ieLength * 8);
                        throw uniIEFieldErrorException(PF_EX_INFO);
                }                        
                break;

            case 3 :
                storage.setInteger(uniBLLI_Layer3UserInfoStr, 
				   userInfo);
                switch (userInfo)
                {
                    case B0000_0110 : // X.25 
                    case B0000_0111 : // X.
                    case B0000_1000 : // X.223/ISO 8878
                        getExtension();
                        storage.setInteger(uniBLLI_Layer3ModeStr,
                                           getBitsInExtension(2));
                        skipInExtension(5);
                        decreaseIfInExtension(ieLength);
                        getExtension();
                        skipInExtension(3);
                        storage.setInteger(uniBLLI_DefaultPacketSizeStr,
                                           getBitsInExtension(4));
                        decreaseIfInExtension(ieLength);
                        getExtension();
                        storage.setInteger(uniBLLI_PacketWindowSizeStr,
                                           getBitsInExtension(7));
                        decreaseIfInExtension(ieLength);
                        endExtension();
                        break;
                        
                    case B0001_0000 : // User Specified
                        
                        getExtension();
                        storage.setInteger(uniBLLI_Layer3ProtocolInfoStr,
                                           getBitsInExtension(7));
                        decreaseIfInExtension(ieLength); 
                        endExtension();
                        break;
                        
                    case B0000_1011 : // ISO/IEC TR 9577
                        
                        getExtension();
                        ipi = getBitsInExtension(7);
                        decreaseIfInExtension(ieLength);
                        getExtension();
                        ipi = (ipi << 1) & getBitsInExtension(1);
                        storage.setInteger(uniBLLI_IPIStr, ipi);
                        skipInExtension(6);
                        decreaseIfInExtension(ieLength);
                        endExtension();
                        if (ipi == B1000_0000)
                        {
                            getExtension();
                            skipInExtension(2); // SNAP ID
                            skipInExtension(5);
                            storage.setInteger(uniBLLI_OUIStr,
                                               getBitsInExtension(24));
                            storage.setInteger(uniBLLI_PIDStr,
                                               getBitsInExtension(16));
                            decreaseIfInExtension(ieLength, 6);
                            endExtension();
                        }
                        break;
                        
                    default:
                        skip(ieLength * 8);
                        throw uniIEFieldErrorException(PF_EX_INFO);
                } // switch (case 3)
                break;
                
            default:
                skip(ieLength * 8);
                throw uniIEFieldErrorException(PF_EX_INFO);
        } // switch
    }
        
    return;
}

void uniPdu :: decodeBroadbandNonlockingShift(void)
{
    defineBroadbandNonlockingShift();
    decodeUnimplemented();
    return;
}

void uniPdu :: decodeBroadbandRepeatIndicator(void)
{
    defineBoolean(uniBroadbandRepeatIndicatorStr);

    checkIEAbsLength(1);

    skip(4);
    pfUlong indicator = getBits(4);
    if (indicator != B0000_0010)
    {
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    setBooleanTrue(uniBroadbandRepeatIndicatorStr);
    
    return;
}

void uniPdu :: decodeBroadbandSendingComplete(void)
{
    pfStorage &storage = defineBroadbandSendingComplete();
    checkIEAbsLength(1);

    getExtension();
    pfUlong indicator = getBits(7);
    endExtension();

    if (indicator != B0010_0001)
    {
        storage.setBooleanFalse(uniBSC_FlagStr);
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    storage.setBooleanTrue(uniBSC_FlagStr);
    
    return;
}

void uniPdu :: decodeCallingPartyNumber(void)
{
    pfStorage &storage = defineCallingPartyNumber();
    pfLong ieLength = checkIELength(1, 22);

    getExtension();
    pfUlong ntype = getBitsInExtension(3);
    storage.setInteger(uniCallingPartyNumber_TypeStr, ntype);
    pfUlong plan = getBitsInExtension(4);
    storage.setInteger(uniCallingPartyNumber_PlanStr, plan);
    decreaseIfInExtension(ieLength);

    getExtension();
    // ++TODO++ This "if" is set since storage can handle "undefined" values
    if (isInExtension() != 0)
    {
        storage.setInteger(uniCallingPartyNumber_PresentIndStr,
                           getBitsInExtension(2));
        skipInExtension(3);
        storage.setInteger(uniCallingPartyNumber_ScreeningIndStr,
                           getBitsInExtension(2));
    }
    decreaseIfInExtension(ieLength);
    endExtension();
    
    string digits;
    if (plan == B0000_0010) // ATM Endsystem
    {
        if (ntype != B0000_0000) // Unknown required
        {
            throw uniIEFieldErrorException(PF_EX_INFO);
        }
        // NSAP decoding
        digits = toolDecodeNSAP(ieLength);
    }
    else
    {
        if (ntype != B0000_0001) // International number required
        {
            throw uniIEFieldErrorException(PF_EX_INFO);
        }
        // E.164 decoding
        digits = toolDecodeISDN(ieLength);
    }

    storage.setString(uniCalledPartyNumber_DigitsStr, digits);
    
    return;
}

void uniPdu :: decodeCallingPartySubaddress(void)
{
    pfStorage &storage = defineCallingPartySubaddress();
    pfLong ieLength = checkIELength(1, 21);

    getExtension();
    pfUlong ntype = getBitsInExtension(3);
    storage.setInteger(uniCallingPS_TypeStr, ntype);
    storage.setInteger(uniCallingPS_OddEvenStr, getBitsInExtension(1));
    skipInExtension(3);
    decreaseIfInExtension(ieLength);
    endExtension();

    string digits;
    digits = toolDecodeNSAP(ieLength);

    storage.setString(uniCallingPS_DigitsStr, digits);
    
    return;
}

void uniPdu :: decodeCalledPartyNumber(void)
{
    debugUser("uniPdu::decodeCalledPartyNumber starting");
    pfStorage &storage = defineCalledPartyNumber();
    pfLong ieLength = checkIELength(1, 21);

    getExtension();
    pfUlong ntype = getBitsInExtension(3);
    storage.setInteger(uniCalledPartyNumber_TypeStr, ntype);
    pfUlong plan = getBitsInExtension(4);
    storage.setInteger(uniCalledPartyNumber_PlanStr, plan);
    decreaseIfInExtension(ieLength);
    endExtension();

    string digits;
    if (plan == B0000_0010) // ATM Endsystem
    {
        debugUser("uniPdu::decodeCalledPartyNumber atm endsystem address");
        if (ntype != B0000_0000) // Unknown required
        {
            throw uniIEFieldErrorException(PF_EX_INFO);
        }
        // NSAP decoding
        digits = toolDecodeNSAP(ieLength);
    }
    else
    {
        debugUser("uniPdu::decodeCalledPartyNumber isdn number");
        if (ntype != B0000_0001) // International number required
        {
            throw uniIEFieldErrorException(PF_EX_INFO);
        }
        // E.164 decoding
        digits = toolDecodeISDN(ieLength);
    }
    debugString("uniPdu::decodeCalledPartyNumber number", digits);

    storage.setString(uniCalledPartyNumber_DigitsStr, digits);

    debugUser("uniPdu::decodeCalledPartyNumber ending");
    return;
}

void uniPdu :: decodeCalledPartySubaddress(void)
{
    pfStorage &storage = defineCalledPartySubaddress();
    pfLong ieLength = checkIELength(1, 21);

    getExtension();
    pfUlong ntype = getBitsInExtension(3);
    storage.setInteger(uniCalledPS_TypeStr, ntype);
    storage.setInteger(uniCalledPS_OddEvenStr, getBitsInExtension(1));
    skipInExtension(3);
    decreaseIfInExtension(ieLength);
    endExtension();

    string digits;
    digits = toolDecodeNSAP(ieLength);

    storage.setString(uniCalledPS_DigitsStr, digits);
    
    return;
}

void uniPdu :: decodeCallState(void)
{
    pfStorage &storage = defineCallState();

    checkIEAbsLength(1);
    skip(2);
    storage.setInteger(uniCallState_StateStr, getBits(6));

    return;
}

void uniPdu :: decodeCause(void)
{
    pfStorage &storage = defineCause();
    
    pfUlong elementLength = checkIELength(2, 30);
    skip(4);
    pfUlong location = getBits(4);
    storage.setInteger(uniCause_LocationStr, location);
    skip(1);
    pfUlong causeValue = getBits(7);
    storage.setInteger(uniCause_ValueStr, causeValue);
    storage.setInteger(uniCause_ClassStr, causeValue >> 4);

    elementLength -= 2;

    //++TODO++
    skip(elementLength * 8); // Skip diagnostics for now

    // Checkings
    if ((location == B0000_0110) ||
        ((location > B0000_1000) &&
         (location != B0000_1010)))
    {
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    return;
}

void uniPdu :: decodeConnectionIdentifier(void)
{
    pfStorage &storage = defineConnectionIdentifier();
    checkIEAbsLength(5);

    getExtension();
    skipInExtension(2); 
    pfUlong VPAssosiated = getBitsInExtension(2);
    pfUlong preferredExclusive = getBitsInExtension(3);
    endExtension();
    
    if ((VPAssosiated != 1) || (preferredExclusive != 0))
    {
        skip(32); // skip rest
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    storage.setInteger(uniConnectionIdentifier_PrefExStr, preferredExclusive);
    storage.setInteger(uniConnectionIdentifier_VPAssosiatedStr, VPAssosiated);
    storage.setInteger(uniConnectionIdentifier_VPCIStr, getBits(16));
    storage.setInteger(uniConnectionIdentifier_VCIStr, getBits(16));
    
    return;
}

void uniPdu :: decodeEndpointReference(void)
{
    defineInteger(uniEndpointReferenceStr);
    checkIEAbsLength(3);
    
    // get Endpoint reference type (=0)
    pfUlong referenceType = getBits(8);    
    if (referenceType != 0) 
    {
        skip(16);
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    // Get reference. Flag must be negated: originating PMP has
    // flag zero. Flag is received in the terminating end as zero.
    // Now it turns to one and the PMP in here has flag set to one.
    // Returning message contains flag set to one indicating "The message
    // is sent to the side that originates the E.R." and when it is
    // negated, the original flag (and endpoint reference) is got.
    
    pfUlong refFlag = getBits(1);
    pfUlong refId = getBits(15);
    pfUlong reference = ((1 - refFlag) << 15) | refId; 
    
    setInteger(uniEndpointReferenceStr, reference);

    return;
}

void uniPdu :: decodeEndpointState(void)
{
    pfStorage &storage = defineEndpointState();
    
    checkIEAbsLength(1);

    skip(2);
    storage.setInteger(uniEndpointState_PartyStateStr, getBits(6));
    
    return;
}

void uniPdu :: decodeQoSParameters(void)
{
    pfStorage &storage = defineQoSParameters();
    checkIEAbsLength(2);

    storage.setInteger(uniQoS_ForwardStr, getBits(8));
    storage.setInteger(uniQoS_BackwardStr, getBits(8));
    
    return;
}

void uniPdu :: decodeRestartIndicator(void)
{
    pfStorage &storage = defineRestartIndicator();
    checkIEAbsLength(1);

    getExtension();
    skipInExtension(4);
    pfUlong restartClass = getBitsInExtension(3);
    endExtension();

    if ((restartClass != 0) && (restartClass != 2))
    {
        throw uniIEFieldErrorException(PF_EX_INFO);
    }
    
    storage.setInteger(uniRestartIndicator_ClassStr, restartClass);
    
    return;
}

void uniPdu :: decodeTransitNetworkSelection(void)
{
    pfStorage &storage = defineTransitNetworkSelection();
    pfLong ieLength = checkIELength(4, 5);

    getExtension();
    getBitsInExtension(3);
    getBitsInExtension(4);
    decreaseIfInExtension(ieLength);
    endExtension();

    debugUser("Before decodeISDN\n");
    string digits = toolDecodeISDN(ieLength);
    debugUser("After decodeISDN\n");
    debugUser(digits);
    storage.setString(uniTNS_NetworkIdentificationStr, digits);

    return;
}

//
// Method: decodeUnimplemented
//
// Description:
//     Decoding method for unimplemented IEs. REMOVE THIS WHEN NOT
//     NEEDED ANYMORE.
//

void uniPdu :: decodeUnimplemented(void)
{
    skipIE();
    return;
}

//
// Method: skipIE
//
// Description:
//     Skips an IE in the frame
//

void uniPdu :: skipIE(void)
{
    pfUlong contentsLength = checkIELength(0);
    skip(contentsLength * 8);
    return;
}

//
// Method: toolDecodeNSAP
//
// Description:
//     Decodes an NSAP address from the frame into a string.
//

string uniPdu :: toolDecodeNSAP(pfLong &ieLength)
{
    if (ieLength != 20)
    {
        skip(ieLength * 8);
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    string digits;
    while (ieLength > 0)
    {
        digits.append(1, (char) pfTools::decToHex(getBits(4)));
        digits.append(1, (char) pfTools::decToHex(getBits(4)));
        ieLength--;
    }

    return digits;
}

//
// Method: toolDecodeISDN
//
// Description:
//     Decodes an ISDN from the frame into a string
//

string uniPdu :: toolDecodeISDN(pfLong &ieLength_)
{
    string digits;
    pfUlong dummy;

    while (ieLength_ > 0) 
    {
        dummy = getBits(8);
        dummy = dummy & B0111_1111;
        digits.append(1, (char) dummy);
        ieLength_--;
    }

    return digits;
}

//
// Method: toolEncodeNSAP
//
// Description:
//     Encodes an NSAP address string into current frame.
//

pfUlong uniPdu :: toolEncodeNSAP(string &digits)
{
    pfUlong hexLength = 0;
    pfLong index;
    pfUlong digit;
    for (index = digits.length() - 1; index >= 0; index--)
    {
        //++TODO++ Error detection
        digit = digits[index];
        if (digit != '.')
        {
            putBits(4, pfTools::hexToDec(digit));
            hexLength++;
        }
    }
    if (hexLength != 40)
    {
        debugUser("Error in NSAP address!!");
        getBits(hexLength * 4);
        hexLength = 0;
    }
    else
    {
        hexLength /= 2;
    }  

    return hexLength;
}

//
// Method: toolEncodeISDN
//
// Description:
//     Encodes an ISDN string into current frame.
//

pfUlong uniPdu :: toolEncodeISDN(string &digits_)
{
    pfUlong length;
    pfUlong digit;
    pfLong index = digits_.length() - 1;

    for (length = 0; index >= 0; index--)
    {
        digit = digits_[index];
        digit = digit & B0111_1111;
        putBits(8, digit);
        length++;
    }

    return length;
}

//
// Method: checkIEAbsLength
//
// Description:
//     Encodes a `length' field from the frame and checks if it
//     is appropriate for current IE. The expected length is given
//     as a parameter.
//

void uniPdu :: checkIEAbsLength(const pfUlong length_)
{
    pfUlong contentsLength = getBits(16);
    
    if (pfUlong(frameLength()) < contentsLength)
    {
        skip(frameLength() * 8);
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    if (contentsLength != length_)
    {
        // Is it better to skip an amount of bits got as a parameter or
        // an amount of bits got from pdu??? This is because we (possibly)
        // want to continue decoding.
        skip(length_ * 8);
        throw uniIEFieldErrorException(PF_EX_INFO);
    }
   
    return;
}

//
// Method: checkIELength
//
// Description:
//     Encodes a `length' field from the frame and checks if
//     it is appropriate for current IE. The allowed range
//     of the value is given as a parameter.
//

pfUlong uniPdu :: checkIELength(const pfUlong rangeMin_,
                                const pfUlong rangeMax_)
{
    pfUlong contentsLength = getBits(16);

    if (pfUlong(frameLength()) < contentsLength)
    {
        skip(frameLength() * 8);
        throw uniIEFieldErrorException(PF_EX_INFO);
    }

    if ((contentsLength < rangeMin_) ||
        (contentsLength > rangeMax_))
    {
        skip(contentsLength * 8);
        throw uniIEFieldErrorException(PF_EX_INFO);
    }
    
    return contentsLength;
}

//
// Method: addMessageLength
//
// Description:
//     Adds amount_ into uniMessageLengthStr variable.
//

void uniPdu :: addMessageLength(pfUlong amount_)
{
    pfUlong currentSize = getInteger(uniMessageLengthStr);
    currentSize += amount_;
    setInteger(uniMessageLengthStr, currentSize);
    return;
}

//
// Method: mandatoryIE
//
// Description:
//     Returns if the IE of type type_ is mandatory or not in the
//     current pdu.
//

bool uniPdu :: isMandatoryIE(IEType type_) const
{
    bool result = _mandatory.find(type_) != _mandatory.end();
    return result;
}

//
// Method: defineAndSetInteger
//
// Description:
//     Sets an integer variable to given value. If the variable of name
//     variable_ is not defined, it will be defined.
//

void uniPdu :: defineAndSetInteger(string variable_, pfUlong int_)
{
    if (isVariableDefined(variable_) == 0)
    {
        defineInteger(variable_);
    }
    setInteger(variable_, int_);
    return;
}

uniMessageInputs *messageCast(pfState *state_)
{
    uniMessageInputs *state = dynamic_cast<uniMessageInputs*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    return state;
}

uniStatusMessageInputs *statusMessageCast(pfState *state_)
{
    uniStatusMessageInputs *state =
        dynamic_cast<uniStatusMessageInputs*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    return state;
}

uniRRNMessageInputs *rrnMessageCast(pfState *state_)
{
    uniRRNMessageInputs *state =
        dynamic_cast<uniRRNMessageInputs*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    return state;
}

uniRSNMessageInputs *rsnMessageCast(pfState *state_)
{
    uniRSNMessageInputs *state = dynamic_cast<uniRSNMessageInputs*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    return state;
}


//----------------------------------------------------------------------
// Class: uniSETUPpdu
//----------------------------------------------------------------------

uniSETUPpdu :: uniSETUPpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgSetup);

    _optional.insert(uniIEAALParameters);
    _mandatory.insert(uniIEATMTrafficDescriptor);
    _mandatory.insert(uniIEBBearerCapability);

    _optional.insert(uniIEBHighLayerInfo);
    _optional.insert(uniIEBRepeatIndicator);
    _optional.insert(uniIEBLowLayerInfo);
    _mandatory.insert(uniIECalledPartyNumber);
    _optional.insert(uniIECalledPartySubaddress);
    _optional.insert(uniIECallingPartyNumber);
    _optional.insert(uniIECallingPartySubaddress);
    _optional.insert(uniIEConnectionIdentifier); // N->U
    _mandatory.insert(uniIEQoSParameters);

    _optional.insert(uniIEBSendingComplete);
    _optional.insert(uniIETransitNetworkSelection); // U->N
    _optional.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniSETUPpdu :: uniSETUPpdu(const uniSETUPpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniSETUPpdu :: ~uniSETUPpdu(void)
{
    return;
}

pfMessenger *uniSETUPpdu :: clone(void)
{
    uniSETUPpdu *newPdu = new uniSETUPpdu(*this);
    return newPdu;
}

uniSETUPpdu *uniSETUPpdu :: create(void)
{
    uniSETUPpdu *pdu = new uniSETUPpdu;
    return pdu;
}

void uniSETUPpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniSETUPpduAct(this, protocol_);
      return;
}

void uniSETUPpdu :: noProtocolCallReferenceProcedures(
    uniCoOrdProtocol *protocol_)
{
    if (getInteger(uniCallReferenceFlagStr) == 0)
    {
        if (protocol_->verifyTrafficParameterCombinations(this) != 0)
        {
            // Verification passed
            protocol_->toB(this);
        } 
        else 
        {
            // Unallowed combination
            protocol_->sendRELEASE_COMPLETEreplyToAAL(
                this, 
                uniCauseValue_ServiceOrOptionNotAvailable);
        }
    }
    return;
}

void uniSETUPpdu :: protocolRelatedCallReferenceProcedures(
    uniCoOrdProtocol *)
{
    return;
}

void uniSETUPpdu :: uniMandatoryIEMissingAct(
    uniCoOrdProtocol *protocol_,
    uniErrorInfo &)
{
    protocol_->sendRELEASE_COMPLETEpduToUNI(this,
					    uniCauseValue_NormalUnspecified);
    throw uniDiscardMessageException(PF_EX_INFO);
    return;}

void uniSETUPpdu :: uniMandatoryIEContentErrorAct(
    uniCoOrdProtocol *protocol_,
    uniErrorInfo &)
{
    protocol_->sendRELEASE_COMPLETEpduToUNI(this,
					    uniCauseValue_NormalUnspecified);
    throw uniDiscardMessageException(PF_EX_INFO);
    return;
}

//----------------------------------------------------------------------
// Class: uniCALL_PROCEEDINGpdu
//----------------------------------------------------------------------

uniCALL_PROCEEDINGpdu :: uniCALL_PROCEEDINGpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgCallProceeding);

    _optional.insert(uniIEConnectionIdentifier);
    _optional.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniCALL_PROCEEDINGpdu :: uniCALL_PROCEEDINGpdu(
    const uniCALL_PROCEEDINGpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniCALL_PROCEEDINGpdu :: ~uniCALL_PROCEEDINGpdu(void)
{
    return;
}

pfMessenger *uniCALL_PROCEEDINGpdu :: clone(void)
{
    uniCALL_PROCEEDINGpdu *newPdu = new uniCALL_PROCEEDINGpdu(*this);
    return newPdu;
}

uniCALL_PROCEEDINGpdu *uniCALL_PROCEEDINGpdu :: create(void)
{
    uniCALL_PROCEEDINGpdu *pdu = new uniCALL_PROCEEDINGpdu;
    return pdu;
}

void uniCALL_PROCEEDINGpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniCALL_PROCEEDINGpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniALERTINGpdu
//----------------------------------------------------------------------

uniALERTINGpdu :: uniALERTINGpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgAlerting);

    _optional.insert(uniIEConnectionIdentifier);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniALERTINGpdu :: uniALERTINGpdu(
    const uniALERTINGpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniALERTINGpdu :: ~uniALERTINGpdu(void)
{
    return;
}

pfMessenger *uniALERTINGpdu :: clone(void)
{
    uniALERTINGpdu *newPdu = new uniALERTINGpdu(*this);
    return newPdu;
}

uniALERTINGpdu *uniALERTINGpdu :: create(void)
{
    uniALERTINGpdu *pdu = new uniALERTINGpdu;
    return pdu;
}

void uniALERTINGpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniALERTINGpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniCONNECTpdu
//----------------------------------------------------------------------

uniCONNECTpdu :: uniCONNECTpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgConnect);

    _optional.insert(uniIEAALParameters);
    _optional.insert(uniIEBLowLayerInfo);
    _optional.insert(uniIEConnectionIdentifier);
    _optional.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniCONNECTpdu :: uniCONNECTpdu(
    const uniCONNECTpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniCONNECTpdu :: ~uniCONNECTpdu(void)
{
    return;
}

pfMessenger *uniCONNECTpdu :: clone(void)
{
    uniCONNECTpdu *newPdu = new uniCONNECTpdu(*this);
    return newPdu;
}

uniCONNECTpdu *uniCONNECTpdu :: create(void)
{
    uniCONNECTpdu *pdu = new uniCONNECTpdu;
    return pdu;
}

void uniCONNECTpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniCONNECTpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniCONNECT_ACKpdu
//----------------------------------------------------------------------

uniCONNECT_ACKpdu :: uniCONNECT_ACKpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgConnectAck);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniCONNECT_ACKpdu :: uniCONNECT_ACKpdu(
    const uniCONNECT_ACKpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniCONNECT_ACKpdu :: ~uniCONNECT_ACKpdu(void)
{
    return;
}

pfMessenger *uniCONNECT_ACKpdu :: clone(void)
{
    uniCONNECT_ACKpdu *newPdu = new uniCONNECT_ACKpdu(*this);
    return newPdu;
}

uniCONNECT_ACKpdu *uniCONNECT_ACKpdu :: create(void)
{
    uniCONNECT_ACKpdu *pdu = new uniCONNECT_ACKpdu;
    return pdu;
}

void uniCONNECT_ACKpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniCONNECT_ACKpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniRELEASEpdu
//----------------------------------------------------------------------

uniRELEASEpdu :: uniRELEASEpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgRelease);

    _mandatory.insert(uniIECause);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniRELEASEpdu :: uniRELEASEpdu(
    const uniRELEASEpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniRELEASEpdu :: ~uniRELEASEpdu(void)
{
    return;
}

pfMessenger *uniRELEASEpdu :: clone(void)
{
    uniRELEASEpdu *newPdu = new uniRELEASEpdu(*this);
    return newPdu;
}

uniRELEASEpdu *uniRELEASEpdu :: create(void)
{
    uniRELEASEpdu *pdu = new uniRELEASEpdu;
    return pdu;
}

void uniRELEASEpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
    uniMessageInputs *messageInput = messageCast(state_);
    messageInput->uniRELEASEpduAct(this, protocol_);
    return;
}

void uniRELEASEpdu :: uniMandatoryIEMissingAct(
    uniCoOrdProtocol *protocol_,
    uniErrorInfo &)
{
    // Required actions taken at uni protocol
    protocol_->toB(this);
    return;
}

void uniRELEASEpdu :: uniMandatoryIEContentErrorAct(
    uniCoOrdProtocol *protocol_,
    uniErrorInfo &)
{
    // Required actions taken at uni protocol
    protocol_->toB(this);
    return;
}

//----------------------------------------------------------------------
// Class: uniRELEASE_COMPLETEpdu
//----------------------------------------------------------------------

uniRELEASE_COMPLETEpdu :: uniRELEASE_COMPLETEpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgReleaseComplete);

    _optional.insert(uniIECause);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniRELEASE_COMPLETEpdu :: uniRELEASE_COMPLETEpdu(
    const uniRELEASE_COMPLETEpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniRELEASE_COMPLETEpdu :: ~uniRELEASE_COMPLETEpdu(void)
{
    return;
}

pfMessenger *uniRELEASE_COMPLETEpdu :: clone(void)
{
    uniRELEASE_COMPLETEpdu *newPdu = new uniRELEASE_COMPLETEpdu(*this);
    return newPdu;
}  

uniRELEASE_COMPLETEpdu *uniRELEASE_COMPLETEpdu :: create(void)
{
    uniRELEASE_COMPLETEpdu *pdu = new uniRELEASE_COMPLETEpdu;
    return pdu;
}

uniRELEASE_COMPLETEpdu *uniRELEASE_COMPLETEpdu :: buildReply(
    pfMessenger *original_, uniErrorInfo &errorInfo_)
{
    uniRELEASE_COMPLETEpdu *rcPdu = create();
    
    pfUlong callRefFlag = original_->getInteger(uniCallReferenceFlagStr);
    pfUlong callReference = original_->getInteger(uniCallReferenceStr);
    rcPdu->setInteger(uniCallReferenceFlagStr, 1 - callRefFlag);
    rcPdu->setInteger(uniCallReferenceStr, callReference);
    rcPdu->setMuxReference();
    rcPdu->defineStorage(uniCauseStr);
    rcPdu->setStorage(uniCauseStr, errorInfo_);
    
    return rcPdu;
}

void uniRELEASE_COMPLETEpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniRELEASE_COMPLETEpduAct(this, protocol_);
      return;
}

void uniRELEASE_COMPLETEpdu :: noProtocolCallReferenceProcedures(
    uniCoOrdProtocol *)
{
    return;
}

void uniRELEASE_COMPLETEpdu :: uniMandatoryIEMissingAct(
    uniCoOrdProtocol *protocol_,
    uniErrorInfo &)
{
    protocol_->sendRELEASE_COMPLETEpduToUNI(this,
uniCauseValue_NormalUnspecified);
    throw uniDiscardMessageException(PF_EX_INFO);
    return;
}

void uniRELEASE_COMPLETEpdu :: uniMandatoryIEContentErrorAct(
    uniCoOrdProtocol *protocol_,
    uniErrorInfo &)
{
    protocol_->sendRELEASE_COMPLETEpduToUNI(this,
uniCauseValue_NormalUnspecified);
    throw uniDiscardMessageException(PF_EX_INFO);
    return;
}

//----------------------------------------------------------------------
// Class: uniNOTIFYpdu
//----------------------------------------------------------------------

uniNOTIFYpdu :: uniNOTIFYpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgNotify);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniNOTIFYpdu :: uniNOTIFYpdu(
    const uniNOTIFYpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniNOTIFYpdu :: ~uniNOTIFYpdu(void)
{
    return;
}

pfMessenger *uniNOTIFYpdu :: clone(void)
{
    uniNOTIFYpdu *newPdu = new uniNOTIFYpdu(*this);
    return newPdu;
}

uniNOTIFYpdu *uniNOTIFYpdu :: create(void)
{
    uniNOTIFYpdu *pdu = new uniNOTIFYpdu;
    return pdu;
}

void uniNOTIFYpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniNOTIFYpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniSTATUSpdu
//----------------------------------------------------------------------

uniSTATUSpdu :: uniSTATUSpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgStatus);
    
    _mandatory.insert(uniIECallState);
    _mandatory.insert(uniIECause);
    _optional.insert(uniIEEndpointReference);
    _optional.insert(uniIEEndpointState);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniSTATUSpdu :: uniSTATUSpdu(const uniSTATUSpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniSTATUSpdu :: ~uniSTATUSpdu(void)
{
    return;
}

pfMessenger *uniSTATUSpdu :: clone(void)
{
    uniSTATUSpdu *newPdu = new uniSTATUSpdu(*this);
    return newPdu;
}

uniSTATUSpdu *uniSTATUSpdu :: create(void)
{
    uniSTATUSpdu *statusPdu = new uniSTATUSpdu;
    return statusPdu;
}

uniSTATUSpdu *uniSTATUSpdu :: buildReply(
    pfMessenger *original_, uniErrorInfo &errorInfo_, pfUlong state_)
{
    uniSTATUSpdu *statusPdu = create();
    uniSTATUSpdu &pdu = *statusPdu;

    pdu.defineCallState();
    
    pfUlong callReference = original_->getInteger(uniCallReferenceStr);
    pfUlong callRefFlag = original_->getInteger(uniCallReferenceFlagStr);
    pdu.setInteger(uniCallReferenceStr, callReference);
    pdu.setInteger(uniCallReferenceFlagStr, 1 - callRefFlag);
    pdu[uniCallStateStr].setInteger(uniCallState_StateStr, state_);
    pdu.defineStorage(uniCauseStr);
    pdu.setStorage(uniCauseStr, errorInfo_);

    return statusPdu;
}

void uniSTATUSpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniStatusMessageInputs *messageInput = statusMessageCast(state_);
      messageInput->uniSTATUSpduAct(this, protocol_);
      return;
}

void uniSTATUSpdu :: globalCallReferenceProcedures(
    uniCoOrdProtocol *protocol_)
{
    pfUlong CRF = getInteger(uniCallReferenceFlagStr);

    if (CRF == 0)
    {
        protocol_->toRRN(this);
    }
    else
    {
        protocol_->toRSN(this);
    }

    return;
}

void uniSTATUSpdu :: noProtocolCallReferenceProcedures(
    uniCoOrdProtocol *protocol_)
{
    if (getInteger(uniCallStateStr) != 0)
    {
        uniErrorInfo
            errorInfo(uniCauseValue_MessageNotCompatibleWithCallState);
        errorInfo.setMessageType(B0111_1101);
        uniRELEASE_COMPLETEpdu *rcPdu = uniRELEASE_COMPLETEpdu::buildReply(
            this, errorInfo);
        protocol_->sendDATAreqToAAL(rcPdu);
    }
    return;
}

//----------------------------------------------------------------------
// Class: uniSTATUS_ENQUIRYpdu
//----------------------------------------------------------------------

uniSTATUS_ENQUIRYpdu :: uniSTATUS_ENQUIRYpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgStatusEnquiry);
    
    _optional.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniSTATUS_ENQUIRYpdu :: uniSTATUS_ENQUIRYpdu(
    const uniSTATUS_ENQUIRYpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniSTATUS_ENQUIRYpdu :: ~uniSTATUS_ENQUIRYpdu(void)
{
    return;
}

pfMessenger *uniSTATUS_ENQUIRYpdu :: clone(void)
{
    uniSTATUS_ENQUIRYpdu *newPdu = new uniSTATUS_ENQUIRYpdu(*this);
    return newPdu;
}

uniSTATUS_ENQUIRYpdu *uniSTATUS_ENQUIRYpdu :: create(void)
{
    uniSTATUS_ENQUIRYpdu *pdu = new uniSTATUS_ENQUIRYpdu;
    return pdu;
}

void uniSTATUS_ENQUIRYpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniSTATUS_ENQUIRYpduAct(this, protocol_);
      return;
}

void uniSTATUS_ENQUIRYpdu :: noProtocolCallReferenceProcedures(
    uniCoOrdProtocol *protocol_)
{
    protocol_->sendSTATUSreplyToAAL(
        this, uniCauseValue_ResponseToSTATUS_ENQUIRY);
    return;
}

//----------------------------------------------------------------------
// Class: uniRESTARTpdu
//----------------------------------------------------------------------

uniRESTARTpdu :: uniRESTARTpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgRestart);
    
    _optional.insert(uniIEConnectionIdentifier);
    _mandatory.insert(uniIERestartIndicator);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniRESTARTpdu :: uniRESTARTpdu(
    const uniRESTARTpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniRESTARTpdu :: ~uniRESTARTpdu(void)
{
    return;
}

pfMessenger *uniRESTARTpdu :: clone(void)
{
    uniRESTARTpdu *newPdu = new uniRESTARTpdu(*this);
    return newPdu;
}

uniRESTARTpdu *uniRESTARTpdu :: create(void)
{
    uniRESTARTpdu *pdu = new uniRESTARTpdu;
    return pdu;
}

void uniRESTARTpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniRRNMessageInputs *messageInput = rrnMessageCast(state_);
      messageInput->uniRESTARTpduAct(this, protocol_);
      return;
}

void uniRESTARTpdu :: globalCallReferenceProcedures(
    uniCoOrdProtocol *protocol_)
{
    if (getInteger(uniCallReferenceFlagStr) == 0)
    {
        protocol_->toRRN(this);
    }
    else
    {
        uniPdu::globalCallReferenceProcedures(protocol_);
    }
    return;
}

//----------------------------------------------------------------------
// Class: uniRESTART_ACKpdu
//----------------------------------------------------------------------

uniRESTART_ACKpdu :: uniRESTART_ACKpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgRestartAck);

    _optional.insert(uniIEConnectionIdentifier);
    _mandatory.insert(uniIERestartIndicator);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniRESTART_ACKpdu :: uniRESTART_ACKpdu(
    const uniRESTART_ACKpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniRESTART_ACKpdu :: ~uniRESTART_ACKpdu(void)
{
    return;
}

pfMessenger *uniRESTART_ACKpdu :: clone(void)
{
    uniRESTART_ACKpdu *newPdu = new uniRESTART_ACKpdu(*this);
    return newPdu;
}

uniRESTART_ACKpdu *uniRESTART_ACKpdu :: create(void)
{
    uniRESTART_ACKpdu *pdu = new uniRESTART_ACKpdu;
    return pdu;
}

void uniRESTART_ACKpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniRSNMessageInputs *messageInput = rsnMessageCast(state_);
      messageInput->uniRESTART_ACKpduAct(this, protocol_);
      return;
}

void uniRESTART_ACKpdu :: globalCallReferenceProcedures(
    uniCoOrdProtocol *protocol_)
{
    if (getInteger(uniCallReferenceFlagStr) == 0)
    {
        uniPdu :: globalCallReferenceProcedures(protocol_);
    }
    else
    {
        uniRESTART_ACKpdu *pdu = new uniRESTART_ACKpdu(*this);
        protocol_->toRSN(pdu);
    }
    return;
}

//----------------------------------------------------------------------
// Class: uniADD_PARTYpdu
//----------------------------------------------------------------------

uniADD_PARTYpdu :: uniADD_PARTYpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgAddParty);

    _optional.insert(uniIEAALParameters);
    _optional.insert(uniIEBHighLayerInfo);
    _optional.insert(uniIEBLowLayerInfo);
    _mandatory.insert(uniIECalledPartyNumber);
    _optional.insert(uniIECalledPartySubaddress);
    _optional.insert(uniIECallingPartyNumber);
    _optional.insert(uniIECallingPartySubaddress);
    _optional.insert(uniIEBSendingComplete);
    _optional.insert(uniIETransitNetworkSelection); // U->N
    _mandatory.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniADD_PARTYpdu :: uniADD_PARTYpdu(const uniADD_PARTYpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniADD_PARTYpdu :: ~uniADD_PARTYpdu(void)
{
    return;
}

pfMessenger *uniADD_PARTYpdu :: clone(void)
{
    uniADD_PARTYpdu *newPdu = new uniADD_PARTYpdu(*this);
    return newPdu;
}

uniADD_PARTYpdu *uniADD_PARTYpdu :: create(void)
{
    uniADD_PARTYpdu *pdu = new uniADD_PARTYpdu;
    return pdu;
}

void uniADD_PARTYpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniADD_PARTYpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniADD_PARTY_ACKpdu
//----------------------------------------------------------------------

uniADD_PARTY_ACKpdu :: uniADD_PARTY_ACKpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgAddPartyAck);

    _mandatory.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniADD_PARTY_ACKpdu :: uniADD_PARTY_ACKpdu(const uniADD_PARTY_ACKpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniADD_PARTY_ACKpdu :: ~uniADD_PARTY_ACKpdu(void)
{
    return;
}

pfMessenger *uniADD_PARTY_ACKpdu :: clone(void)
{
    uniADD_PARTY_ACKpdu *newPdu = new uniADD_PARTY_ACKpdu(*this);
    return newPdu;
}

uniADD_PARTY_ACKpdu *uniADD_PARTY_ACKpdu :: create(void)
{
    uniADD_PARTY_ACKpdu *pdu = new uniADD_PARTY_ACKpdu;
    return pdu;
}

void uniADD_PARTY_ACKpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniADD_PARTY_ACKpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniADD_PARTY_REJECTpdu
//----------------------------------------------------------------------

uniADD_PARTY_REJECTpdu :: uniADD_PARTY_REJECTpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgAddPartyReject);

    _mandatory.insert(uniIECause);
    _mandatory.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniADD_PARTY_REJECTpdu :: uniADD_PARTY_REJECTpdu(
    const uniADD_PARTY_REJECTpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniADD_PARTY_REJECTpdu :: ~uniADD_PARTY_REJECTpdu(void)
{
    return;
}

pfMessenger *uniADD_PARTY_REJECTpdu :: clone(void)
{
    uniADD_PARTY_REJECTpdu *newPdu = new uniADD_PARTY_REJECTpdu(*this);
    return newPdu;
}

uniADD_PARTY_REJECTpdu *uniADD_PARTY_REJECTpdu :: create(void)
{
    uniADD_PARTY_REJECTpdu *pdu = new uniADD_PARTY_REJECTpdu;
    return pdu;
}

void uniADD_PARTY_REJECTpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniADD_PARTY_REJECTpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniDROP_PARTYpdu
//----------------------------------------------------------------------

uniDROP_PARTYpdu :: uniDROP_PARTYpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgDropParty);

    _mandatory.insert(uniIECause);
    _mandatory.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniDROP_PARTYpdu :: uniDROP_PARTYpdu(const uniDROP_PARTYpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniDROP_PARTYpdu :: ~uniDROP_PARTYpdu(void)
{
    return;
}

pfMessenger *uniDROP_PARTYpdu :: clone(void)
{
    uniDROP_PARTYpdu *newPdu = new uniDROP_PARTYpdu(*this);
    return newPdu;
}

uniDROP_PARTYpdu *uniDROP_PARTYpdu :: create(void)
{
    uniDROP_PARTYpdu *pdu = new uniDROP_PARTYpdu;
    return pdu;
}

void uniDROP_PARTYpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniDROP_PARTYpduAct(this, protocol_);
      return;
}

//----------------------------------------------------------------------
// Class: uniDROP_PARTY_ACKpdu
//----------------------------------------------------------------------

uniDROP_PARTY_ACKpdu :: uniDROP_PARTY_ACKpdu(void)
    : uniPdu()
{
    setInteger(uniMessageTypeStr, uniMsgDropParty);

    _optional.insert(uniIECause);
    _mandatory.insert(uniIEEndpointReference);

    defineBoolean(uniDEBUGStr);
    
    return;
}

uniDROP_PARTY_ACKpdu :: uniDROP_PARTY_ACKpdu(const uniDROP_PARTY_ACKpdu &other_)
    : uniPdu(other_)
{
    return;
}

uniDROP_PARTY_ACKpdu :: ~uniDROP_PARTY_ACKpdu(void)
{
    return;
}

pfMessenger *uniDROP_PARTY_ACKpdu :: clone(void)
{
    uniDROP_PARTY_ACKpdu *newPdu = new uniDROP_PARTY_ACKpdu(*this);
    return newPdu;
}

uniDROP_PARTY_ACKpdu *uniDROP_PARTY_ACKpdu :: create(void)
{
    uniDROP_PARTY_ACKpdu *pdu = new uniDROP_PARTY_ACKpdu;
    return pdu;
}

void uniDROP_PARTY_ACKpdu :: apply(pfState *state_, pfProtocol *protocol_)
{
      uniMessageInputs *messageInput = messageCast(state_);
      messageInput->uniDROP_PARTY_ACKpduAct(this, protocol_);
      return;
}

