diff -r 000000000000 -r 1bce908db942 natfw/natfwconnectionmultiplexer/src/cncmconnectionobserverhandler.cpp --- /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( + 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 ); + }