/*
* Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:    RTP Manager
*
*/




// INCLUDE FILES
#include <srtpsession.h>
#include "mccrtpmanager.h"
#include "mccinternalcodecs.h"
#include "mccrtpdatasink.h"
#include "mccrtpdatasource.h"
#include "mmccevents.h"
#include "mccsubcontrollerlogs.h"
#include "mccrtcpreceiver.h"
#include "mccrtpkeepalivecontainer.h"
#include "mccresources.h"
#include "mccqoshandler.h"
#include "mccinternaldef.h"

// LOCAL CONSTANTS AND MACROS

// Default IP type-of-service value.
const TInt KDefaultIpTOS = 184;

// ============================= LOCAL FUNCTIONS ===============================

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CMccRtpManager::CMccRtpManager
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CMccRtpManager::CMccRtpManager( 
    MAsyncEventHandler& aHandler, 
    MMccResources& aMccResources,
    TUint32 aMccSessionId ) : 
    iRtpSessionId( KNullId ), 
    iStreamArray( RArray<TRtpId>() ), 
    iEventHandler( aHandler ),
    iMccResources( aMccResources ),
    iIpTOS( KDefaultIpTOS ), 
    iLocalPort( KDefaultRtpPort ),
    iMccSessionId( aMccSessionId ),
    iDummyRcvStreamId( KNullId )
    {

    }

// -----------------------------------------------------------------------------
// CMccRtpManager::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CMccRtpManager::ConstructL()
    {
    __SUBCONTROLLER( "CMccRtpManager::ConstructL" )

    iRtpApi = CRtpAPI::NewL( *this );
    iRtcpReceiver = CMccRtcpReceiver::NewL( this, iEventHandler, iMccResources, *iRtpApi );
    iQosHandler = CMccQosHandler::NewL( *this );
    
    __SUBCONTROLLER( "CMccRtpManager::ConstructL exit" )
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::NewL
// Static constructor.
// -----------------------------------------------------------------------------
//
CMccRtpManager* CMccRtpManager::NewL( 
    MAsyncEventHandler& aHandler,
    MMccResources& aMccResources,
    TUint32 aMccSessionId
    )
    {
    CMccRtpManager* self = new (ELeave) CMccRtpManager( aHandler, aMccResources, 
                                                        aMccSessionId );
    CleanupStack::PushL( self );      
    self->ConstructL();           
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::~CMccRtpManager
// Destructor
// -----------------------------------------------------------------------------
//
CMccRtpManager::~CMccRtpManager()
    {
    __SUBCONTROLLER( "CMccRtpManager::~CMccRtpManager" )
    
    delete iRtcpReceiver;
    delete iRtpKeepaliveMechanism;
    
    if ( KNullId != iDummyRcvStreamId && iRtpApi )
        {
        iRtpApi->CloseStream( iDummyRcvStreamId );
        }
            
    if( KNullId != iRtpSessionId && iRtpApi )
        {
        iRtpApi->CloseSession( iRtpSessionId );
        iRtpApi->Close();
        }
    
    delete iSecSession;
    delete iRtpApi;
    delete iQosHandler;
    
    iStreamArray.Close();
    
    delete iCName;
    __SUBCONTROLLER( "CMccRtpManager::~CMccRtpManager, exit" )
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::CreateSessionL
// Creates RTP session and adds session to SessionArray
// -----------------------------------------------------------------------------
//
void CMccRtpManager::CreateSessionL( 
    TUint& aPort, 
    TBool aEnableRTCP,
    TBool aSecurity, 
    TBool aIncreaseDefaultSocketSize )
    {
    __SUBCONTROLLER( "CMccRtpManager::CreateSessionL" )
    
    if( KNullId != iRtpSessionId )
        {
        User::Leave( KErrAlreadyExists );
        }

    TCreateSessionParams params;    
    params.iPriority = TCreateSessionParams::EPriorityStandard;    
    aEnableRTCP = ETrue;
    
    if ( aIncreaseDefaultSocketSize )
        {
        params.iSocketBufSize = KMccIncreasedRtpSocketSize;
        }
    __SUBCONTROLLER_INT1( "CMccRtpManager::CreateSessionL, socket size:", 
                          params.iSocketBufSize )
    
    TInetAddr localAddress = iRtpApi->GetLocalIPAddressL();
    
    if ( aSecurity )
        {
        iSecSession = CSRTPSession::NewL( localAddress );
        iRtpSessionId = iRtpApi->CreateSessionL( params, aPort, aEnableRTCP,
                                                 NULL, *iSecSession );
        }
    else
        {
        iRtpSessionId = iRtpApi->CreateSessionL( params, aPort, aEnableRTCP, NULL );
        }
        
    if( KNullId == iRtpSessionId )
        {
        User::Leave( KErrCouldNotConnect );
        }
    
    __ASSERT_ALWAYS( !iRtpKeepaliveMechanism, User::Leave( KErrAlreadyExists ) );     
    iRtpKeepaliveMechanism = 
        CMccRtpKeepaliveContainer::NewL( iEventHandler, 
                                         *iRtpApi, 
                                         iRtpSessionId );
    
    iLocalPort = aPort;
    iRtcpEnabled = aEnableRTCP;
    
    __SUBCONTROLLER( "CMccRtpManager::CreateSessionL, keepalive initialized" )
    
    iRtcpReceiver->HandleReceiving( iRtpSessionId, iRtcpEnabled );
    
    __SUBCONTROLLER( "CMccRtpManager::CreateSessionL, exit" )
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::CloseSession
// Closes RTP session
// -----------------------------------------------------------------------------
//
void CMccRtpManager::CloseSession()
    {
    __SUBCONTROLLER( "CMccRtpManager::CloseSession" )
    if ( KNullId != iRtpSessionId ) 
        {
        if ( iRtpKeepaliveMechanism )
            {
            iRtpKeepaliveMechanism->StopAll();
            }
        
        iRtpApi->CloseSession( iRtpSessionId );
        iRtpApi->Close();
        iStreamArray.Reset();
        
        iRtpSessionId = KNullId;
        
        if ( iQosHandler->QoSEnabled() )
            {
            iQosHandler->DisableQoS();
            }
        }
    __SUBCONTROLLER( "CMccRtpManager::CloseSession, exit" )
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::GetRtpReference
// Returns RTPApi reference
// -----------------------------------------------------------------------------
//
CRtpAPI* CMccRtpManager::GetRtpReferenceL( )
    {
    if ( !IsOpen() ) 
        {
        User::Leave( KErrNotFound );
        }
    return iRtpApi;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::SetRemoteAddress
// Sets RTP Remote Address
// -----------------------------------------------------------------------------
//
TInt CMccRtpManager::SetRemoteAddress( const TInetAddr& aRemoteAddress )
    {
    __SUBCONTROLLER( "CMccRtpManager::SetRemoteAddress" )
    TInt err( KErrNotFound );
    if ( KNullId != iRtpSessionId ) 
        {   
        // Do only if address has changed
        err =( iRemoteAddress.Address() == aRemoteAddress.Address() && 
               iRemoteAddress.Port() == aRemoteAddress.Port() ) ? KErrNone : err;
        if ( err )
            { 
            __SUBCONTROLLER_INT1( "CMccRtpManager::SetRemoteAddress, setting addr:", 
                                  aRemoteAddress.Address() )
            __SUBCONTROLLER_INT1( "CMccRtpManager::SetRemoteAddress, setting port:", 
                                  aRemoteAddress.Port() )
            
            err = iRtpApi->SetRemoteAddress( iRtpSessionId, aRemoteAddress );
            if ( !err )
                {
                iRemoteAddress.SetAddress( aRemoteAddress.Address() );
                iRemoteAddress.SetPort( aRemoteAddress.Port() );
                if ( iRtpKeepaliveMechanism )
                    {
                    err = iRtpKeepaliveMechanism->RemoteAddressSet();
                    }
                }
            }
        }
    __SUBCONTROLLER_INT1( "CMccRtpManager::SetRemoteAddress, exit with err", err )
    return err;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::SetRemoteRtcpAddress
// Sets RTP Remote Address
// -----------------------------------------------------------------------------
//
TInt CMccRtpManager::SetRemoteRtcpAddr( const TInetAddr& aRemoteAddress )
    {
    __SUBCONTROLLER( "CMccRtpManager::SetRemoteRtcpAddress" )
    TInt err( KErrNotFound );
    if ( KNullId != iRtpSessionId ) 
        {   
        // Do only if address has changed
        err =( iRemoteRtcpAddr.Address() == aRemoteAddress.Address() && 
               iRemoteRtcpAddr.Port() == aRemoteAddress.Port() ) ? KErrNone : err;
        __SUBCONTROLLER_INT1( "Remote RtcpPort", aRemoteAddress.Port() )
        __SUBCONTROLLER_INT1( "Saved Remote RtcpPort", iRemoteAddress.Port() )
        if ( err )
            { 
            __SUBCONTROLLER_INT1( "CMccRtpManager::SetRemoteAddress, setting addr:", 
                                  aRemoteAddress.Address() )
            __SUBCONTROLLER_INT1( "CMccRtpManager::SetRemoteAddress, setting port:", 
                                  aRemoteAddress.Port() )
            
            err = iRtpApi->SetRemoteRtcpAddress( iRtpSessionId, aRemoteAddress );
            if ( !err )
                {
                iRemoteRtcpAddr.SetAddress( aRemoteAddress.Address() );
                iRemoteRtcpAddr.SetPort( aRemoteAddress.Port() );
                __SUBCONTROLLER_INT1( "Remote RtcpPort", aRemoteAddress.Port() )
                }
            }
        }
    __SUBCONTROLLER_INT1( "CMccRtpManager::SetRemoteAddress, exit with err", err )
    return err;
    }
// -----------------------------------------------------------------------------
// CMccRtpManager::SetIpTOS
// Sets TOS flag, must be called before StartSession
// -----------------------------------------------------------------------------
//
void CMccRtpManager::SetIpTOS( TInt aIpTOS ) 
    {
    iIpTOS = aIpTOS;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::StartSession
// Starts RTP session
// -----------------------------------------------------------------------------
//
void CMccRtpManager::StartSessionL()
    {
    __SUBCONTROLLER( "CMccRtpManager::StartSessionL" )
    if ( KNullId != iRtpSessionId ) 
        {
        __SUBCONTROLLER( "CMccRtpManager::StartSessionL, session exists" )
        
		RSocket* socketPtr = iRtpApi->GetRtpSocket( iRtpSessionId );
		
		if( !socketPtr )
		    {
		    __SUBCONTROLLER( "CMccRtpManager::StartSessionL, no socket!" )
            #ifdef TEST_EUNIT            
            // The stub for RTP API returns a NULL socket pointer. Just pretend
            // everything is fine.
            return;            
            #else
		    User::Leave( KErrNotReady );
            #endif
		    }
		else
		    {
            User::LeaveIfError( iRtpApi->StartSession( iRtpSessionId ) );      
            
            __SUBCONTROLLER_INT1( "CMccRtpManager::StartSessionL, iptos:", iIpTOS )
             
            User::LeaveIfError( socketPtr->SetOpt( KSoIpTOS, KSolInetIp, iIpTOS ) );
            User::LeaveIfError( socketPtr->SetOpt( KSoUdpReceiveICMPError, KSolInetUdp, 1 ) );
            
            if ( !iQosHandler->QoSEnabled() )
                {
                // These has to be set before enabling QoS
                iQosHandler->SetSubConnectionParams( iConnection,
                                             iSocketServ,
                                             *socketPtr );
                                                
                // If we cannot enable QoS for some reason, we should not
                // consider it as a fatal error. If error happens, then
                // disable qos. This will clean up some unneeded resources.
                // Also this leads to retries when streams are created.
                TRAPD( err, iQosHandler->EnableQosL() );
                if ( KErrNone != err )
                    {
                    __SUBCONTROLLER_INT1( "CMccRtpManager::StartSessionL QOS:", err )
            
                    iQosHandler->DisableQoS();
                    }
                }
		    }
        }
    else
        {
        User::Leave( KErrNotFound );
        }
    
    __SUBCONTROLLER( "CMccRtpManager::StartSessionL, exit" ) 
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::Initialize
// Opens RTPApi and starts connection
// -----------------------------------------------------------------------------
//
void CMccRtpManager::InitializeL( TRequestStatus& aStatus, TInt aIapId )
    {
    TInt err = iRtpApi->OpenL( iRtpSdes, NULL, &iSocketServ, &iConnection );
    if ( KErrNone == err ) 
        {
        User::LeaveIfError( iRtpApi->StartConnection( aStatus, aIapId ) );
        }
    else
        {
        User::Leave( err );
        }
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::CheckStreamExists
// Checks that stream exists
// -----------------------------------------------------------------------------
//
TBool CMccRtpManager::CheckStreamExists( const TRtpId& aStreamId ) const
    {
    TInt index = iStreamArray.Find( aStreamId );
    
    if( KErrNotFound == index )
        {
        return EFalse;
        }
    else
        {
        return ETrue;
        }
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::IsOpen
// Checks that RTPApi is opened
// -----------------------------------------------------------------------------
//
TBool CMccRtpManager::IsOpen() const
    {
    if ( iRtpApi->GetRtpSocket( iRtpSessionId ) ) 
        {
        return ETrue;
        }
    else 
        {
        return EFalse;
        }
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::RemoveStreamFromArray
// Removes RTP stream from stream array
// -----------------------------------------------------------------------------
//
void CMccRtpManager::RemoveStreamFromArray( const TRtpId& aStreamId )
    {
    const TInt index( iStreamArray.Find( aStreamId ) );
    if( KErrNotFound != index )
        {
        iStreamArray.Remove( index );
        }
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::SessionId
// Returns the Session ID for this object
// -----------------------------------------------------------------------------
//
TRtpId CMccRtpManager::SessionId() const
    {
    return iRtpSessionId;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::ErrorNotify
// Error callback.
// -----------------------------------------------------------------------------
//
void CMccRtpManager::ErrorNotify( TInt aErrCode )
    {
    if ( KErrNone != aErrCode )
        {
        __SUBCONTROLLER_INT1( "CMccRtpManager::ErrorNotify, error", aErrCode )
        
        // Report all errors coming from here as rtp category stream errors
        // In HW when remote end drops from network, this function will be
        // called with KErrHostUnreach (-191) and in some cases this will return
        // as KErrGeneral with DTMF's. KErrCouldNotConnect error is received in
        // ICMP port unreachable situation. In these cases, handle just the 
        // KErrHostUnreach and KErrCouldNotConnect.
        if ( KErrHostUnreach == aErrCode || KErrCouldNotConnect == aErrCode )
            {
            TMccEvent event;
            event.iErrorCode = KErrHostUnreach;
            event.iEventCategory = KMccEventCategoryRtp;
            event.iEventType = KMccStreamError;
            
            // Use whatever internal uid
            TMccInternalEvent internalEvent( KMccRtpSourceUid, 
                                     EMccInternalEventNone,
                                     event );
            
            iEventHandler.SendEventToClient( internalEvent );
            }
        }
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::CreateTransmitStreamL
// Creates a new transmit stream based on given parameters
// -----------------------------------------------------------------------------
//
TUint32 CMccRtpManager::CreateTransmitStreamL( MDataSink& aSink, 
    const TMccCodecInfo& aCodecInfo )
    {
    TUint32 streamId( 0 );

    if( aCodecInfo.iPayloadType < KMccPayloadTypeMax )
        {
        CMccRtpDataSink& dSink = static_cast<CMccRtpDataSink&>( aSink );
        TMccRtpSessionParams sessParams( iRtpApi, 
                                         iRtpSessionId, 
                                         iRtcpEnabled, 
                                         iRtpKeepaliveMechanism,
                                         iSecSession );
        
        dSink.SetSessionParamsL( sessParams );
        
        TMccCodecInfoBuffer infoBuffer( aCodecInfo );
        dSink.ConfigureL( infoBuffer );
        
        UpdateL( &aCodecInfo );
        }
    else
        {
        User::Leave( KErrArgument );
        }
    return streamId;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::CreateReceiveStreamL
// Creates a new receive stream based on given parameters
// -----------------------------------------------------------------------------
//
TUint32 CMccRtpManager::CreateReceiveStreamL( MDataSource& aSource, 
    const TMccCodecInfo& aCodecInfo )
    {
    TUint32 streamId( 0 );

    if( aCodecInfo.iPayloadType < KMccPayloadTypeMax )
        {
        CMccRtpDataSource& dSource = static_cast<CMccRtpDataSource&>( aSource );
        TMccRtpSessionParams sessParams( iRtpApi, 
                                         iRtpSessionId, 
                                         iRtcpEnabled,
                                         iRtpKeepaliveMechanism,
                                         iSecSession );
        
        dSource.SetSessionParamsL( sessParams );
        
        TMccCodecInfoBuffer infoBuffer( aCodecInfo );
        dSource.ConfigureL( infoBuffer );
        
        UpdateL( &aCodecInfo );
        }
    else
        {
        User::Leave( KErrArgument );
        }

    return streamId;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::SetRTCPSendReceive
// Enables/disables automatic transmission and receiving of RTCP packets
// in a session.
// -----------------------------------------------------------------------------
//
TInt CMccRtpManager::SetRTCPSendReceive( TBool aEnableRtcp )
    {
    __SUBCONTROLLER( "CMccRtpManager::SetRTCPSendReceive" )
    
    // Check that session exists
    TInt err( KErrNotFound );
    if ( iRtpSessionId != KNullId ) 
        {    
        __SUBCONTROLLER_INT1( "CMccRtpManager::SetRTCPSendReceive, enable:", aEnableRtcp )
        
        iRtcpEnabled = aEnableRtcp;
        
        err = iRtcpReceiver->HandleReceiving( iRtpSessionId, iRtcpEnabled );
        if ( !err )
            {
            __SUBCONTROLLER( "CMccRtpManager::SetRTCPSendReceive, calling rtp api" )
            err = iRtpApi->SuspendRtcpSending( iRtpSessionId, aEnableRtcp );
            }
        }
    return err;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::SetLinkId
// -----------------------------------------------------------------------------
//
void CMccRtpManager::SetLinkId( TUint32 aLinkId )
    {
    iLinkId = aLinkId;
    }
    
// -----------------------------------------------------------------------------
// CMccRtpManager::UpdateL
// Creates dummy receive stream if rtp session does not have any receive
// stream (RTP source) or removes the dummy receive stream if RTP source
// exists.
// -----------------------------------------------------------------------------
//    
void CMccRtpManager::UpdateL( const TMccCodecInfo* aCodecInfo )
    {
    __SUBCONTROLLER( "CMccRtpManager::UpdateL" )
    
    MDataSource* source = 0;
    MDataSink* sink = 0;
    TInt err = 
        iMccResources.FindResource( iLinkId, 0, KMccRtpSourceUid, &source, &sink );
        
    if ( !err && source )
        {
        if ( iDummyRcvStreamId != KNullId )
            {
            __SUBCONTROLLER( "CMccRtpManager::UpdateL, dummy rcv stream not needed" )
            
            iRtpApi->CloseStream( iDummyRcvStreamId );
            iDummyRcvStreamId = KNullId;
            }
        }
    else
        {
        if ( iDummyRcvStreamId == KNullId && aCodecInfo )
            {
            __SUBCONTROLLER( "CMccRtpManager::UpdateL, dummy rcv stream needed" )
            
            TRcvStreamParams rcvParams;
            rcvParams.iPayloadType = aCodecInfo->iPayloadType;
            iDummyRcvStreamId = iRtpApi->CreateReceiveStreamL( iRtpSessionId, rcvParams );
            if ( KNullId == iDummyRcvStreamId )
                {
                __SUBCONTROLLER( "CMccRtpDataSource::UpdateL, could not create dummy rcv stream" )
                
                User::Leave( KErrCouldNotConnect );
                }
            }
        }
        
    __SUBCONTROLLER( "CMccRtpManager::UpdateL, exit" )
    }
    
// -----------------------------------------------------------------------------
// CMccRtpManager::GetLocalIpAddressesL
// -----------------------------------------------------------------------------
//
void CMccRtpManager::GetLocalIpAddressesL( TMccCreateLink& aClientData )
    {
    __SUBCONTROLLER( "CMccRtpManager::GetLocalIpAddressesL" )
    
    __ASSERT_ALWAYS( KNullId != iRtpSessionId && iRtpApi, User::Leave( KErrNotReady ) );
    
    RSocket* rtpSocket( iRtpApi->GetRtpSocket( iRtpSessionId ) );
    RSocket* rtcpSocket( iRtpApi->GetRtcpSocket( iRtpSessionId ) );
    TInetAddr localAddr( iRtpApi->GetLocalIPAddressL() );
    
    if ( rtpSocket )
        {
        if ( KAfInet6 == localAddr.Family() )
            {
            aClientData.iLocalAddress.SetAddress( localAddr.Ip6Address() );
            }
        else
            {
            aClientData.iLocalAddress.SetAddress( localAddr.Address() );
            }
        
        aClientData.iLocalAddress.SetPort( rtpSocket->LocalPort() );
        }
    else
        {
        User::Leave( KErrGeneral );
        }
    
    if ( iRtcpReceiver && rtcpSocket )
        {
        if ( KAfInet6 == localAddr.Family() )
            {
            aClientData.iLocalRtcpAddress.SetAddress( localAddr.Ip6Address() );
            }
        else
            {
            aClientData.iLocalRtcpAddress.SetAddress( localAddr.Address() );
            }
        
        aClientData.iLocalRtcpAddress.SetPort( rtcpSocket->LocalPort() );
        }
    
    __SUBCONTROLLER( "CMccRtpManager::GetLocalIpAddressesL, exit" )
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::SetCNameL
// -----------------------------------------------------------------------------
//
void CMccRtpManager::SetCNameL( const TDesC8& aCName )
    {
    HBufC8* cname = aCName.AllocLC();
    delete iCName;
    iCName = cname;
    CleanupStack::Pop( cname );
        
    iRtpSdes.iCName.Set( *iCName );
        
    iRtpApi->SetLocalSdes( iRtpSdes );
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::MccSessionId
// -----------------------------------------------------------------------------
//
TUint32 CMccRtpManager::MccSessionId() const
    {
    return iMccSessionId;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::QoSParamEvent()
// From MMccQosEventObserver
// -----------------------------------------------------------------------------
//
void CMccRtpManager::QoSParamEvent( TInt aError, TUint32 /*aEvent*/ )
    {
    __SUBCONTROLLER_INT1( "CMccRtpManager::QoSParamEvent aError:", aError )
    
    aError = aError;
    }

// -----------------------------------------------------------------------------
// CMccRtpManager::QoSConnEvent()
// From MMccQosEventObserver
// -----------------------------------------------------------------------------
//
void CMccRtpManager::QoSConnEvent( TInt aError, TUint32 /*aEvent*/ )
    {
    __SUBCONTROLLER_INT1( "CMccRtpManager::QoSConnEvent aError:", aError )
    
    aError = aError;
    }

