natplugins/natpnatfwsdpprovider/src/nspmediastreamcomponent.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 15:21:04 +0300
changeset 13 861e78e4e84c
parent 0 1bce908db942
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 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:  Media stream component class implementation
*
*/

#include "natfwcandidate.h"
#include "natfwcandidatepair.h"
#include "mnatfwsocketmediaconnwrapper.h"
#include "nspsessionobserver.h"
#include "nspmediastreamcomponent.h"
#include "nspnatfwasyncstate.h"
#include "nspcontrollerif.h"
#include "nspdefs.h"

const TUint KNSPFetchCandTimerInMicros = 7000000; // 7 seconds
const TUint KNSPRtcpComponentId = 2;

#define TOINETADDR_L( aDesc, aPort ) ConvertTDesC8ToTInetAddrL( aDesc, aPort )
#define NATFWRECEIVING_L( aCand, aState ) \
	iController.SetReceivingStateL( aCand, aState )
#define NATFWSENDING_L( aCand, aState ) \
	iController.SetSendingStateL( aCand, aState, iRemoteAddress, iRemotePort )


// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::CNSPMediaStreamComponent
// ---------------------------------------------------------------------------
//
CNSPMediaStreamComponent::CNSPMediaStreamComponent( MNSPControllerIF& aController,
        TUint aSessionId, TUint aCollectionId, TUint aComponentId )
    : iController( aController ),
      iSessionId( aSessionId ),
      iCollectionId( aCollectionId ),
      iComponentId( aComponentId )
    {
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::ConstructL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::ConstructL( const TDesC8& aAddress, TUint aPort,
        TUint aProtocol, TUint aMediaTos )
    {
    TInetAddr addr = TOINETADDR_L( aAddress, aPort );
    iAddrFamily = addr.Family();
    
    iStreamId = iController.CreateStreamL( 
        iSessionId, aProtocol, static_cast<TInt>( aMediaTos ) );
    iWrapper = &iController.CreateWrapperL( iSessionId, iStreamId );
    
    iWrapper->SetIncomingAddrL( addr );
    iWrapper->SetReceivingStateL( EStreamingStateActive );
    iWrapper->SetSendingStateL( EStreamingStateActive );
    
    iState = CNSPNATFWAsyncState::NewL();
    iRemoteAddress.Assign( KNullDesC8().AllocL() );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::NewL
// ---------------------------------------------------------------------------
//
CNSPMediaStreamComponent* CNSPMediaStreamComponent::NewL(
        MNSPControllerIF& aController, TUint aSessionId,
        TUint aCollectionId, TUint aComponentId, const TDesC8& aAddress,
        TUint aPort, TUint aProtocol, TUint aMediaTos )
    {
    CNSPMediaStreamComponent* self = CNSPMediaStreamComponent::NewLC(
            aController, aSessionId, aCollectionId, aComponentId,
            aAddress, aPort, aProtocol, aMediaTos );
    CleanupStack::Pop( self );
    return self;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::NewLC
// ---------------------------------------------------------------------------
//
CNSPMediaStreamComponent* CNSPMediaStreamComponent::NewLC(
        MNSPControllerIF& aController, TUint aSessionId, TUint aCollectionId,
        TUint aComponentId, const TDesC8& aAddress, TUint aPort,
        TUint aProtocol, TUint aMediaTos )
    {
    CNSPMediaStreamComponent* self = new ( ELeave ) CNSPMediaStreamComponent(
            aController, aSessionId, aCollectionId, aComponentId );
    CleanupStack::PushL( self );
    self->ConstructL( aAddress, aPort, aProtocol, aMediaTos );
    return self;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::~CNSPMediaStreamComponent
// ---------------------------------------------------------------------------
//
CNSPMediaStreamComponent::~CNSPMediaStreamComponent()
    {
    iRemoteAddress.Close();
    iWrapper = NULL;
    delete iState;
    delete iCandidatePair;
    iLocalCandidates.ResetAndDestroy();
    iLocalCandidates.Close();
    iController.Cancel( iTimerTransactionId );
    TRAP_IGNORE( iController.CloseStreamL( iSessionId, iStreamId ) )
    }

// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::ControlMediaL
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::ControlMediaL(
		MNATFWConnectivityObserver::TNATFWConnectivityEvent aEvent,
		TInt aError, TAny* aData )
	{
    NSPLOG_STR( "CNSPMediaStreamComponent::ControlMediaL(), Entry" )
    
    TNatReturnStatus status = KNatAsync;
    
    switch ( aEvent )
    	{
    	case MNATFWConnectivityObserver::ELocalCandidateFound:
    		{
    		iLocalCandidates.AppendL( reinterpret_cast<CNATFWCandidate*>(aData) );
    		break;
    		}
    	
    	case MNATFWConnectivityObserver::ECandidatePairFound:
    		{
    	    delete iCandidatePair;
    	    iCandidatePair = reinterpret_cast<CNATFWCandidatePair*>(aData);
    		break;
    		}
    	
        case MNATFWConnectivityObserver::EReceivingActivated:
            {
            status = HandleReceivingActivated( aError );
            break;
            }
        
        case MNATFWConnectivityObserver::ESendingActivated:
            {
            status = HandleSendingActivated( aError );
            break;
            }
        
        case MNATFWConnectivityObserver::EFetchingCompleted:
            {
            status = HandleFetchingCompleted( aError );
            break;
            }
        
        case MNATFWConnectivityObserver::EConnChecksCompleted:
            {
            status = HandleConnChecksCompleted( aError );
            break;
            }
        
        case MNATFWConnectivityObserver::EReceivingDeactivated:
            {
            status = HandleReceivingDeActivated( aError );
            break;
            }
        
        case MNATFWConnectivityObserver::ESendingDeactivated:
            {
            status = HandleSendingDeActivated( aError );
            break;
            }
        
        case MNATFWConnectivityObserver::EGeneralError:
        	{
        	status = ErrorOccurred( aError );
        	break;
        	}
        
        case MNATFWConnectivityObserver::ESessionCreated:
        default:
            {
            User::Leave( KErrNotReady );
            }
    	}
    
    NSPLOG_INT( "CNSPMediaStreamComponent::ControlMediaL(), Exit, status", status )
    return status;
	}


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::ResetAndDestroyCandidates
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::ResetAndDestroyCandidates()
    {
    iLocalCandidates.ResetAndDestroy();
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::FetchCandidateL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::FetchCandidateL()
    {
    iState->CheckStateL( CNSPNATFWAsyncState::ENATFWEventFetchCand );
    
    iController.FetchCandidateL( iSessionId, iStreamId, iAddrFamily );
    iTimerTransactionId = iController.OrderTimeoutL( iSessionId, iStreamId,
            MNATFWConnectivityObserver::EFetchingCompleted,
            KNSPFetchCandTimerInMicros );
    
    iState->ChangeStateL( CNSPNATFWAsyncState::ENATFWEventFetchCand );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::FetchCandidatesL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::FetchCandidatesL()
    {
    iState->CheckStateL( CNSPNATFWAsyncState::ENATFWEventFetchCand );
    
    iController.FetchCandidatesL( iSessionId,
            iStreamId, iCollectionId, iComponentId, iAddrFamily );
    iTimerTransactionId = iController.OrderTimeoutL( iSessionId, iStreamId,
            MNATFWConnectivityObserver::EFetchingCompleted,
            KNSPFetchCandTimerInMicros );
    
    iState->ChangeStateL( CNSPNATFWAsyncState::ENATFWEventFetchCand );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::PerformCandidateChecksL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::PerformCandidateChecksL()
    {
    iState->ChangeStateL( CNSPNATFWAsyncState::ENATFWEventPerformChecks );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::ActivateL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::ActivateL( const TDesC8& aAddress, TUint aPort )
    {
    iState->CheckStateL( CNSPNATFWAsyncState::ENATFWEventRecvAct );
    iState->ChangeStateL( CNSPNATFWAsyncState::ENATFWEventRecvDeAct );
    iState->ChangeStateL( CNSPNATFWAsyncState::ENATFWEventSendDeAct );
    
    iRemoteAddress.Close();
    iRemoteAddress.Assign( aAddress.AllocL() );
    iRemotePort = aPort;
    
    __ASSERT_ALWAYS( iLocalCandidates.Count(), User::Leave( KErrNotReady ) );
    NATFWRECEIVING_L( *iLocalCandidates[0], EStreamingStateActive );
    NATFWSENDING_L( *iLocalCandidates[0], EStreamingStateActive );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::ActivateL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::ActivateL()
    {
    __ASSERT_ALWAYS( iCandidatePair, User::Leave( KErrNotReady ) );
    
    iState->CheckStateL( CNSPNATFWAsyncState::ENATFWEventRecvAct );    
    iState->ChangeStateL( CNSPNATFWAsyncState::ENATFWEventRecvDeAct );
    iState->ChangeStateL( CNSPNATFWAsyncState::ENATFWEventSendDeAct );
    
    iRemoteAddress.Close();
    iRemoteAddress.Assign( iCandidatePair->RemoteCandidate().TransportDomainAddr().AllocL() );
    iRemotePort = iCandidatePair->RemoteCandidate().TransportDomainPort();
    
    NATFWRECEIVING_L( iCandidatePair->LocalCandidate(), EStreamingStateActive );
    NATFWSENDING_L( iCandidatePair->LocalCandidate(), EStreamingStateActive );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::DeActivateL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::DeActivateL()
    {
    iState->CheckStateL( CNSPNATFWAsyncState::ENATFWEventRecvDeAct );
    
    __ASSERT_ALWAYS( iLocalCandidates.Count(), User::Leave( KErrNotReady ) );
    NATFWRECEIVING_L( *iLocalCandidates[0], EStreamingStatePassive );
    NATFWSENDING_L( *iLocalCandidates[0], EStreamingStatePassive );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::RemoteAddress
// ---------------------------------------------------------------------------
//
const TDesC8& CNSPMediaStreamComponent::RemoteAddress() const
    {
    return iRemoteAddress;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::RemotePort
// ---------------------------------------------------------------------------
//
TUint CNSPMediaStreamComponent::RemotePort() const
    {
    return iRemotePort;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::StreamId
// ---------------------------------------------------------------------------
//
TUint CNSPMediaStreamComponent::StreamId() const
    {
    return iStreamId;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::ComponentId
// ---------------------------------------------------------------------------
//
TUint CNSPMediaStreamComponent::ComponentId() const
    {
    return iComponentId;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::LocalCandidates
// ---------------------------------------------------------------------------
//
RPointerArray<CNATFWCandidate>& CNSPMediaStreamComponent::LocalCandidates()
    {
    return iLocalCandidates;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::IceLocalCandidateL
// ---------------------------------------------------------------------------
//
const CNATFWCandidate& CNSPMediaStreamComponent::IceLocalCandidateL()
    {
    __ASSERT_ALWAYS( iCandidatePair, User::Leave( KErrNotReady ) );
    return iCandidatePair->LocalCandidate();
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::IceRemoteCandidateL
// ---------------------------------------------------------------------------
//
const CNATFWCandidate& CNSPMediaStreamComponent::IceRemoteCandidateL()
    {
    __ASSERT_ALWAYS( iCandidatePair, User::Leave( KErrNotReady ) );
    return iCandidatePair->RemoteCandidate();
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::OutgoingAddress
// ---------------------------------------------------------------------------
//
TInt CNSPMediaStreamComponent::OutgoingAddress( TDes8& aAddress, TUint& aPort ) const
    {
    TInetAddr address;
    iWrapper->OutgoingAddr( address );
    TRAPD( error, ConvertTInetAddrToTDes8AndTUintL( address, aAddress, aPort ) );
    return error;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::SetCredentialsL
// ---------------------------------------------------------------------------
//
void CNSPMediaStreamComponent::SetCredentialsL( const CNATFWCredentials& aCredentials )
    {
    iController.SetCredentialsL( iSessionId, iStreamId, aCredentials );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::AttachCandidateL
// ---------------------------------------------------------------------------
//
TBool CNSPMediaStreamComponent::AttachCandidateL( CNATFWCandidate& aCandidate ) const
    {
    if ( aCandidate.ComponentId() == iComponentId )
        {
        aCandidate.SetStreamId( iStreamId );
        return ETrue;
        }
    
    return EFalse;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::HandleReceivingActivated
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::HandleReceivingActivated(
        TInt aError )
    {
    TInt error = iState->CheckState( CNSPNATFWAsyncState::ENATFWEventRecvAct );
    
    if ( KErrNone == error && KErrNone == aError )
        {
        iState->ChangeState( CNSPNATFWAsyncState::ENATFWEventRecvAct );
        return Continue();
        }
    else if ( KErrNone == aError )
        {
        return ErrorOccurred( error );
        }
    else
        {
        return ErrorOccurred( aError );
        }
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::HandleSendingActivated
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::HandleSendingActivated(
        TInt aError )
    {
    TInt error = iState->CheckState( CNSPNATFWAsyncState::ENATFWEventSendAct );
    
    if ( KErrNone == error && KErrNone == aError )
        {
        iState->ChangeState( CNSPNATFWAsyncState::ENATFWEventSendAct );
        return Continue();
        }
    else if ( KErrNone == aError )
        {
        return ErrorOccurred( error );
        }
    else
        {
        return ErrorOccurred( aError );
        }
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::HandleReceivingDeActivated
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::HandleReceivingDeActivated(
        TInt aError )
    {
    TInt error = iState->CheckState( CNSPNATFWAsyncState::ENATFWEventRecvDeAct );
    
    if ( KErrNone == error && KErrNone == aError )
        {
        iState->ChangeState( CNSPNATFWAsyncState::ENATFWEventRecvDeAct );
        return Continue();
        }
    else if ( KErrNone == aError )
        {
        return ErrorOccurred( error );
        }
    else
        {
        return ErrorOccurred( aError );
        }
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::HandleSendingDeActivated
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::HandleSendingDeActivated(
        TInt aError )
    {
    TInt error = iState->CheckState( CNSPNATFWAsyncState::ENATFWEventSendDeAct );
    
    if ( KErrNone == error && KErrNone == aError )
        {
        iState->ChangeState( CNSPNATFWAsyncState::ENATFWEventSendDeAct );
        return Continue();
        }
    else if ( KErrNone == aError )
        {
        return ErrorOccurred( error );
        }
    else
        {
        return ErrorOccurred( aError );
        }
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::HandleFetchingCompleted
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::HandleFetchingCompleted( TInt aError )
    {
    iController.Cancel( iTimerTransactionId );
    
    TNatReturnStatus status = 
        ( KErrNone == aError ? Continue() : ErrorOccurred( aError ) );
    
    if ( iLocalCandidates.Count() )
        {
        const CNATFWCandidate& candidate = *iLocalCandidates[0];
        
        // local candidates are never in FQDN format
        if ( candidate.Type() == CNATFWCandidate::EServerReflexive &&
             candidate.Base().CmpAddr( candidate.TransportAddr() ) )
            {
            // we are not behind NAT, no need to proceed with NATFW
            NSPLOG_STR( 
                "CNSPMediaStreamComponent::HandleFetchingCompleted, NO NAT" )
            status = KNatNonFatalErrorLimit;
            }
        }
    
    return status;
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::HandleConnChecksCompleted
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::HandleConnChecksCompleted( TInt aError )
    {
    return ( KErrNone == aError ? Continue() : ErrorOccurred( aError ) );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::Continue
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::Continue()
    {
    return ( iState->Continue() ? KNatReady : KNatAsync );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStreamComponent::ErrorOccurred
// ---------------------------------------------------------------------------
//
TNatReturnStatus CNSPMediaStreamComponent::ErrorOccurred( TInt aError )
    {
    NSPLOG_INT( "CNSPMediaStreamComponent::ErrorOccurred():", aError )
    
    return ( KErrTimedOut == aError ||
    		 SuppressRtcpIcmp( aError ) ? Continue() : aError );
    }


// ---------------------------------------------------------------------------
// CNSPMediaStream::SuppressRtcpIcmp
// ---------------------------------------------------------------------------
//
TBool CNSPMediaStreamComponent::SuppressRtcpIcmp( TInt aError ) const
	{
	return ( KNSPRtcpComponentId == iComponentId && NSP_ICMP( aError ) );
	}


// end of file