rtp/srtpstack/src/srtpsession.cpp
changeset 0 307788aac0a8
--- /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);
+			}	
+		}
+	}