natplugins/natpnatfwsdpprovider/src/nspmediastream.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/natplugins/natpnatfwsdpprovider/src/nspmediastream.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,719 @@
+/*
+* 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 class implementation.
+*
+*/
+
+#include <sdpconnectionfield.h>
+#include <sdpmediafield.h>
+#include "natfwcandidate.h"
+#include "natfwcandidatepair.h"
+#include "natfwcredentials.h"
+#include "nspmediastream.h"
+#include "nspmediastreamcomponent.h"
+#include "nspcontentparser.h"
+#include "nsputil.h"
+#include "nspcontrollerif.h"
+#include "nspdefs.h"
+
+const TInt KMaxLengthOfFQDN = 255;
+const TUint KMaxPasswordLength = 100;
+const TUint KNSPRtpComponentId = 1;
+const TUint KNSPRtcpComponentId = 2;
+
+static void UpdateConnFieldL( CSdpMediaField& aMediaField,
+        const TDes8& aAddress )
+	{
+	if ( aMediaField.ConnectionFields().Count() )
+		{
+		NSPUtil::UpdateConnectionFieldL( *aMediaField.ConnectionFields()[0],
+		    aAddress );
+		}
+	}
+
+// ======== MEMBER FUNCTIONS ========
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::CNSPMediaStream
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStream::CNSPMediaStream( MNSPControllerIF& aController,
+        TUint aSessionId, TUint aCollectionId )
+    : iController( aController ),
+      iSessionId( aSessionId ),
+      iCollectionId( aCollectionId )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::ConstructL( CSdpMediaField& aMediaField,
+        const TDesC8& aAddress, TUint aProtocol, TUint aMediaTos )
+    {
+    iMediaField = aMediaField.CloneL( EFalse );
+    
+    RBuf8 addr;
+    addr.CleanupClosePushL();
+    addr.CreateL( KMaxLengthOfFQDN );
+    addr = CONN_ADDR( aMediaField, aAddress );
+    TUint port = iMediaField->Port();
+    
+    CNSPMediaStreamComponent* rtp = CNSPMediaStreamComponent::NewLC(
+            iController, iSessionId, iCollectionId, KNSPRtpComponentId,
+            addr, port, aProtocol, aMediaTos );
+    User::LeaveIfError( iStreamComponentArray.Append( rtp ) );
+    CleanupStack::Pop( rtp );
+    
+    iController.ContentParser().FindRTCP( aMediaField, addr, ++port );
+    
+    CNSPMediaStreamComponent* rtcp = CNSPMediaStreamComponent::NewLC(
+            iController, iSessionId, iCollectionId, KNSPRtcpComponentId,
+            addr, port, aProtocol, aMediaTos );
+    User::LeaveIfError( iStreamComponentArray.Append( rtcp ) );
+    CleanupStack::Pop( rtcp );
+    
+    CleanupStack::PopAndDestroy( &addr );
+    
+    iInboundCredentials = CNATFWCredentials::NewL();
+    iInboundCredentials->SetDirection( CNATFWCredentials::EInbound );
+    HBufC8* buffer = HBufC8::NewLC( KMaxPasswordLength );
+    TPtr8 ptr( buffer->Des() );
+    iController.GenerateUsernameL( ptr );
+    iInboundCredentials->SetUsernameL( buffer->Des() );
+    iController.GeneratePasswordL( ptr );
+    iInboundCredentials->SetPasswordL( buffer->Des() );
+    CleanupStack::PopAndDestroy( buffer );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::NewL
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStream* CNSPMediaStream::NewL( MNSPControllerIF& aController,
+        CSdpMediaField& aMediaField, TUint aSessionId, TUint aCollectionId,
+        const TDesC8& aAddress, TUint aProtocol, TUint aMediaTos )
+    {
+    CNSPMediaStream* self = CNSPMediaStream::NewLC( aController,
+            aMediaField, aSessionId, aCollectionId, aAddress,
+            aProtocol, aMediaTos );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::NewLC
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStream* CNSPMediaStream::NewLC( MNSPControllerIF& aController,
+        CSdpMediaField& aMediaField, TUint aSessionId, TUint aCollectionId,
+        const TDesC8& aAddress, TUint aProtocol, TUint aMediaTos )
+    {
+    CNSPMediaStream* self = new ( ELeave ) CNSPMediaStream(
+            aController, aSessionId, aCollectionId );
+    CleanupStack::PushL( self );
+    self->ConstructL( aMediaField, aAddress, aProtocol, aMediaTos );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::~CNSPMediaStream
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStream::~CNSPMediaStream()
+    {
+    delete iMediaField;
+    delete iInboundCredentials;
+    delete iOutboundCredentials;
+    iPendingArray.Close();
+    iStreamComponentArray.ResetAndDestroy();
+    iStreamComponentArray.Close();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::HasMediaComponent
+// ---------------------------------------------------------------------------
+//
+TBool CNSPMediaStream::HasMediaComponent( TUint aStreamId )
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        if ( iStreamComponentArray[index]->StreamId() == aStreamId )
+            {
+            return ETrue;
+            }
+        }
+        
+    return EFalse;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::Notify
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStream::ControlMediaL( TUint aStreamId,
+		MNATFWConnectivityObserver::TNATFWConnectivityEvent aEvent,
+		TInt aError, TAny* aData )
+	{
+    TNatReturnStatus status = KErrNone;
+    const TInt index = FindMediaComponent( aStreamId );
+	
+    if ( KErrNotFound != index )
+    	{
+        status = iStreamComponentArray[index]->ControlMediaL( aEvent, aError, aData );
+        TNatReturnStatus cont = RemovePending( aStreamId, KNatReady == status );
+        status = ( KNatReady == status ? cont : status );    	
+    	}
+    else
+    	{
+    	status = KErrNotFound;
+    	}
+    
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::ModifyStunConnL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::ModifyStunConnL( CSdpMediaField& aMediaField,
+        TDes8& aAddress ) const
+    {
+    NSPLOG_STR( "CNSPMediaStream::ModifyStunConnL(), Entry" )
+    
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        RPointerArray<CNATFWCandidate>& localcand = component->LocalCandidates();
+        NSPUtil::SortCandidatesL( localcand ); // leave if empty
+        
+        if ( KNSPRtpComponentId == component->ComponentId() )
+            {
+            aAddress = localcand[0]->TransportDomainAddr();
+            aMediaField.SetPortL( localcand[0]->TransportDomainPort() );
+            UpdateConnFieldL( aMediaField, aAddress );
+            }
+        else if ( KNSPRtcpComponentId == component->ComponentId() )
+            {
+            iController.ContentParser().ModifyRTCPL( aMediaField,
+                    localcand[0]->TransportDomainAddr(),
+                    localcand[0]->TransportDomainPort() );
+            }
+        else
+            {
+            User::Leave( KErrNotFound );
+            }
+        }
+    
+    NSPLOG_STR( "CNSPMediaStream::ModifyStunConnL(), Exit" )
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::ModifyIceConnL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::ModifyIceConnL( CSdpMediaField& aMediaField,
+        TDes8& aAddress ) const
+    {
+    NSPLOG_STR( "CNSPMediaStream::ModifyIceConnL(), Entry" )
+    
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        const CNATFWCandidate& localcandidate = component->IceLocalCandidateL();
+        
+        if ( KNSPRtpComponentId == component->ComponentId() )
+            {
+            aAddress = localcandidate.TransportDomainAddr();
+            aMediaField.SetPortL( localcandidate.TransportDomainPort() );
+            UpdateConnFieldL( aMediaField, aAddress );
+            }
+        else if ( KNSPRtcpComponentId == component->ComponentId() )
+            {
+            iController.ContentParser().ModifyRTCPL( aMediaField,
+                    localcandidate.TransportDomainAddr(),
+                    localcandidate.TransportDomainPort() );
+            }
+        else
+            {
+            User::Leave( KErrNotFound );
+            }
+        }
+    
+    NSPLOG_STR( "CNSPMediaStream::ModifyIceConnL(), Exit" )
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::ModifyLocalConnL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::ModifyLocalConnL( CSdpMediaField& aMediaField,
+        TDes8& aAddress ) const
+    {
+    NSPLOG_STR( "CNSPMediaStream::ModifyLocalConnL(), Entry" )
+    
+    TUint port( 0 );
+    RBuf8 address;
+    address.CreateL( KMaxLengthOfFQDN );
+    address.CleanupClosePushL();
+    
+    const TInt streamcompcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < streamcompcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        User::LeaveIfError( component->OutgoingAddress( address, port ) );
+        
+        if ( KNSPRtpComponentId == component->ComponentId() )
+            {
+            aAddress = address;
+            aMediaField.SetPortL( port );
+            UpdateConnFieldL( aMediaField, aAddress );
+            }
+        else if ( KNSPRtcpComponentId == component->ComponentId() )
+            {
+            iController.ContentParser().ModifyRTCPL( aMediaField, address, port );
+            }
+        else
+            {
+            User::Leave( KErrNotFound );
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( &address );
+    
+    NSPLOG_STR( "CNSPMediaStream::ModifyLocalConnL(), Exit" )
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::AddLocalCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::AddLocalCandidatesL( CSdpMediaField& aMediaField ) const
+    {
+    RPointerArray<CNATFWCandidate> localcand;
+    CleanupClosePushL( localcand );
+    LocalCandidatesL( localcand );
+    iController.ContentParser().AddCandidatesL( aMediaField, localcand );
+    CleanupStack::PopAndDestroy( &localcand );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::GetCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::GetCandidatesL( CSdpMediaField& aMediaField,
+        RPointerArray<CNATFWCandidate>& aRemoteCandidates ) const
+    {
+    iController.ContentParser().GetCandidatesL( aMediaField, aRemoteCandidates );
+    AttachCandidatesL( aRemoteCandidates );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::MediaConnInfoL
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStream::MediaConnInfoL( CSdpMediaField& aMediaField,
+        const TDesC8& aAddress ) const
+    {
+    TNatReturnStatus status = KNatReady;
+    TNatReturnStatus mediastatus = status;
+    const TDesC8& address = CONN_ADDR( aMediaField, aAddress );
+
+    RBuf8 addr;
+    addr.CreateL( KMaxLengthOfFQDN );
+    addr.CleanupClosePushL();
+    
+    const TInt streamcompcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < streamcompcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        TUint port = aMediaField.Port();
+        addr = address;
+        
+        if ( KNSPRtcpComponentId == component->ComponentId() )
+            {
+            iController.ContentParser().FindRTCP( aMediaField, addr, ++port );
+            }
+        
+        const TDesC8& remoteAddr = component->RemoteAddress();
+        const TUint remotePort = component->RemotePort();
+        mediastatus = ( ( !addr.Compare( remoteAddr ) && remotePort == port ) ||
+        				NSPUtil::IsUnspecifiedL( addr, port ) ? KNatReady : KNatAsync );
+        
+        if ( KNatAsync == mediastatus )
+            {
+            component->ActivateL( addr, port );
+            }
+        
+        status = ( KNatReady == status ? mediastatus : status );
+        }
+    
+    CleanupStack::PopAndDestroy( &addr );
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::AddRemoteCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::AddRemoteCandidatesL( CSdpMediaField& aMediaField ) const
+    {
+    RPointerArray<CNATFWCandidate> remotecandidates;
+    CleanupClosePushL( remotecandidates );
+    
+    const TInt streamcompcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < streamcompcount; index++ )
+        {
+        remotecandidates.AppendL( &iStreamComponentArray[index]->IceLocalCandidateL() );
+        }
+    
+    iController.ContentParser().AddRemoteCandidatesL( aMediaField, remotecandidates );
+    CleanupStack::PopAndDestroy(); // remotecandidates
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::AddCredentialsL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::AddCredentialsL( CSdpMediaField& aMediaField ) const
+    {
+    iController.ContentParser().AddCredentialsL( aMediaField, *iInboundCredentials );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::LocalCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::LocalCandidatesL(
+			RPointerArray<CNATFWCandidate>& aLocalcand ) const
+    {
+    const TInt streamcompcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < streamcompcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        RPointerArray<CNATFWCandidate>& localcand = component->LocalCandidates();
+        NSPUtil::SortCandidatesL( localcand ); // leave if empty
+        
+        const TInt localcandcount( localcand.Count() );
+        for ( TInt jndex = 0; jndex < localcandcount ; jndex++ )
+            {
+            aLocalcand.AppendL( localcand[jndex] );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::FetchCandidateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::FetchCandidateL()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        component->FetchCandidateL();
+        iPendingArray.AppendL( component->StreamId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::FetchCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::FetchCandidatesL()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        component->FetchCandidatesL();
+        iPendingArray.AppendL( component->StreamId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::PerformCandidateChecksL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::PerformCandidateChecksL()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        component->PerformCandidateChecksL();
+        iPendingArray.AppendL( component->StreamId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::ActivateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::ActivateL( CSdpMediaField& aMediaField,
+        const TDesC8& aAddress )
+    {
+    const TDesC8& address = CONN_ADDR( aMediaField, aAddress );
+    
+    RBuf8 addr;
+    addr.CreateL( KMaxLengthOfFQDN );
+    addr.CleanupClosePushL();
+    
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        TUint port = aMediaField.Port();
+        addr = address;
+        
+        if ( KNSPRtcpComponentId == component->ComponentId() )
+            {
+            iController.ContentParser().FindRTCP( aMediaField, addr, ++port );
+            }
+        
+        iStreamComponentArray[index]->ActivateL( addr, port );
+        iPendingArray.AppendL( iStreamComponentArray[index]->StreamId() );
+        }
+    
+    CleanupStack::PopAndDestroy( &addr );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::ActivateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::ActivateL()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        component->ActivateL();
+        iPendingArray.AppendL( component->StreamId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::DeActivateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::DeActivateL()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        CNSPMediaStreamComponent* component = iStreamComponentArray[index];
+        component->DeActivateL();
+        iPendingArray.AppendL( component->StreamId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::CollectionId
+// ---------------------------------------------------------------------------
+//
+TUint CNSPMediaStream::CollectionId() const
+    {
+    return iCollectionId;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::MediaField
+// ---------------------------------------------------------------------------
+//
+const CSdpMediaField& CNSPMediaStream::MediaField() const
+    {
+    return (*iMediaField);
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::SetInboundCredentialsL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::SetInboundCredentialsL()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        iStreamComponentArray[index]->SetCredentialsL( *iInboundCredentials );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::SetOutboundCredentialsL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::SetOutboundCredentialsL()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        iStreamComponentArray[index]->SetCredentialsL( *iOutboundCredentials );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::SetOutboundCredentialsL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::SetOutboundCredentials( CNATFWCredentials* aOutboundCredentials )
+    {
+    if ( iOutboundCredentials != aOutboundCredentials )
+        {
+        delete iOutboundCredentials;
+        iOutboundCredentials = aOutboundCredentials;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::NeedToUpdate
+// ---------------------------------------------------------------------------
+//
+TBool CNSPMediaStream::NeedToUpdateL()
+    {
+    TBool needUpdate = EFalse;
+    
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount && !needUpdate; index++ )
+        {
+        const CNATFWCandidate& local =
+                (*iStreamComponentArray[index]->LocalCandidates()[0]);
+        const CNATFWCandidate& working =
+                iStreamComponentArray[index]->IceLocalCandidateL();
+        
+        needUpdate = !(
+                !working.TransportDomainAddr().Compare( local.TransportDomainAddr() ) &&
+                working.TransportDomainPort() == local.TransportDomainPort() );
+        }
+    
+    return needUpdate;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::ResetAndDestroyCandidates
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::ResetAndDestroyCandidates()
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        iStreamComponentArray[index]->ResetAndDestroyCandidates();
+        }    
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::RemovePending
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStream::RemovePending( TUint aStreamId, TBool aRemove )
+    {
+    TNatReturnStatus status = KNatAsync;
+    
+    if ( aRemove )
+        {
+        const TInt index = iPendingArray.Find( aStreamId );
+        
+        if ( KErrNotFound != index )
+            {
+            iPendingArray.Remove( index );
+            iPendingArray.Compress();
+            status = ( iPendingArray.Count() ? KNatAsync : KNatReady );
+            }
+        else
+            {
+            status = KNatAsync;
+            }
+        }
+    
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::AttachCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStream::AttachCandidatesL(
+        RPointerArray<CNATFWCandidate>& aRemoteCandidates ) const
+    {
+    const TInt candidatecount( aRemoteCandidates.Count() );
+    for ( TInt index = 0; index < candidatecount; index++ )
+        {
+        aRemoteCandidates[index]->SetSessionId( iSessionId );
+        aRemoteCandidates[index]->SetStreamCollectionId( iCollectionId );
+        
+        TBool attach( EFalse );
+        const TInt componentcount( iStreamComponentArray.Count() );
+        for ( TInt jndex = 0; jndex < componentcount && !attach ; jndex++ )
+            {
+            attach = iStreamComponentArray[jndex]->AttachCandidateL(
+                                *aRemoteCandidates[index] );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStream::FindMediaComponent
+// ---------------------------------------------------------------------------
+//
+TInt CNSPMediaStream::FindMediaComponent( TUint aStreamId )
+    {
+    const TInt componentcount( iStreamComponentArray.Count() );
+    for ( TInt index = 0; index < componentcount; index++ )
+        {
+        if ( iStreamComponentArray[index]->StreamId() == aStreamId )
+            {
+            return index;
+            }
+        }
+    
+    return KErrNotFound;
+    }
+
+// end of file