--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rtp/srtpstack/src/srtpsession.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,492 @@
+/*
+* Copyright (c) 2004 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: Contains a default cryptographic context for SRTP streams.
+*
+*/
+
+
+
+
+// INCLUDES
+#include "srtpsession.h"
+#include "srtpstream.h"
+#include "srtpcryptocontext.h"
+#include "srtpstreamin.h"
+#include "srtpstreamout.h"
+#include "msrtprekeyingobserver.h"
+#include "srtputils.h"
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor. Used when stream uses default cryptographic context
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CSRTPSession* CSRTPSession::NewL( const TInetAddr& aDestination )
+ {
+ CSRTPSession* self = CSRTPSession::NewLC( aDestination );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor. Used when stream uses its own cryptographic context
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CSRTPSession* CSRTPSession::NewL( const TInetAddr& aDestination,
+ CSRTPCryptoContext* aCon,
+ MSRTPReKeyingObserver& aObs )
+ {
+ CSRTPSession* self = CSRTPSession::NewLC( aDestination, aCon, aObs );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor. Used when stream uses its own cryptographic context
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CSRTPSession* CSRTPSession::NewLC( const TInetAddr& aDestination )
+ {
+ CSRTPSession* self = new( ELeave ) CSRTPSession ( aDestination );
+ CleanupStack::PushL( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor. Used when stream uses its own cryptographic context
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CSRTPSession* CSRTPSession::NewLC( const TInetAddr& aDestination,
+ CSRTPCryptoContext* aCon,
+ MSRTPReKeyingObserver& aObs )
+ {
+ CSRTPSession* self = new( ELeave ) CSRTPSession ( aDestination, aObs );
+ CleanupStack::PushL( self );
+ self->ConstructL( aCon );
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSRTPSession::CSRTPSession
+// -----------------------------------------------------------------------------
+//
+ CSRTPSession::CSRTPSession( const TInetAddr& aDestination,
+ MSRTPReKeyingObserver& aObs )
+ : iStreamList(CSRTPStream::iStreamOffset),
+ iStreamIter( iStreamList ),
+ iDestination(aDestination),
+ iObserver(&aObs),
+ iStreamCount(NULL),
+ iRekey(EFalse)
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CSRTPSession::CSRTPSession
+// -----------------------------------------------------------------------------
+//
+ CSRTPSession::CSRTPSession(const TInetAddr& aDestination)
+ : iStreamList(CSRTPStream::iStreamOffset),
+ iStreamIter( iStreamList ),
+ iDestination(aDestination),
+ iContext(NULL),
+ iObserver(NULL),
+ iStreamCount(NULL),
+ iSesssionCrypto(EFalse),
+ iRekey(EFalse)
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CSRTPSession::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSRTPSession::ConstructL( CSRTPCryptoContext* aCon )
+ {
+ if( !aCon )
+ {
+ //delete this;// because of NewLC so we need to delete it
+ User::Leave( KErrArgument );
+ }
+ else
+ {
+ if (!aCon->Valid())
+ {
+ User::Leave( KErrArgument );
+ }
+ iSesssionCrypto=ETrue;
+ iContext = aCon;
+
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::~CSRTPSession
+// ---------------------------------------------------------------------------
+//
+CSRTPSession::~CSRTPSession()
+ {
+ if (iContext)
+ {
+ delete iContext;iContext=NULL;
+ }
+ if (iStreamCount)
+ {
+ RemoveAllStream( );
+ }
+ iStreamList.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// CSRTPSession::UpdateCryptoContextL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSRTPSession::SetCryptoContextL(CSRTPCryptoContext* aCon)
+ {
+ //Note that ROC is not re-set.
+ if( !aCon)
+ {
+ User::Leave( KErrArgument );
+ }
+ if (!iRekey )
+ {
+ if (iContext && iSesssionCrypto )
+ {
+ delete iContext;iContext=NULL;
+ }
+ iSesssionCrypto = ETrue;
+ iContext = aCon;
+ //should implement a way that session knows how to updated the stream
+ if (!iStreamList.IsEmpty())
+ {
+ CSRTPStream* item=NULL;
+
+ iStreamIter.SetToFirst();
+ while ((item=iStreamIter++) != NULL)
+ {
+ TRAPD( err, item->UpdateCryptoAndStatesL() );
+ if ( err )
+ {
+ iContext = NULL; // Cannot take ownership if leave occurs
+ User::Leave( err );
+ }
+ }
+ }
+
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CSRTPSession::RemoteAddr()
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TInetAddr& CSRTPSession::RemoteAddr()
+ {
+ return iDestination;
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::StreamL
+// ---------------------------------------------------------------------------
+//
+
+EXPORT_C CSRTPStream& CSRTPSession::StreamL(TUint aSSRC, TBool aIsInStream)
+ {
+ CSRTPStream* item=NULL;
+
+ iStreamIter.SetToFirst();
+ while ((item=iStreamIter++) != NULL)
+ {
+ if (item->SSRC()==aSSRC && aIsInStream== item->StreamType())
+ return *item;
+ }
+ User::Leave(KErrNotFound);
+ return *item;
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::ProtectRTPL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CSRTPSession::ProtectRTPL(TUint aSSRC, const TDesC8& aPacket)
+ {
+ SRTP_DEBUG_DETAIL( "CSRTPSession::ProtectRTPL ENTRY" );
+
+ //find the matching ssrc stream
+ CSRTPStreamOut* stream = static_cast<CSRTPStreamOut*> (&StreamL(aSSRC, EFalse));
+ SRTP_DEBUG_TUINT_VALUE( "aSSRC is", aSSRC);
+
+ //If it is streamIn
+ SRTP_DEBUG_DETAIL( "CSRTPSession::ProtectRTPL EXIT" );
+
+ return stream->ProtectRtpL( aPacket );
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::UnprotectRTPL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CSRTPSession::UnprotectRTPL(TUint aSSRC, const TDesC8& aPacket)
+ {
+ SRTP_DEBUG_DETAIL( "CSRTPSession::UnprotectRTPL ENTRY" );
+
+ //Find Stream by SSRC
+ CSRTPStreamIn* stream;
+ if(FindStream(aSSRC, ETrue))
+ {
+ SRTP_DEBUG_TUINT_VALUE( "not latebinding and stream found and aSSRC is", aSSRC);
+
+ stream= static_cast<CSRTPStreamIn*> (&StreamL(aSSRC, ETrue));
+ //If found
+ return stream->UnprotectSrtpL( aPacket );
+ }
+ //If not found, try to find the stream SSRC=0;
+ SRTP_DEBUG_DETAIL( "UnprotectRTPL is latebinding and If not found, try to find the stream SSRC=0");
+
+ SRTP_DEBUG_DETAIL( "CSRTPSession::UnprotectRTPL EXIT" );
+ return FindLateBindingStreamAndUnprotectRTPL(aSSRC, aPacket);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::ProtectRTCPL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CSRTPSession::ProtectRTCPL(TUint aSSRC, const TDesC8& aPacket)
+ {
+ //find the matching ssrc stream
+ CSRTPStreamOut* stream = static_cast<CSRTPStreamOut*> (&StreamL(aSSRC, EFalse));
+ //If it is streamIn
+ return stream->ProtectRtcpL( aPacket );
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::UnprotectRTPL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CSRTPSession::UnprotectRTCPL(TUint aSSRC, const TDesC8& aPacket)
+ {
+ //Find Stream by SSRC
+ CSRTPStreamIn* stream;
+ if(FindStream(aSSRC, ETrue) )
+ {
+ stream= static_cast<CSRTPStreamIn*> (&StreamL(aSSRC, ETrue));
+ //If found
+ return stream->UnprotectSrtcpL( aPacket );
+ }
+ //If not found, return NULL since there must already some RTP packet received
+ // But for outgoing stream to receive RR and SDES so it should be able to
+ // decod this RTCP packet as well
+ return FindLateBindingStreamAndUnprotectRTCPL(aSSRC, aPacket);
+
+ }
+// ---------------------------------------------------------------------------
+// CSRTPSession::FindStream
+// ---------------------------------------------------------------------------
+//
+
+TBool CSRTPSession::FindStream(TUint aSSRC, TBool aIsInStream )
+ {
+ TBool found=EFalse;
+ TInt count = iStreamCount;
+ CSRTPStream* item=NULL;
+
+ iStreamIter.SetToFirst();
+ item=iStreamIter;
+ while ((item=iStreamIter++) != NULL && count !=0)
+ {
+ if (item->SSRC()==aSSRC && (aIsInStream== item->StreamType()))
+ {
+ found = ETrue;
+ return found;
+ }
+ count --;
+ }
+ return found;
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::FindLateBindingStreamAndUnprotect
+// ---------------------------------------------------------------------------
+//
+
+HBufC8* CSRTPSession::FindLateBindingStreamAndUnprotectRTPL(TUint aSSRC,
+ const TDesC8& aPacket)
+ {
+ SRTP_DEBUG_DETAIL( "CSRTPSession::FindLateBindingStreamAndUnprotectRTPL ENTRY" );
+
+ CSRTPStream* item=NULL;
+
+ iStreamIter.SetToFirst();
+ while ((item=iStreamIter++) != NULL)
+ {
+ //In the case of late binding state unprotect failed but SSRC
+ // has set; we should set it again to the corrected one in the
+ // case SSRC is different from previous one
+ if ((item->StreamType()))
+ {
+ if ((item->SSRC()==0) ||
+ (item->SSRC()!=0 &&
+ static_cast<CSRTPStreamIn*> (item)->iCurrentRTPState==
+ MSRTPStreamInContext::ESRTPStreamInLateBinding)
+ )
+ {
+ SRTP_DEBUG_TUINT_VALUE( "FindLateBindingStreamAndUnprotectRTPL and ssrc is", aSSRC );
+
+ item->SetSSRC(aSSRC);
+ HBufC8* packet= static_cast<CSRTPStreamIn*>
+ (item)->UnprotectSrtpL( aPacket );
+ return packet;
+ }
+ }
+ }
+
+ SRTP_DEBUG_TUINT_VALUE( "NOT Find any match SSRC in FindLBStrmUnprotectRTPL and ssrc is", aSSRC);
+
+ //If not found stream ssrc =0it leaves
+ User::Leave(KErrCorrupt);
+ //keep away warnings
+ SRTP_DEBUG_DETAIL( "CSRTPSession::FindLateBindingStreamAndUnprotectRTPL EXIT" );
+
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::FindLateBindingStreamAndUnprotectRTCP
+// ---------------------------------------------------------------------------
+//
+
+HBufC8* CSRTPSession::FindLateBindingStreamAndUnprotectRTCPL(TUint aSSRC,
+ const TDesC8& aPacket)
+ {
+ SRTP_DEBUG_DETAIL( "CSRTPSession::FindLateBindingStreamAndUnprotectRTCPL ENTRY" );
+
+ CSRTPStream* item=NULL;
+
+ iStreamIter.SetToFirst();
+ while ((item=iStreamIter++) != NULL)
+ {
+ //Only InStreams are handled for received RTCP Packets.
+ if (item->StreamType())
+ {
+ //In the case of late binding state unprotect failed but SSRC
+ // has set; we should set it again to the corrected one in the
+ // case SSRC is different from previous one
+
+ if ((item->SSRC()==0) ||
+ (item->SSRC()!=0 &&
+ static_cast<CSRTPStreamIn*> (item)->iCurrentRTCPState==
+ MSRTPStreamInContext::ESRTPStreamInLateBinding))
+ {
+ CSRTPStreamIn *pStrmIn = static_cast<CSRTPStreamIn*> (item);
+
+ if(pStrmIn->SSRC()!=0 && pStrmIn->iCurrentRTPState == MSRTPStreamInContext::ESRTPStreamInNormal)
+ {
+ if(pStrmIn->SSRC() != aSSRC )
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+ item->SetSSRC(aSSRC);
+ HBufC8* packet= static_cast<CSRTPStreamIn*>
+ (item)->UnprotectSrtcpL( aPacket );
+ return packet;
+ }
+ SRTP_DEBUG_TUINT_VALUE( "FindLateBindingStreamAndUnprotectRTCPL and ssrc is", aSSRC);
+ }
+ }
+ //If not found stream ssrc =0it leaves
+ User::Leave(KErrCorrupt);
+ //keep away warnings
+ SRTP_DEBUG_DETAIL( "CSRTPSession::FindLateBindingStreamAndUnprotectRTCPL EXIT" );
+
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::AddStreamToList()
+// ---------------------------------------------------------------------------
+//
+void CSRTPSession::AddStreamToList(CSRTPStream *aStream)
+ {
+ iStreamList.AddLast(*aStream);
+ ++iStreamCount;
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::RemoveStreamFromListL()
+// ---------------------------------------------------------------------------
+//
+void CSRTPSession::RemoveStreamFromList(CSRTPStream *aStream)
+ {
+ //when there are 2 same stream ...it could not remove
+ TBool found = FindStream(aStream->SSRC(), aStream->StreamType() );
+ if (found)
+ {
+ iStreamList.Remove(*aStream);
+ --iStreamCount;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CSRTPSession::RemoveAllStream
+// ---------------------------------------------------------------------------
+//
+
+void CSRTPSession::RemoveAllStream( )
+ {
+ CSRTPStream* item=NULL;
+ iStreamIter.SetToFirst();
+ item=iStreamIter;
+ while ((item=iStreamIter++) != NULL)
+ {
+ delete item; item=NULL;
+ }
+ }
+// ---------------------------------------------------------------------------
+// void CSRTPSession::GetCryptoContext()
+//
+// ---------------------------------------------------------------------------
+//
+CSRTPCryptoContext& CSRTPSession::GetCryptoContext()
+ {
+ return *iContext;
+ }
+
+
+// ---------------------------------------------------------------------------
+// void CSRTPSession::ReKeyNeeded()
+//
+// ---------------------------------------------------------------------------
+//
+void CSRTPSession::ReKeyNeeded(const CSRTPStream& aStream, TBool aIsStrmCrypto)
+ {
+ if (iObserver)
+ {
+ if (aIsStrmCrypto)
+ {
+ iObserver->SRTPMasterKeyStaleEvent(aStream);
+ }
+ else
+ {
+ iObserver->SRTPMasterKeyStaleEvent(*this);
+ }
+ }
+ }