natfw/natfwconnectionmultiplexer/src/cncmconnectionobserverhandler.cpp
changeset 0 1bce908db942
child 13 fb1bbf85a302
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/natfw/natfwconnectionmultiplexer/src/cncmconnectionobserverhandler.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,495 @@
+/*
+* Copyright (c) 2006-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:    Handler for connection observers on multiplexer
+*
+*/
+
+
+
+
+#include "cncmconnectionobserverhandler.h"
+#include "mncmincomingconnectionobserver.h"
+#include "mncmoutgoingconnectionobserver.h"
+#include "mncmconnectionobserver.h"
+#include "ncmconnectionmultiplexerlogs.h"
+#include "ncmconnectionmultiplexer.hrh"
+#include "cncmmediasource.h"
+#include "ncmconnectionmultiplexerassert.h"
+#include "mncmmessageobserver.h"
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::CNcmConnectionObserverHandler
+// ---------------------------------------------------------------------------
+//
+CNcmConnectionObserverHandler::CNcmConnectionObserverHandler()
+    {
+    }
+
+    
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::NewL
+// ---------------------------------------------------------------------------
+//
+CNcmConnectionObserverHandler*
+    CNcmConnectionObserverHandler::NewL()
+    {
+    __CONNECTIONMULTIPLEXER( 
+        "CNcmConnectionObserverHandler::NewL" )
+        
+    CNcmConnectionObserverHandler* self =
+        CNcmConnectionObserverHandler::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::NewLC
+// ---------------------------------------------------------------------------
+//
+CNcmConnectionObserverHandler* CNcmConnectionObserverHandler::NewLC()
+    {
+    __CONNECTIONMULTIPLEXER( "CNcmConnectionObserverHandler::NewLC" )
+        
+    CNcmConnectionObserverHandler* self =
+        new( ELeave ) CNcmConnectionObserverHandler;
+    CleanupStack::PushL( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::~CNcmConnectionObserverHandlerL
+// ---------------------------------------------------------------------------
+//
+CNcmConnectionObserverHandler::~CNcmConnectionObserverHandler()
+    {
+    __CONNECTIONMULTIPLEXER( 
+        "CNcmConnectionObserverHandler::~CNcmConnectionObserverHandler" )
+        
+    iIncomingObservers.Close();
+    iOutgoingObservers.Close();
+    iConnectionObservers.Close();
+    
+    delete iMediaSource;
+    iMessageObserver = NULL;
+    
+    iLatestHashes.Close();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RegisterOutgoingConnectionObserverL
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::RegisterOutgoingConnectionObserverL(
+    const MNcmOutgoingConnectionObserver& aOutgoingConnectionObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::RegisterOutgoingConnectionObserver" )
+      
+    if ( KErrNotFound == iOutgoingObservers.Find(
+        &aOutgoingConnectionObserver ) )
+        {
+        iOutgoingObservers.AppendL( &aOutgoingConnectionObserver );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RegisterIncomingConnectionObserverL
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::RegisterIncomingConnectionObserverL(
+    const MNcmIncomingConnectionObserver& aIncomingConnectionObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::RegisterIncomingConnectionObserver" )
+   
+    if ( KErrNotFound == iIncomingObservers.Find(
+                                            &aIncomingConnectionObserver ) )
+        {
+        iIncomingObservers.AppendL( &aIncomingConnectionObserver );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::UnregisterOutgoingConnectionObserverL
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::UnregisterOutgoingConnectionObserverL(
+    const MNcmOutgoingConnectionObserver& aOutgoingConnectionObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::UnregisterOutgoingConnectionObserver" )
+       
+    TInt index( 0 );   
+    index = iOutgoingObservers.Find( &aOutgoingConnectionObserver );
+
+    if ( KErrNotFound != index )
+        {
+        iOutgoingObservers.Remove( index );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::UnregisterIncomingConnectionObserver
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::UnregisterIncomingConnectionObserverL(
+    const MNcmIncomingConnectionObserver& aIncomingConnectionObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::UnregisterIncomingConnectionObserver" )
+         
+    TInt index( 0 );  
+    index = iIncomingObservers.Find( &aIncomingConnectionObserver );
+    
+    if ( KErrNotFound != index )
+        {
+        iIncomingObservers.Remove( index );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RegisterConnectionObserverL
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::RegisterConnectionObserverL(
+    const MNcmConnectionObserver& aConnectionObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::RegisterConnectionObserverL" )
+   
+    if ( KErrNotFound == iConnectionObservers.Find( &aConnectionObserver ) )
+        {
+        iConnectionObservers.AppendL( &aConnectionObserver );
+        }
+    }
+ 
+ 
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::UnregisterIncomingConnectionObserver
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::UnregisterConnectionObserverL(
+    const MNcmConnectionObserver& aConnectionObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::UnregisterConnectionObserverL" )
+         
+    TInt index( 0 ); 
+    index = iConnectionObservers.Find( &aConnectionObserver );
+    
+    if ( KErrNotFound != index )
+        {
+        iConnectionObservers.Remove( index );
+        }
+    }   
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RegisterMessageObserver
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::RegisterMessageObserver(
+    MNcmMessageObserver& aMessageObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::RegisterMessageObserverL" )
+    __CONNECTIONMULTIPLEXER_ASSERT_L(
+        NULL == iMessageObserver, KErrNotReady );
+       
+    iMessageObserver = &aMessageObserver;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::UnregisterMessageObserver
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::UnregisterMessageObserver(
+    const MNcmMessageObserver& aMessageObserver )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::UnregisterMessageObserverL" )
+     __CONNECTIONMULTIPLEXER_ASSERT_L( iMessageObserver, KErrNotFound );
+     __CONNECTIONMULTIPLEXER_ASSERT_L(
+        &aMessageObserver == iMessageObserver, KErrArgument );
+         
+    iMessageObserver = NULL;
+    }  
+   
+ 
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::IsDuplicatePacket
+// Used for replicated RTP/RTCP packet filtering. This is quick fix only,
+// usage of KSoReuseAddr should be minimized. Also RSocket::Connect can be
+// used to associate a socket to the explicit remote address. In this case
+// TCP/IP stack does not replicate packet to the other sockets bound to the
+// same local transport address.
+// ---------------------------------------------------------------------------
+//
+TBool CNcmConnectionObserverHandler::IsDuplicatePacket( 
+        const TDesC8& aMessage, TBool& aIsStunMessage )
+    {
+    TUint hash( 0 );
+    TBool isDuplicate( EFalse );
+    aIsStunMessage = EFalse;
+    
+    const TUint KMaxValueOfFirstByteOfStunMsg( 2 );
+    if ( 0 != aMessage.Length() 
+            && KMaxValueOfFirstByteOfStunMsg < aMessage[0] )
+        {
+        // In the beginning of RTP/RTCP header there is two bit long version
+        // field, which has always value of 2. Thus value of first byte of 
+        // RTP/RTCP message is at least 128.
+        const TInt KRtpRtcpDiffByteOffset( 1 );
+        const TInt KLowestAssignedRtcpMsgType = 200;
+        const TInt KHighestAssignedRtcpMsgType = 209;
+        TBool isRtcp = 
+           ( KLowestAssignedRtcpMsgType <= aMessage[KRtpRtcpDiffByteOffset] &&
+            aMessage[KRtpRtcpDiffByteOffset] <= KHighestAssignedRtcpMsgType );
+        
+        // This offset refers either to SR RTP timestamp or RR highest 
+        // sequence number received. These are unique for a distinct 
+        // RTCP packet.
+        const TInt KRtcpDiffByteOffset( 19 );
+        
+        // This offset refers to lower byte of unique RTP sequence number.
+        const TInt KRtpDiffByteOffset( 3 );
+        TInt diffByteOffset 
+            = isRtcp ? KRtcpDiffByteOffset : KRtpDiffByteOffset;
+
+        if ( diffByteOffset < aMessage.Size() )
+            {
+            hash = aMessage[diffByteOffset];
+            }
+        else
+            {
+            __CONNECTIONMULTIPLEXER( 
+            "CNcmConnectionObserverHandler::IsDuplicatePacket INVALID PACKET")
+            return EFalse;
+            }
+
+        if ( KErrNotFound != iLatestHashes.Find( hash ) )
+            {
+            // this is duplicate packet
+            __CONNECTIONMULTIPLEXER(
+                "CNcmConnectionObserverHandler::IsDuplicatePacket TRUE" )
+            isDuplicate = ETrue;
+            }
+        else
+            {
+            isDuplicate = EFalse;
+            }
+        
+        iLatestHashes.Append( hash );
+        const TInt KMaxHashCount( 5 );
+        if ( KMaxHashCount <= iLatestHashes.Count() )
+            {
+            iLatestHashes.Remove( 0 );
+            }
+        }
+    else
+        {
+        __CONNECTIONMULTIPLEXER( 
+            "CNcmConnectionObserverHandler::IsDuplicatePacket STUN MSG")
+            
+        aIsStunMessage = ETrue;
+        }
+    
+    return isDuplicate;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RevealIncomingMessageL
+// ---------------------------------------------------------------------------
+//
+TBool CNcmConnectionObserverHandler::RevealIncomingMessageL(
+    TUint aStreamId, HBufC8*& aMessage, const TInetAddr& aLocalAddr,
+    const TInetAddr& aFromAddr )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::RevealIncomingMessageL" )
+    
+    TBool isStunMessage( EFalse );
+    
+    if ( IsDuplicatePacket( *aMessage, isStunMessage ) )
+        {
+        return ETrue;
+        }
+    
+    TInetAddr peerRemoteAddress( KInetAddrNone, 0 );
+
+    HBufC8* modified( NULL );
+    
+    if ( iMessageObserver )
+        {
+        modified = iMessageObserver->IncomingMessageNotify( 
+            aStreamId, *aMessage, aLocalAddr, aFromAddr, peerRemoteAddress );
+            
+        // replace message if new content is found
+        if ( modified )
+            {
+            delete aMessage;
+            aMessage = modified;
+            }
+        }
+        
+    // offer to all incoming observers and finish when comsumer is found
+    TBool consumed( EFalse );
+    TInt index( iIncomingObservers.Count() );
+        
+    while ( index-- && !consumed )
+        {
+        TRAP_IGNORE( iIncomingObservers[index]->IncomingMessageL( 
+            aStreamId, *aMessage, aLocalAddr, aFromAddr, peerRemoteAddress,
+            consumed ) )
+        }
+    
+    if ( iMediaSource && !consumed && !isStunMessage  )
+        {
+        iMediaSource->PutMessageL( *aMessage );
+        consumed = ETrue;
+        }
+        
+    return consumed;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RevealOutgoingMessageL
+// ---------------------------------------------------------------------------
+//
+TBool CNcmConnectionObserverHandler::RevealOutgoingMessageL(
+    TUint aStreamId, TUint aConnectionId, HBufC8*& aMessage,
+    const TInetAddr& aDestinationAddress )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::RevealOutgoingMessageL" )
+         
+    TInt observerCount( iOutgoingObservers.Count() );
+    TBool consumed( EFalse );
+    HBufC8* modified( NULL );
+    
+    if ( iMessageObserver )
+        {
+        modified = iMessageObserver->OutgoingMessageNotify( 
+            aStreamId, aConnectionId, aDestinationAddress, *aMessage );
+            
+        // replace message if new content is found
+        if ( modified )
+            {
+            delete aMessage;
+            aMessage = modified;
+            }
+        }
+    
+    // offer to all outgoing observers and see if anyone consumed it
+    for ( TInt i = 0; i < observerCount && !consumed; i++ )
+        {
+         iOutgoingObservers[i]->OutgoingMessageL( 
+            aStreamId, aConnectionId, aDestinationAddress, *aMessage,
+            consumed );
+        }
+
+    return consumed;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::ConnectionNotify
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::ConnectionNotify(
+    TUint aStreamId, TUint aConnectionId, 
+    TMultiplexerConnectionNotifyType aType, TInt aError )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::ConnectionNotify, start" )
+    
+    TInt ind( iConnectionObservers.Count() );
+    while ( KErrNotFound != ind-- )
+        {
+        TInt maxIndex( iConnectionObservers.Count() - 1 );
+        
+        ind = ( ind >= maxIndex ) ? maxIndex : ind;
+        
+        if ( KErrNotFound != ind )
+            {
+            iConnectionObservers[ind]->ConnectionNotify( 
+                aStreamId, aConnectionId,
+                static_cast<MNcmConnectionObserver::TConnectionNotifyType>(
+                    aType ), aError ); 
+            }         
+        }
+
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::ConnectionNotify, end" )    
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RegisterMediaSourceL
+// ---------------------------------------------------------------------------
+//
+void CNcmConnectionObserverHandler::RegisterMediaSourceL( 
+    CNcmMediaSource* aMediaSource )
+    {
+    __CONNECTIONMULTIPLEXER(
+        "CNcmConnectionObserverHandler::RegisterMediaSource" )
+    __CONNECTIONMULTIPLEXER_ASSERT_L( NULL != aMediaSource, KErrArgument );
+    delete iMediaSource;
+    iMediaSource = NULL;
+    iMediaSource = aMediaSource;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::RegisterMediaSourceObserver
+// ---------------------------------------------------------------------------
+//      
+void CNcmConnectionObserverHandler::RegisterMediaSourceObserver( 
+    MNcmSourceObserver& aMediaSourceObserver )
+    {
+    __CONNECTIONMULTIPLEXER_ASSERT_L( NULL != iMediaSource, KErrArgument );
+    iMediaSource->RegisterMessageObserver( aMediaSourceObserver );  
+    }
+
+    
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::UnregisterMediaSourceObserver
+// ---------------------------------------------------------------------------
+//     
+void CNcmConnectionObserverHandler::UnregisterMediaSourceObserver(
+    const MNcmSourceObserver& aMediaSourceObserver )
+    {
+    __CONNECTIONMULTIPLEXER_ASSERT_L( NULL != iMediaSource, KErrArgument );
+    iMediaSource->UnregisterMessageObserver( aMediaSourceObserver );   
+    }
+ 
+   
+// ---------------------------------------------------------------------------
+// CNcmConnectionObserverHandler::SetReceivingState
+// ---------------------------------------------------------------------------
+//     
+void CNcmConnectionObserverHandler::SetReceivingState(
+    TNATFWStreamingState aState )
+    {
+    iMediaSource->SetReceivingState( aState );   
+    }