--- /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 );
+ }