realtimenetprots/rtp/cfrtp/src/rtpbaseflow.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/rtp/cfrtp/src/rtpbaseflow.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,544 @@
+// Copyright (c) 2008-2009 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:
+// RTP Base Flow Implementation
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <comms-infras/ss_log.h>
+#include <comms-infras/ss_logext.h>
+
+#include <comms-infras/ss_protflow.h>
+
+#include "rtpbaseflow.h"
+#include "rtp_cfmessages.h"
+
+#if defined(ESOCK_LOGGING_ACTIVE)
+_LIT8(KRtpBaseFlowSubTag, "RtpbaseFlow");
+#endif
+
+ESock::MSessionControl* CRtpBaseFlow::GetControlL(TInt aSessionType,ESock::MSessionControlNotify& 
+												aSessionControlNotify)
+	{
+	if(aSessionType != KSockDatagram)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	iSessionControlNotify = &aSessionControlNotify;
+	return this;
+	}
+
+ESock::MSessionData* CRtpBaseFlow::BindL(ESock::MSessionDataNotify& aSessionDataNotify)
+	{
+	
+	ASSERT(!iSessionDataNotify);
+	iSessionDataNotify = &aSessionDataNotify;
+	iSubConnectionProvider.PostMessage(Id(),TCFControlProvider::TActive().CRef());
+	return this;	
+	}
+
+void CRtpBaseFlow::Unbind()
+	{
+	iSessionControlNotify =NULL;
+	iSessionDataNotify = NULL;
+
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t Unbind() "), this));
+
+	/* The Upper flow has left. ASSERT if we still have a Bearer */
+	/* By this time we should have called UnBind() on the lower flow.
+	   so something went wrong(??) */
+	ASSERT(!iSSP && !iFlowBinder);
+
+    ProcessDCIdleState();	
+
+	if(iRecvdImmediateShutDown)
+		{
+		Destroy(); //BANG BANG!!
+		}
+	else
+		{
+		/* Once Defect with HandleDataClients is fixed uncomment this line! */
+		//ProcessDCIdleState();
+		}	
+	}
+									
+CRtpBaseFlow::CRtpBaseFlow(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf)
+: CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf)
+	{
+	}
+
+ 
+ESock::CSubConnectionFlowBase* CRtpBaseFlow::Flow()
+/**
+Return the Flow corresponding to the MFlowBinderControl
+*/
+	{	
+	return this;
+	}
+	
+
+ESock::CSubConnectionFlowBase& CRtpBaseFlow::CloneFlowL()
+/**
+Return the Flow corresponding to the MFlowBinderControl
+*/
+	{
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t CloneFlowL() "), this));
+
+   	ASSERT(iProtocolIntf);
+    TDefaultFlowFactoryQuery query (iProtocolIntf->ControlProviderId(), iSubConnectionProvider.RecipientId());
+	ESock::CSubConnectionFlowBase& flow = static_cast<ESock::CSubConnectionFlowBase&>(*(Factory().CreateObjectL(query)));
+
+	return flow;
+	}	
+	
+CRtpBaseFlow::~CRtpBaseFlow()
+	{
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t ~CRtpBaseFlow() "), this));
+	}
+
+// CSubConnectionFlowBase
+// MCFNode 
+    
+void CRtpBaseFlow::ProcessDCIdleState()
+	{
+	iSubConnectionProvider.PostMessage(Id(),TCFControlProvider::TIdle().CRef());
+	}
+void CRtpBaseFlow::CompleteStart(TInt aError)
+	{
+	if (aError==KErrNone)
+		{
+		iStartRequest.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
+		}
+	else
+		{
+		iStartRequest.ReplyTo(Id(), Messages::TEBase::TError(TCFDataClient::TStart::Id(),aError).CRef());
+		}
+	iIsStarting = EFalse;
+	}
+		
+	
+ESock::MFlowBinderControl* CRtpBaseFlow::DoGetBinderControlL()
+	{		
+    return this;
+	}
+
+void CRtpBaseFlow::BindToL(TCFDataClient::TBindTo& aBindTo)
+	{
+	__ASSERT_DEBUG(!iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	
+	const Messages::TNodeId& commsId = aBindTo.iNodeId;
+	
+#if defined(__GCCXML__)
+    CSubConnectionFlowBase* flow = reinterpret_cast<CSubConnectionFlowBase*>(reinterpret_cast<Messages::ANode*>(commsId.Ptr()));
+#else
+    CSubConnectionFlowBase* flow = mcfnode_cast<CSubConnectionFlowBase>(reinterpret_cast<Messages::ANode*>(commsId.Ptr()));
+#endif
+   if (!flow)
+        {
+        iSubConnectionProvider.PostMessage(Id(),TCFDataClient::TStopped(KErrDisconnected).CRef());
+        User::Leave(KErrArgument);
+        }
+     
+     if (iFlowBinder && iFlowBinder->Flow() != flow )
+    	{
+    	//already bound -> unbind first.
+    	iFlowBinder->Unbind();
+    	iFlowBinder = NULL;
+    	}
+    	
+    if (!iFlowBinder)
+        {
+        iFlowBinder = flow->GetBinderControlL();
+      	iSSP = iFlowBinder->GetControlL(KSockDatagram, *this);
+     	iSSPData = iFlowBinder->BindL(*this);
+        }
+ 	}
+
+void CRtpBaseFlow::StopFlow(TCFDataClient::TStop& aMessage)
+	{
+
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t StopFlow() "), this));
+
+	/* We shud UnBind from the lower flow ? */
+	if (iFlowBinder)
+		{
+		iFlowBinder->Unbind();
+		// Flowbinder takes care of itself from now onwards; forget all downwards pointers
+		iSSP = NULL;
+		iSSPData = NULL;
+		iFlowBinder = NULL;
+		iServiceProvider.Close();
+		}
+	/* Notify data Client is Stopped */
+    iSubConnectionProvider.PostMessage(Id(),TCFDataClient::TStopped(aMessage.iValue).CRef());
+	}
+	
+void CRtpBaseFlow::Destroy()
+	{
+ 	DeleteThisFlow();
+	}
+	
+// MSessionControl
+void CRtpBaseFlow::Shutdown(MSessionControl::TCloseType , const TDesC8& )
+	{
+	
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t Shutdown() Invalid Path PANIC!"), this));	
+
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+
+void CRtpBaseFlow::Shutdown(MSessionControl::TCloseType aOption)
+	{
+	
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t Shutdown() "), this));
+
+	if(iSSP)
+		{
+		LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t Calling Shutdown() - On iSSP"), this));
+		iSSP->Shutdown(aOption);
+		}
+	
+	if(MSessionControl::EImmediate == aOption)
+		{
+		/* So the lower layer will not call CanClose(). Handle everything here
+		 * */
+		LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t Calling Shutdown() MSessionControl::EImmediate"), this));	
+		if (iFlowBinder)
+			{
+			iFlowBinder->Unbind();
+			}
+		
+		// Flowbinder takes care of itself from now onwards; forget all downwards pointers
+		iSSP = NULL;
+		iSSPData = NULL;
+		iFlowBinder = NULL;
+		iServiceProvider.Close();
+		iRecvdImmediateShutDown = ETrue;
+		}
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t Shutdown() Done!"), this));
+	}
+
+void CRtpBaseFlow::ActiveOpen()
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath)); 
+	}
+
+void CRtpBaseFlow::ActiveOpen(const TDesC8& )
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath)); 
+	}
+	
+TInt CRtpBaseFlow::PassiveOpen(TUint )
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath)); 
+	return KErrNotSupported;
+	}
+	
+TInt CRtpBaseFlow::PassiveOpen(TUint ,const TDesC8& )
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath)); 
+	return KErrNotSupported;
+	}
+
+void CRtpBaseFlow::AutoBind()
+	{
+
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t AutoBind() "), this));
+	
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	iSSP->AutoBind();
+	
+	/* Retrive the local address and notify the flows */
+	TSockAddr addr;
+	iSSP->LocalName(addr);
+	DoUpdateLocalAddress(addr);
+	}
+	
+void CRtpBaseFlow::LocalName(TSockAddr& anAddr) const
+	{
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider)); 
+	iSSP->LocalName(anAddr);
+	}
+
+#ifndef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
+TInt CRtpBaseFlow::SetLocalName(TSockAddr& anAddr)
+	{
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	TInt ret;
+	ret = iSSP->SetLocalName(anAddr);
+	if(KErrNone == ret)
+		{
+		DoUpdateLocalAddress(anAddr);
+		}
+	return ret;
+	}
+#else
+void  CRtpBaseFlow::SetLocalName(TSockAddr& anAddr)
+	{
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	
+	iLocalAddress = anAddr;
+	(void)iSSP->SetLocalName(anAddr);
+	
+	
+	}
+#endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
+
+void CRtpBaseFlow::RemName(TSockAddr& anAddr) const
+	{
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	iSSP->RemName(anAddr);
+	return;
+	}
+
+TInt CRtpBaseFlow::SetRemName(TSockAddr& anAddr)
+	{
+	
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t SetRemName() "), this));	
+
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	/* "Normal" UDP Sockets can be connected over and over again. We should disable that because
+	   this donot have any sense for RTP */
+	if(iConnected)
+		{
+		return KErrNotSupported;
+		}
+	
+	TInt ret = iSSP->SetRemName(anAddr);
+	if(KErrNone == ret)
+		{
+		iDestAddr  =  anAddr;
+		iConnected = ETrue;
+		}
+	return ret;
+	}
+	
+void CRtpBaseFlow::ConnectComplete() 
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+	
+void CRtpBaseFlow::ConnectComplete(const TDesC8& ) 
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+	
+void CRtpBaseFlow::ConnectComplete(CSubConnectionFlowBase& ) 
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+	
+void CRtpBaseFlow::ConnectComplete(CSubConnectionFlowBase& ,const TDesC8& )
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+
+TInt CRtpBaseFlow::Error(TInt anError,TUint anOperationMask)
+	{
+	TInt ret = KErrNone;
+
+	LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpBaseFlowSubTag,_L8("CRtpBaseFlow %08x:\t Error() "), this));	
+
+	/* Error message From down or flow error */
+	if(iSessionControlNotify)
+		{
+		ret = iSessionControlNotify->Error(anError,anOperationMask);
+		if (KErrNone != ret)
+	    	{
+	    	if (iFlowBinder)
+				{
+				iFlowBinder->Unbind();
+				}
+			// Flowbinder takes care of itself from now onwards; forget all downwards pointers
+			iSSP = NULL;
+			iSSPData = NULL;
+			iFlowBinder = NULL;
+			iServiceProvider.Close();
+	    	}
+		}
+	return ret;
+	}
+		
+void CRtpBaseFlow::Disconnect()
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+	
+void CRtpBaseFlow::Disconnect(TDesC8& ) 
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+	
+TInt CRtpBaseFlow::SecurityCheck(MProvdSecurityChecker* aSecurityChecker)
+	{ 
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+    /* Pass on the Security check Params to DownStream */
+    return iSSP->SecurityCheck(aSecurityChecker); 
+	}
+	 
+TInt CRtpBaseFlow::GetOption(TUint level, TUint name, TDes8 &anOption) const
+	{ 
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	return DoGetOption(level,name,anOption);
+	}
+	
+TInt CRtpBaseFlow::SetOption(TUint level, TUint name, const TDesC8 &anOption)
+	{
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	return DoSetOption(level, name, anOption);
+	}
+	
+void CRtpBaseFlow::Ioctl(TUint level, TUint name, TDes8 *anOption)
+	{
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	iSSP->Ioctl(level,name,anOption);
+	return;
+	}
+	
+void CRtpBaseFlow::CanSend()
+	{
+	__ASSERT_DEBUG(iSessionDataNotify,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoControlProvider));
+	iSessionDataNotify->CanSend();
+	}
+
+void CRtpBaseFlow::IoctlComplete(TDesC8* aBuf)
+	{
+	__ASSERT_DEBUG(iSessionControlNotify,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoControlProvider));
+	iSessionControlNotify->IoctlComplete(aBuf);
+	}
+	 
+void CRtpBaseFlow::CancelIoctl(TUint aLevel, TUint aName)
+	{
+	__ASSERT_DEBUG(iSSP,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider));
+	iSSP->CancelIoctl(aLevel,aName);
+	return;
+	}
+
+void CRtpBaseFlow::Start()
+	{
+	return;
+	}
+
+// MSessionData
+TUint CRtpBaseFlow::Write(const TDesC8& ,TUint ,TSockAddr* )
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath)); 
+	return 0;	
+	}
+
+void CRtpBaseFlow::GetData(TDes8& ,TUint ,TSockAddr* )
+	{
+	__ASSERT_DEBUG(0,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicUnexpectedExecutionPath));
+	}
+
+void CRtpBaseFlow::NewData(TUint aCount)
+	{
+	__ASSERT_DEBUG(iSessionDataNotify,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoControlProvider));
+	iSessionDataNotify->NewData(aCount);
+	}
+	
+void CRtpBaseFlow::CanClose(MSessionControlNotify::TDelete aDelete)
+/**
+Called from protocol to indicate that a graceful close has completed
+*/
+	{
+	
+	DoCanClose(aDelete);
+
+	if (iFlowBinder)
+		{
+		iFlowBinder->Unbind();
+		}
+		
+	// Flowbinder takes care of itself from now onwards; forget all downwards pointers
+	iSSP = NULL;
+	iSSPData = NULL;
+	iFlowBinder = NULL;
+	iServiceProvider.Close();
+	
+	/* Now pass this up to the ControlProvider */
+	iSessionControlNotify->CanClose(aDelete);
+	}
+
+void CRtpBaseFlow::CanClose(const TDesC8& , MSessionControlNotify::TDelete aDelete)
+/**
+Called from protocol to indicate that a graceful close has completed with disconnect data
+*/
+	{
+	/* Will we ever reach here? */
+	CanClose(aDelete);
+	}
+	
+
+TInt CRtpBaseFlow::HandleProvisionMessage(Messages::TSignatureBase&)
+/* Helper funtion that will send a No Bearer and save the Activity ID */
+	{
+	/* The custom message TRtpMessageReadyForBind should be send to the SCPR once we get
+    the response for NoNearer. The RtpScprBinderRequest activity will be waiting for this
+    request */
+	iSubConnectionProvider.PostMessage(Id(),TCFControlProvider::TNoBearer().CRef());
+		
+	iWaitingForBindTo = ETrue;
+	
+	return KErrNone;
+	}
+
+
+TInt CRtpBaseFlow::HandleBindToMessage(Messages::TSignatureBase& , TInt aErrCode)
+/* Creates and Sends a provision Done message with the Error Code */
+	{
+	/* Got the Bearer. Finish off the BinderRequest acitivity  */
+	TRtpMessages::TRtpMessageReadyForBind provDoneMsg(aErrCode);
+	iSubConnectionProvider.PostMessage(Id(),provDoneMsg);
+	iWaitingForBindTo = EFalse;
+	return KErrNone;
+	}
+
+
+TInt CRtpBaseFlow::HandleError(TInt aErrorCode)
+/* Handles a TError Message from SubConnection */
+	{
+	/* Check if we were waiting for BindToMessage. If we were waiting then
+	   send a failure to Provision Done Message. This will free up the SCPR
+	   activity socket open will fail */
+	if(iWaitingForBindTo)
+		{
+		TRtpMessages::TRtpMessageReadyForBind provDoneMsg(KErrCompletion);
+		iSubConnectionProvider.PostMessage(Id(),provDoneMsg);
+		iWaitingForBindTo = EFalse;
+		/* At this point we shud not have a CP shud we be doing this? */
+		Error(aErrorCode);
+		/*The bearer has failed. So kill ourselves*/
+		Destroy();
+		}
+	else 
+		{
+		Error(aErrorCode);
+		}
+	return KErrNone;
+	}
+
+#ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
+void CRtpBaseFlow::SetLocalNameComplete()
+{
+  __ASSERT_DEBUG(iSessionControlNotify,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoControlProvider));
+  DoUpdateLocalAddress(iLocalAddress);
+  iSessionControlNotify->SetLocalNameComplete();
+ }
+#endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDIN
+