contentmgmt/cafstreamingsupport/test/streamingtestagent/source/server/stasession.cpp
branchRCL_3
changeset 43 2f10d260163b
child 61 641f389e9157
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contentmgmt/cafstreamingsupport/test/streamingtestagent/source/server/stasession.cpp	Mon Mar 15 12:46:43 2010 +0200
@@ -0,0 +1,427 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Implements CStaSession which is server-side session object.
+// 
+//
+
+#include "staserver.h"
+#include "srautils.h"
+
+using namespace StreamAccess;
+using namespace ContentAccess;
+
+CStaSession::CStaSession(CStaServer& aServer)
+/**
+	Intializes the Streaming Test Agent session object with the server handle.
+ */
+	:	CScsSession(aServer)
+		{
+		//empty
+		}
+
+
+CStaSession::~CStaSession()
+/**
+	Destructor.
+ */
+	{
+	delete iBuffer;	
+	delete iKeyStreamSink;
+	delete iRo;
+#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY
+	delete iSdp;
+	delete iSdpDoc;
+#endif
+	}
+
+	
+CStaSession* CStaSession::NewL(CStaServer& aServer)
+/**
+	Factory function allocates new instance of CStaSession.
+	
+	@param aServer  Streaming Test Agent server object.
+	@return			New, initialized instance of CStaSession 
+					which is owned by the caller.
+ */
+	{
+	CStaSession* s = new (ELeave) CStaSession(aServer);
+	CleanupStack::PushL(s);
+	s->ConstructL();
+	CleanupStack::Pop(s);
+	return s;
+	}
+
+
+TBool CStaSession::DoServiceL(TInt aFunction, const RMessage2& aMessage)
+/**
+	Implement CScsSession by handling the supplied message.
+
+	@param	aFunction	Function identifier without SCS code.
+	@param	aMessage	Standard server-side handle to message.
+	@return 			ETrue, if the service is done successfully. Otherwise, EFalse.
+ */
+	{
+	TStaFunction f = static_cast<TStaFunction>(aFunction);
+				
+	switch(f)
+		{
+		case EGetAttribute:
+			GetAttributeL(aMessage);
+			break;
+		case EGetStringAttributeSize:
+			GetStringAttributeSizeL(aMessage);
+			break;
+		case EGetStringAttributeData:
+			GetStringAttributeDataL(aMessage);
+			break;
+		case EGetPostDeliveryRights:
+			GetPostDeliveryRightsL(aMessage);
+			//RMessage2 object is closed by both TransferToClient() and SCS framework.
+			//return EFalse to prevent SCS to close the message object.
+			return EFalse;
+		case ESendKeyStream:
+			GetKeyStreamL(aMessage);
+			break;
+		case ESetKeyStreamSink:
+			SetKeyStreamSinkL(aMessage);
+			break;
+		case ESetSdpKeyStream:
+			SetSdpMediaFieldL(aMessage);
+			break;
+		case ESetSdpDocument:
+			SetSdpDocumentL(aMessage);
+			break;
+		case ESetIpSecAssoc:
+			SetIpSecAssociationL(aMessage);
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+		}
+	return ETrue;
+	}//End of function DoServiceL
+
+
+void CStaSession::GetAttributeL(const RMessage2& aMessage)
+/**
+ 	Returns the value of an attribute requested by the client.
+ 	@param	aMessage	Standard server-side handle to message.
+  */
+	{
+	TAttribute attr;
+	TPckg<TAttribute> attrBuf(attr);
+	aMessage.ReadL(0,attrBuf);
+	
+	VerifyRoL();
+	
+	TBool retVal = EFalse;
+	
+	switch(attr)
+		{
+		case EIsProgramProtected:
+			retVal = iRo->AccessRights() & EProgramProtected;
+			break;
+		case EIsServiceProtected:
+			retVal = iRo->AccessRights() & EServiceProtected;
+			break;
+		case ECanExport:
+			retVal = iRo->AccessRights() & ECanExportContent;
+			break;
+		case EMustProtectIfRecording:
+			retVal = iRo->AccessRights() & EMustProtectContentIfRecording;
+			break;
+		case ECanPlay:
+			retVal = iRo->AccessRights() & ECanPlayContent;
+			break;
+		default:
+			PanicClient(aMessage, KErrCAOutOfRange);
+		}
+	
+	// If the the return value is greater than 0, set the boolean value to ETrue
+	if(retVal)
+		{
+		retVal = ETrue;
+		}
+	
+	TPckg<TBool> retValBuf(retVal);
+	aMessage.WriteL(1, retValBuf);
+	}
+
+
+void CStaSession::GetStringAttributeSizeL(const RMessage2& aMessage)
+/**
+ 	Returns the size of the string attribute requested by the client.
+ 	@param	aMessage	Standard server-side handle to message.
+  */
+	{
+	TStringAttribute strAttr;
+	TPckg<TStringAttribute> strAttrBuf(strAttr);
+	aMessage.ReadL(0,strAttrBuf);
+	
+	VerifyRoL();
+	TInt size = 0;
+	
+	switch(strAttr)
+		{
+		case EContentID:
+			size = iRo->ContentId()->Des().Size();
+			break;
+		case ERightsIssuerURI:
+			size = iRo->RightsIssuer()->Des().Size();
+			break;
+		default:
+			PanicClient(aMessage, KErrCAOutOfRange);
+		}
+	
+	TPckg<TInt> sizeBuf(size);
+	aMessage.WriteL(1, sizeBuf);
+	}
+
+
+void CStaSession::GetStringAttributeDataL(const RMessage2& aMessage)
+/**
+ 	Returns the value of a string attribute requested by the client.
+ 	@param	aMessage	Standard server-side handle to message.
+  */
+	{
+	TStringAttribute strAttr;
+	TPckg<TStringAttribute> strAttrBuf(strAttr);
+	aMessage.ReadL(0,strAttrBuf);
+	
+	VerifyRoL();
+	HBufC8* str = NULL;
+	
+	switch(strAttr)
+	{
+	case EContentID:
+		str = iRo->ContentId();
+		break;
+	case ERightsIssuerURI:
+		str = iRo->RightsIssuer();
+		break;
+	default:
+		PanicClient(aMessage, KErrCAOutOfRange);
+	}
+	TPtr8 ptr(str->Des());
+	aMessage.WriteL(1, ptr);
+	}
+
+
+void CStaSession::GetPostDeliveryRightsL(const RMessage2& aMessage)
+/**
+ 	Returns the file handle of the requested post-acqusition rights, its content id, 
+ 	the post-acquisition rights' mime type and the post-acquisition content's mime type.
+ 	@param	aMessage	Standard server-side handle to message.
+ */ 
+	{
+	VerifyRoL();
+	
+	//In this test agent, a pre-defined post-acquisition rights object is used.
+	//In real-life standards, the post-acquisition rights object would be generated
+	//from the rights object which is used to decode key stream.
+	
+	//Get the file path of the pre-defined post acqusition rights object
+	TFileName fPath(KStaPrivateFolder);
+	fPath[0] = Server()->iFs.GetSystemDriveChar();
+	//Convert 8-bit to 16-bit
+	HBufC* fName = HBufC::NewLC(iRo->ContentId()->Des().Length());
+	TPtr ptrName(fName->Des());
+	ptrName.Copy(iRo->ContentId()->Des());
+	fPath.Append(*fName);
+	fPath.Append(KRoFileExtension);
+	CleanupStack::PopAndDestroy(fName);
+	
+	//Open the post-acqusition rights object file
+	RFile f;
+	User::LeaveIfError(f.Open(Server()->iFs, fPath, EFileRead | EFileShareAny));
+	CleanupClosePushL(f);
+	
+	//Send the content id of the post-acquisition rights object
+	aMessage.WriteL(1, KPostAcquisitionCid());
+	//Send the mime type of the post-acquisition rights object
+	aMessage.WriteL(2, KPostAcquisitionRoMimeType());
+	//Send the mime type of the post-acquisition content
+	aMessage.WriteL(3, KPostAcquisitionContentMimeType());
+	
+	//Pass the file	handle to the client
+	User::LeaveIfError(f.TransferToClient(aMessage, 0));
+	//The message should have been completed
+	ASSERT(aMessage.IsNull());
+	CleanupStack::PopAndDestroy(&f);
+	}
+
+
+void CStaSession::GetKeyStreamL(const RMessage2& aMessage)
+/**
+ 	Gets an encrypyed short-term key from the client.
+ 	@param	aMessage	Standard server-side handle to message.
+  */
+	{
+	TInt len = aMessage.GetDesMaxLengthL(0);
+	HBufC8* shortTermKey = HBufC8::NewLC(len);
+	TPtr8 ptr(shortTermKey->Des());
+	aMessage.ReadL(0,ptr);
+	
+	//Check if the long-term key key exists in the short-term key
+	TInt ret = shortTermKey->Find(*iRo->Key());
+	if(ret == KErrNotFound)
+		{
+		User::Leave(KErrGeneral);
+		}
+	
+	//Get the plain string (key)
+	HBufC8* decryptedKey = HBufC8::NewLC(ret);
+	TPtr8 ptrKey(decryptedKey->Des());
+	ptrKey.Copy(shortTermKey->Des().Ptr(), ret);
+	
+	CTestKeyAssociation* decryptedAssoc = CTestKeyAssociation::NewL(ptrKey);
+	CleanupStack::PushL(decryptedAssoc);
+	
+	iKeyStreamSink->ProcessNewKeyAssociationL(*decryptedAssoc);
+	
+	CleanupStack::PopAndDestroy(3, shortTermKey);
+	}
+
+
+void CStaSession::SetKeyStreamSinkL(const RMessage2& aMessage)
+/**
+ 	Gets a key stream sink from the client.
+ 	@param	aMessage	Standard server-side handle to message.
+  */
+	{
+	TInt len = aMessage.GetDesMaxLengthL(0);
+	HBufC8* des = HBufC8::NewLC(len);
+	TPtr8 ptr(des->Des());
+	aMessage.ReadL(0,ptr);		
+	delete iKeyStreamSink;
+	iKeyStreamSink = NULL;
+	TRAPD(err, 
+		iKeyStreamSink = CKeyStreamSink::InternalizeLC(ptr); 
+		CleanupStack::Pop(iKeyStreamSink););
+	// In addition to the production supported key stream sinks, there is also the Test key stream sink
+	// If the production code could not load the key stream sink, it must be the test key stream sink - load it
+	if (err == KErrNotSupported)		
+		{		
+		RDesReadStream readStream(ptr);
+		CleanupClosePushL(readStream);		
+		iKeyStreamSink = CTestKeyStreamSink::NewL(readStream);
+		CleanupStack::PopAndDestroy(&readStream);
+		}		
+	else
+		User::LeaveIfError(err);	
+	CleanupStack::PopAndDestroy(des);
+	}
+
+void CStaSession::SetIpSecAssociationL(const RMessage2& aMessage)
+	{
+	TInt len = aMessage.GetDesMaxLengthL(0);
+	HBufC8* des = HBufC8::NewLC(len);
+	TPtr8 ptr(des->Des());
+	aMessage.ReadL(0,ptr);
+	
+	RDesReadStream readStream(ptr);
+	CleanupClosePushL(readStream);
+	
+	TInt32 spi = readStream.ReadInt32L();
+	HBufC8* encryptionKey = HBufC8::NewLC(readStream, 128);
+	HBufC8* authenticationKey = HBufC8::NewLC(readStream, 128);
+	
+	CKeyAssociation *ipSecKeyAssociation = CIpSecKeyAssociation::NewLC(spi, encryptionKey, authenticationKey);			
+	iKeyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);
+	CleanupStack::PopAndDestroy(5, des);
+	}
+
+void CStaSession::SetSdpMediaFieldL(const RMessage2& aMessage)
+/**
+ 	Gets an SDP object from the client.
+ 	@param	aMessage	Standard server-side handle to message.
+  */
+	{
+#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY
+	TInt len = aMessage.GetDesMaxLengthL(0);
+	HBufC8* des = HBufC8::NewLC(len);
+	TPtr8 ptr(des->Des());
+	aMessage.ReadL(0,ptr);
+	
+	//Delete previous SDP and rights objects
+	delete iSdp;
+	iSdp = NULL;
+	delete iRo;
+	iRo = NULL;
+	
+	DoSetSdpMediaFieldL(Server()->iFs, iSdp, iRo, ptr, KStaPrivateFolder());
+	CleanupStack::PopAndDestroy(des);
+	
+	//Leave if no RO has been found
+	if(!iRo)
+		{
+		User::Leave(KErrCANoRights);
+		}
+#else
+	(void) aMessage;
+	User::Leave(KErrCANoRights);
+#endif
+	}
+
+void CStaSession::SetSdpDocumentL(const RMessage2& aMessage)
+/**
+ 	Sets the SDP document object coming from the client.
+ 	
+ 	@param	aMessage	Standard server-side handle to message.
+  */
+	{
+#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY
+	TInt len = aMessage.GetDesMaxLengthL(0);
+	HBufC8* des = HBufC8::NewLC(len);
+	TPtr8 ptr(des->Des());
+	aMessage.ReadL(0,ptr);
+	
+	//Delete previous SDPDoc
+	delete iSdpDoc;
+	iSdpDoc = NULL;
+	
+	// Decode the SDP document object from the encoded data
+	iSdpDoc = CSdpDocument::DecodeL(*des);
+	CleanupStack::PopAndDestroy(des);
+#else
+	(void) aMessage;
+#endif
+	}
+
+void CStaSession::VerifyRoL()
+/**
+ 	Verifies that the rights object exists.
+ */
+	{
+	if(!iRo)
+		{//The RO defined in the SDP does not exist
+		User::Leave(KErrCANoRights);
+		}
+	if(iRo->IsExpired())
+		{
+		User::Leave(KErrCANoPermission);
+		}
+	}
+
+void CStaSession::PanicClient(const RMessagePtr2& aMessage, TInt aReason)
+/**
+	Panic the client which sent the supplied message with
+	category KScsClientPanicCat and the supplied reason.
+
+	@param	aMessage		Client message.
+	@param	aReason			Why the client will be panicked.
+	@see KStaClientPanicCat
+ */
+	{
+	aMessage.Panic(KStaClientPanicCat, aReason);
+	}