natplugins/natpnatfwsdpprovider/src/nspmediastreamcontainer.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/natplugins/natpnatfwsdpprovider/src/nspmediastreamcontainer.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,904 @@
+/*
+* 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:  Container for NAT FW streams, class implementation.
+*
+*/
+
+#include <sdpdocument.h>
+#include <sdpconnectionfield.h>
+#include <sdpmediafield.h>
+#include "natfwcredentials.h"
+#include "natfwcandidate.h"
+#include "natfwcandidatepair.h"
+#include "nspmediastreamcontainer.h"
+#include "nspmediastream.h"
+#include "nspcontrollerif.h"
+#include "nspcontentparser.h"
+#include "nsputil.h"
+#include "nspdefs.h"
+
+const TInt KMaxLengthOfFQDN = 255;
+const TUint KDefaultTosValue = 184;
+const TUint KMaxTosValue = 255;
+
+#define FINDSTREAM_L( stream, mediafield, streamarray )\
+    User::LeaveIfNull( stream = NSPUtil::FindMediaStream( mediafield, streamarray ) )
+#define FINDSTREAM( mediafield, streamarray )\
+    NSPUtil::FindMediaStream( mediafield, streamarray )
+#define FINDSTREAM_NOREJECT( mediafield, streamarray )\
+    ( !NSPUtil::IsReject( mediafield ) ? FINDSTREAM( mediafield, streamarray ) : NULL )
+
+#define FINDFIELD_L( field, mediastream, fieldarray )\
+    User::LeaveIfNull( field = NSPUtil::FindMediaField( mediastream, fieldarray ) )
+#define FINDFIELD( mediastream, fieldarray )\
+    NSPUtil::FindMediaField( mediastream, fieldarray )
+#define FINDFIELD_NOREJECT( mediastream, fieldarray )\
+    ( !NSPUtil::IsReject( *FINDFIELD( mediastream, fieldarray ) ) ? FINDFIELD( mediastream, fieldarray ) : NULL )
+
+// ======== MEMBER FUNCTIONS ========
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::CNSPMediaStreamContainer
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStreamContainer::CNSPMediaStreamContainer(
+        MNSPControllerIF& aController, TUint aSessionId, TUint aProtocol )
+    : iController( aController ),
+      iSessionId( aSessionId ),
+      iProtocol( aProtocol ),
+      iMediaTos( KDefaultTosValue )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::NewL
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStreamContainer* CNSPMediaStreamContainer::NewL(
+        MNSPControllerIF& aController, TUint aSessionId, TUint aProtocol )
+    {
+    CNSPMediaStreamContainer* self = CNSPMediaStreamContainer::NewLC(
+            aController, aSessionId, aProtocol );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::NewLC
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStreamContainer* CNSPMediaStreamContainer::NewLC(
+        MNSPControllerIF& aController, TUint aSessionId, TUint aProtocol )
+    {
+    CNSPMediaStreamContainer* self =  new ( ELeave ) CNSPMediaStreamContainer(
+            aController, aSessionId, aProtocol );
+    CleanupStack::PushL( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::~CNSPMediaStreamContainer
+// ---------------------------------------------------------------------------
+//
+CNSPMediaStreamContainer::~CNSPMediaStreamContainer()
+    {
+    iPendingArray.Close();
+    iStreamArray.ResetAndDestroy();
+    iStreamArray.Close();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::ControlMediaL
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStreamContainer::ControlMediaL( TUint aStreamId,
+		MNATFWConnectivityObserver::TNATFWConnectivityEvent aEvent,
+		TInt aError, TAny* aData )
+	{
+    TNatReturnStatus status = KErrNone;
+    const TInt index = FindMediaStream( aStreamId );
+	
+    if ( KErrNotFound != index )
+        {
+        status = iStreamArray[index]->ControlMediaL( aStreamId, aEvent, aError, aData );
+        const TInt collectionId = iStreamArray[index]->CollectionId();
+        TNatReturnStatus cont = RemovePending( collectionId, KNatReady == status );
+        status = ( KNatReady == status ? cont : status );
+        }
+    else
+    	{
+    	status = KErrNotFound;
+    	}
+    
+    return status;
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::UpdateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::UpdateL( RPointerArray<CNATFWCandidate>& aRemoteCands )
+    {
+    __ASSERT_ALWAYS( &aRemoteCands, User::Leave( KErrArgument ) );
+    iController.UpdateIceProcessingL( iSessionId, aRemoteCands );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::SetRoleL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::SetRoleL( TNATFWIceRole aRole )
+    {
+    iController.SetRoleL( iSessionId, aRole );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::SetInboundCredentialsL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::SetInboundCredentialsL()
+    {
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->SetInboundCredentialsL();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::SetOutboundCredentialsL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::SetOutboundCredentialsL()
+    {
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->SetOutboundCredentialsL();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::ResetAndDestroyCandidates
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::ResetAndDestroyCandidates()
+    {
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->ResetAndDestroyCandidates();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::LoadPluginL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::LoadPluginL( CDesC8Array& aPlugins, TInt& aPluginIndex )
+    {
+    __ASSERT_ALWAYS( &aPlugins, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( &aPluginIndex, User::Leave( KErrArgument ) );
+    
+    iController.LoadPluginL( iSessionId, aPlugins, aPluginIndex );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::FetchCandidateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::FetchCandidateL()
+    {
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->FetchCandidateL();
+        iPendingArray.AppendL( iStreamArray[index]->CollectionId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::FetchCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::FetchCandidatesL()
+    {
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->FetchCandidatesL();
+        iPendingArray.AppendL( iStreamArray[index]->CollectionId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::PerformCandidateChecksL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::PerformCandidateChecksL(
+        RPointerArray<CNATFWCandidate>& aRemoteCandidates )
+    {
+    __ASSERT_ALWAYS( &aRemoteCandidates, User::Leave( KErrArgument ) );
+    
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->PerformCandidateChecksL();
+        iPendingArray.AppendL( iStreamArray[index]->CollectionId() );
+        }
+    
+    iController.PerformCandidateChecksL( iSessionId, aRemoteCandidates );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::ActivateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::ActivateL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    CSdpMediaField* field = NULL;
+    CSdpConnectionField* connField = aDoc.ConnectionField();
+    const TDesC8& address = ( connField ? connField->Address() : KNullDesC8 );
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        field = NSPUtil::FindMediaField( *iStreamArray[index], mediafields );
+        iStreamArray[index]->ActivateL( *field, address );
+        iPendingArray.AppendL( iStreamArray[index]->CollectionId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::ActivateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::ActivateL()
+    {
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->ActivateL();
+        iPendingArray.AppendL( iStreamArray[index]->CollectionId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::DeActivateL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::DeActivateL()
+    {
+    const TInt mediastreamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamcount ; index++ )
+        {
+        iStreamArray[index]->DeActivateL();
+        iPendingArray.AppendL( iStreamArray[index]->CollectionId() );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::CreateStreamsL
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStreamContainer::CreateStreamsL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    const CSdpConnectionField* connField = aDoc.ConnectionField();
+    const TDesC8& address = ( connField ? connField->Address() : KNullDesC8 );
+    
+    TNatReturnStatus status = KNatReady;
+    CNSPMediaStream* stream = NULL;
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldcount( mediafields.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldcount != 0, User::Leave( KErrNotFound ) );
+    
+    for ( TInt index = 0; index < mediafieldcount; index++ )
+         {
+         stream = NSPUtil::FindMediaStream( *mediafields[index], iStreamArray );
+         if( NSPUtil::IsReject( *mediafields[index] ) || ( stream && 
+        	  stream->MediaField().Port() ==  ( *mediafields[index] ).Port() ) )
+            {
+            NSPLOG_STR( "No need to create stream" )
+            }
+		    else 
+		        {
+            if ( stream ) 
+            	  { 
+			          RemoveStream( stream );
+			          }
+            stream = CNSPMediaStream::NewLC( iController, *mediafields[index],
+        	               iSessionId, iController.CreateUniqueId(), address,
+        	               iProtocol, iMediaTos );
+        	  iStreamArray.AppendL( stream );
+        	  CleanupStack::Pop( stream );
+        	  status = KNatAsync;
+		        }
+	        }
+    
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::RemoveStreamsL
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStreamContainer::RemoveStreamsL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    TNatReturnStatus status = KNatReady;
+    CSdpMediaField* field = NULL;
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldcount( mediafields.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldcount != 0, User::Leave( KErrNotFound ) );
+    
+    for ( TInt index = 0; index < iStreamArray.Count(); )
+        {
+        field = FINDFIELD_NOREJECT( *iStreamArray[index], mediafields );
+        
+        if ( !field )
+            {
+            delete iStreamArray[index];
+            iStreamArray.Remove(index);
+            iStreamArray.Compress();
+            status = KNatAsync;
+            }
+        else
+            {
+            index++;
+            }
+        }
+    
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::ModStunSolvedL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::ModStunSolvedL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    TBool sessionlevel = EFalse;
+    CNSPMediaStream* stream = NULL;
+    CSdpConnectionField* connField = aDoc.ConnectionField();
+    CSdpOriginField* originField = aDoc.OriginField();
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldscount( mediafields.Count() );
+    const TInt mediastreamscount( iStreamArray.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldscount != 0, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( mediastreamscount != 0, User::Leave( KErrNotFound ) );
+
+    RBuf8 addr;
+    addr.CreateL( KMaxLengthOfFQDN );
+    addr.CleanupClosePushL();
+    
+    for ( TInt index = 0; index < mediafieldscount; index++ )
+        {
+        stream = FINDSTREAM_NOREJECT( *mediafields[index], iStreamArray );
+        
+        if ( stream )
+            {
+            stream->ModifyStunConnL( *mediafields[index], addr );
+            
+            if ( !sessionlevel )
+                {
+                if ( connField )
+                    {
+                    NSPUtil::UpdateConnectionFieldL( *connField, addr );
+                    }
+                
+                if ( originField )
+                    {
+                    NSPUtil::UpdateOriginFieldL( *originField, addr );
+                    }
+                
+                sessionlevel = ETrue;
+                }
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( &addr );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::ModIceSolvedL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::ModIceSolvedL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    TBool sessionlevel = EFalse;
+    CNSPMediaStream* stream = NULL;
+    CSdpConnectionField* connField = aDoc.ConnectionField();
+    CSdpOriginField* originField = aDoc.OriginField();
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldscount( mediafields.Count() );
+    const TInt mediastreamscount( iStreamArray.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldscount != 0, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( mediastreamscount != 0, User::Leave( KErrNotFound ) );
+    
+    RBuf8 addr;
+    addr.CreateL( KMaxLengthOfFQDN );
+    addr.CleanupClosePushL();
+    
+    for ( TInt index = 0; index < mediafieldscount; index++ )
+        {
+        stream = FINDSTREAM_NOREJECT( *mediafields[index], iStreamArray );
+        
+        if ( stream )
+            {
+            stream->ModifyIceConnL( *mediafields[index], addr );
+            
+            if ( !sessionlevel )
+                {
+                if ( connField )
+                    {
+                    NSPUtil::UpdateConnectionFieldL( *connField, addr );
+                    }
+                
+                if ( originField )
+                    {
+                    NSPUtil::UpdateOriginFieldL( *originField, addr );
+                    }
+                
+                sessionlevel = ETrue;
+                }
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( &addr );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::ModLocalSolvedL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::ModLocalSolvedL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    TBool sessionlevel = EFalse;
+    CNSPMediaStream* stream = NULL;
+    CSdpConnectionField* connField = aDoc.ConnectionField();
+    CSdpOriginField* originField = aDoc.OriginField();
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldscount( mediafields.Count() );
+    const TInt mediastreamscount( iStreamArray.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldscount != 0, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( mediastreamscount != 0, User::Leave( KErrNotFound ) );
+    
+    RBuf8 addr;
+    addr.CreateL( KMaxLengthOfFQDN );
+    addr.CleanupClosePushL();
+    
+    for ( TInt index = 0; index < mediafieldscount; index++ )
+        {
+        stream = FINDSTREAM_NOREJECT( *mediafields[index], iStreamArray );
+        
+        if ( stream )
+            {
+            stream->ModifyLocalConnL( *mediafields[index], addr );
+            
+            if ( !sessionlevel )
+                {
+                if ( connField )
+                    {
+                    NSPUtil::UpdateConnectionFieldL( *connField, addr );
+                    }
+                
+                if ( originField )
+                    {
+                    NSPUtil::UpdateOriginFieldL( *originField, addr );
+                    }
+                
+                sessionlevel = ETrue;
+                }
+            }
+        else
+            {
+            NSPUtil::RejectL( *mediafields[index] );
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( &addr );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::AddIceContentL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::AddIceContentL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    CNSPMediaStream* stream = NULL;
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldscount( mediafields.Count() );
+    const TInt mediastreamscount( iStreamArray.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldscount != 0, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( mediastreamscount != 0, User::Leave( KErrNotFound ) );
+    
+    for ( TInt index = 0; index < mediafieldscount; index++ )
+        {
+        FINDSTREAM_L( stream, *mediafields[index], iStreamArray );
+        stream->AddCredentialsL( *mediafields[index] );
+        stream->AddLocalCandidatesL( *mediafields[index] );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::AddRemoteCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CNSPMediaStreamContainer::AddRemoteCandidatesL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    CNSPMediaStream* stream = NULL;
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldcount( mediafields.Count() );
+    for ( TInt index = 0; index < mediafieldcount; index++ )
+        {
+        FINDSTREAM_L( stream, *mediafields[index], iStreamArray );
+        stream->AddRemoteCandidatesL( *mediafields[index] );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::GetCandidatesL
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStreamContainer::GetCandidatesL( CSdpDocument& aDoc,
+        RPointerArray<CNATFWCandidate>& aRemoteCandidates )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( &aRemoteCandidates, User::Leave( KErrArgument ) );
+    
+    TNatReturnStatus status = KNatReady;
+    CNSPMediaStream* stream = NULL;
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldscount( mediafields.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldscount != 0, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( iStreamArray.Count() != 0, User::Leave( KErrNotFound ) );
+    
+    for ( TInt index = 0; index < mediafieldscount; index++ )
+        {
+        RPointerArray<CNATFWCandidate> remotecands;
+        CleanupStack::PushL( TCleanupItem( NSPUtil::CleanupArrayItem, &remotecands ) );
+        stream = FINDSTREAM( *mediafields[index], iStreamArray );
+        
+        if ( stream )
+            {
+            stream->GetCandidatesL( *mediafields[index], remotecands );
+            
+            while ( 0 < remotecands.Count() )
+                {
+                if ( NSPUtil::IsDuplicate( *remotecands[0], aRemoteCandidates ) )
+                    {
+                    delete remotecands[0];
+                    }
+                else
+                    {
+                    aRemoteCandidates.AppendL( remotecands[0] );// ownership transferred
+                    status = KNatAsync;
+                    }
+                
+                remotecands.Remove(0);
+                remotecands.Compress();
+                }
+            }
+        
+        CleanupStack::PopAndDestroy(); // remotecands
+        }
+    
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::GetCredentialsL
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStreamContainer::GetCredentialsL( CSdpDocument& aDoc,
+        CNATFWCredentials& aSessionlevel )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( &aSessionlevel, User::Leave( KErrArgument ) );
+    
+    TNatReturnStatus status = KNatReady;
+    CNSPMediaStream* stream = NULL;
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldscount( mediafields.Count() );
+    const TInt mediastreamscount( iStreamArray.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldscount != 0, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( mediastreamscount != 0, User::Leave( KErrNotFound ) );
+    
+    CNATFWCredentials* sessionLevel = CNATFWCredentials::NewLC();
+    sessionLevel->SetDirection( CNATFWCredentials::EOutbound );
+    iController.ContentParser().GetCredentialsL( aDoc, *sessionLevel );
+    
+    if ( !CNATFWCredentials::Compare( aSessionlevel, *sessionLevel ) )
+        {
+        aSessionlevel.CopyL( *sessionLevel );
+        status = KNatAsync;
+        }
+    
+    CleanupStack::PopAndDestroy( sessionLevel );
+    
+    for ( TInt index = 0; index < mediafieldscount; index++ )
+        {
+        CNATFWCredentials* mediaLevel = CNATFWCredentials::NewLC( aSessionlevel );
+        iController.ContentParser().GetCredentialsL( *mediafields[index], *mediaLevel );
+        CleanupStack::Pop( mediaLevel );
+        
+        stream = FINDSTREAM( *mediafields[index], iStreamArray );
+        
+        if ( stream )
+            {
+            stream->SetOutboundCredentials( mediaLevel ); // ownership changed.
+            }
+        else
+            {
+            delete mediaLevel;
+            }
+        }
+    
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::GetSessionConnInfoL
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStreamContainer::GetSessionConnInfoL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    TNatReturnStatus status = KNatReady;
+    TNatReturnStatus mediastatus = status;
+    CNSPMediaStream* stream = NULL;
+    CSdpConnectionField* connField = aDoc.ConnectionField();
+    const TDesC8& address = ( connField ? connField->Address() : KNullDesC8 );
+    RPointerArray<CSdpMediaField>& mediafields = aDoc.MediaFields();
+    
+    const TInt mediafieldscount( mediafields.Count() );
+    const TInt mediastreamscount( iStreamArray.Count() );
+    
+    __ASSERT_ALWAYS( mediafieldscount != 0, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( mediastreamscount != 0, User::Leave( KErrNotFound ) );
+
+    RBuf8 addr;
+    addr.CreateL( KMaxLengthOfFQDN );
+    addr.CleanupClosePushL();
+    
+    for ( TInt index = 0; index < mediafieldscount; index++ )
+        {
+        stream = FINDSTREAM( *mediafields[index], iStreamArray );
+        
+        if ( stream )
+            {
+            addr = address;
+            mediastatus = stream->MediaConnInfoL( *mediafields[index], addr );
+            status = ( KNatReady == status ? mediastatus : status );
+            addr.Zero();
+            }
+        else
+            {
+            NSPUtil::RejectL( *mediafields[index] );
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( &addr );
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::CheckUpdateL
+// ---------------------------------------------------------------------------
+//
+CSdpDocument* CNSPMediaStreamContainer::CheckUpdateL( CSdpDocument& aDoc )
+    {
+    __ASSERT_ALWAYS( &aDoc, User::Leave( KErrArgument ) );
+    
+    TBool needToUpdate = EFalse;
+    CSdpDocument* update = NULL;
+    
+    const TInt mediastreamscount( iStreamArray.Count() );
+    
+    __ASSERT_ALWAYS( mediastreamscount != 0, User::Leave( KErrNotFound ) );
+    
+    for ( TInt index = 0; index < mediastreamscount && !needToUpdate; index++ )
+        {
+        needToUpdate = iStreamArray[index]->NeedToUpdateL();
+        }
+    
+    if ( needToUpdate )
+        {
+        ModIceSolvedL( aDoc );
+        update = aDoc.CloneL();
+        }
+    
+    return update;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::SetMediaTos
+// ---------------------------------------------------------------------------
+//
+TInt CNSPMediaStreamContainer::SetMediaTos( TUint aMediaTos )
+    {
+    if ( KMaxTosValue >= aMediaTos )
+        {
+        iMediaTos = aMediaTos;
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::MediaTos
+// ---------------------------------------------------------------------------
+//
+TUint CNSPMediaStreamContainer::MediaTos() const
+    {
+    return iMediaTos;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::RemovePending
+// ---------------------------------------------------------------------------
+//
+TNatReturnStatus CNSPMediaStreamContainer::RemovePending(
+        TUint aComponentId, TBool aRemove )
+    {
+    TNatReturnStatus status = KNatAsync;
+    
+    if ( aRemove )
+        {
+        const TInt index = iPendingArray.Find( aComponentId );
+        
+        if ( KErrNotFound != index )
+            {
+            iPendingArray.Remove( index );
+            iPendingArray.Compress();
+            status = ( iPendingArray.Count() ? KNatAsync : KNatReady );
+            }
+        else
+            {
+            status = KNatAsync;
+            }
+        }
+    
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::FindMediaStream
+// ---------------------------------------------------------------------------
+//
+TInt CNSPMediaStreamContainer::FindMediaStream( TUint aStreamId )
+    {
+    const TInt streamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < streamcount; index++ )
+        {
+        if ( iStreamArray[index]->HasMediaComponent( aStreamId ) )
+            {
+            return index;
+            }
+        }
+    
+    return KErrNotFound;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::FindCollection
+// ---------------------------------------------------------------------------
+//
+TInt CNSPMediaStreamContainer::FindCollection( TUint aCollectionId )
+    {
+    const TInt streamcount( iStreamArray.Count() );
+    for ( TInt index = 0; index < streamcount; index++ )
+        {
+        if ( iStreamArray[index]->CollectionId() == aCollectionId )
+            {
+            return index;
+            }
+        }
+    
+    return KErrNotFound;
+    }
+    
+    
+// ---------------------------------------------------------------------------
+// CNSPMediaStreamContainer::RemoveStream
+// ---------------------------------------------------------------------------
+//
+TInt CNSPMediaStreamContainer::RemoveStream( CNSPMediaStream* aStream )
+    {
+    TInt status = KErrNotFound;
+    const TInt mediastreamscount( iStreamArray.Count() );
+    for ( TInt index = 0; index < mediastreamscount; index++ )
+         {
+         if ( iStreamArray[index] == aStream ) 
+             {
+			       delete iStreamArray[index];
+	           iStreamArray.Remove(index);
+	           iStreamArray.Compress();
+	           status = KErrNone;
+	           return status;
+	           }      
+		     }
+    return status;
+    }
+
+
+// end of file