datacommsserver/esockserver/ssock/ss_connstates.cpp
branchRCL_3
changeset 14 4ccf8e394726
parent 12 8b5d60ce1e94
child 15 51722b10598b
--- a/datacommsserver/esockserver/ssock/ss_connstates.cpp	Wed Mar 31 23:27:09 2010 +0300
+++ b/datacommsserver/esockserver/ssock/ss_connstates.cpp	Wed Apr 14 17:14:05 2010 +0300
@@ -625,6 +625,160 @@
     return EFalse;
 	}
 
+
+
+//----------------------------------------------------
+//Handling Progress/TStateChange
+DEFINE_SMELEMENT(ConnStates::TAwaitingStateChange, NetStateMachine::MState, ConnStates::TContext)
+TBool ConnStates::TAwaitingStateChange::Accept()
+    {
+    TCFMessage::TStateChange* progressMsg = message_cast<TCFMessage::TStateChange>(&iContext.iMessage);
+    if (progressMsg)
+        {
+        TStateChange& progress = progressMsg->iStateChange;
+        
+        if (iContext.iSender != iContext.Node().Id())
+            {
+            //CConnection trusts that locally generated progresses are to be trusted,
+            //but some of the legacy progresses coming from the stack need some filtering.
+            //Here's the filtering.
+        
+            // Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen)
+            // the log only sees the translated version, this goes into the queue, so it alright I suppose.
+            if (progress.iStage == KDataTransferUnblocked )
+                {
+                progress.iStage = KConnectionUp;    // KLinkLayerOpen
+                }
+            if (progress.iError == KErrForceDisconnected)
+                {
+                progress.iError = KErrDisconnected;
+                }
+            
+            if (progress.iStage == KConnectionUninitialised)
+                {
+                //KConnectionUninitialised has been deprecated in the stack and it will be ignored
+                //when reported by it. It is still valid towards the application. Here it is being reported by the stack.
+                //The original KConnectionUninitialised denoted CAgentReference destruction and as such speculated too
+                //much about the sturcture of the stack (notably: there isn't necesserily an agent anymore.
+                //As defined KConnectionUninitialised would need to be reported after TCFControlClient::TGoneDown or TCFServiceProvider::TStopped,
+                //except the stack decomposes after TCFControlClient::TGoneDown or TCFServiceProvider::TStopped and the progress path along with
+                //it. It is therefore impossible for the stack to generate KConnectionUninitialised after
+                //TCFControlClient::TGoneDown or TCFServiceProvider::TStopped. CConnection takes over and will generate KConnectionUninitialised
+                //when detatching from the service providers (see ConnStates::TGenerateConnectionUninitialisedProgress)
+                LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tProgressNotification(TInt aStage %d, TInt aError %d) - deprecated progress, ignoring"),
+                        &(iContext.Node()), progress.iStage, progress.iError) );
+                progressMsg->ClearMessageId();
+                return EFalse;
+                }   
+            }
+        LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tProgressNotification(TInt aStage %d, TInt aError %d)"),
+            &(iContext.Node()), progress.iStage, progress.iError) );
+        
+        CConnection& cc = iContext.Node();
+        if (cc.iLastProgress == progress)
+            {
+            progressMsg->ClearMessageId();            
+            return EFalse; //ignore this duplicate
+            }
+        cc.iLastProgress = progress;
+
+        if (progress.iError != KErrNone)
+            {
+            cc.iLastProgressError = progress; //Save last progress in error for use by LastProgressErrorL()
+            }
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+//Progress & Progress Request
+DEFINE_SMELEMENT(ConnStates::TEnqueueStateChange, NetStateMachine::MStateTransition, ConnStates::TContext)
+void ConnStates::TEnqueueStateChange::DoL()
+    {
+    TStateChange& progress = message_cast<TCFMessage::TStateChange>(iContext.iMessage).iStateChange;
+    //Diagnostic assertion.
+    
+    //If ECFActivityConnectionStateChangeRequest is running, it has not been
+    //presented with the TStateChange message (channel activity id != 0?) which is a serious mistake.
+    __ASSERT_DEBUG(iContext.Node().CountActivities(ECFActivityConnectionStateChangeRequest)==0, User::Panic(KSpecAssert_ESockSSockscnsts, 9));
+
+    CConnection& cc = iContext.Node();
+#ifdef ESOCK_LOGGING_ACTIVE
+    // Check to see if the progress queue is full causing older progress to be discarded.
+    // This has the potential to cause problems if a critical progress item is lost.
+    // Normally the queue is large enough such that this doesn't happen but this log entry
+    // serves as a warning if it ever does.
+    if( cc.iProgressQueue.IsFull() )
+        {
+        LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tThe maximum progress queue size of %d has been exceeded - discarding old progress to make space for new item"), this, KMaxProgressQueueLength); )
+        }
+#endif
+    
+    //Add the progress to queue
+    cc.iProgressQueue.Enque(progress);
+    }
+
+
+DEFINE_SMELEMENT(ConnStates::TProcessProgressRequest, NetStateMachine::MStateTransition, ConnStates::TContext)
+void ConnStates::TProcessProgressRequest::DoL()
+    {
+    __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
+    CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
+    TUint selectedProgressStage = ac.Int1();
+    TStateChange progress;
+    TBool found = EFalse;
+
+    __ASSERT_DEBUG((subsessmessage_cast<ECNProgressNotification>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
+    
+    //Process the queue looking for the progress of interest
+    found = iContext.Node().iProgressQueue.Deque(progress);
+    if (found && selectedProgressStage != KConnProgressDefault)
+        {
+        // For a selected progress request, dequeue entries until we find one which
+        // matches the criteria.  If we dequeue all entries, fall through without
+        // completing the message.  It it not considered useful to retain un-matching
+        // entries on the queue if a selected progress request is pending.
+        while (found)
+            {
+            if (progress.iStage == selectedProgressStage || progress.iError != KErrNone)
+                {
+                break;
+                }
+            found = iContext.Node().iProgressQueue.Deque(progress);
+            }
+        }
+
+    if (found)
+        {
+        //We have found a progress of interest, finish
+        TPckg<TStateChange> progressPkg(progress);
+        ac.WriteL(0,progressPkg);
+        ac.SetIdle(); //We are done
+        }
+    }
+
+DEFINE_SMELEMENT(ConnStates::TProcessStateChange, NetStateMachine::MStateTransition, ConnStates::TContext)
+void ConnStates::TProcessStateChange::DoL()
+    {
+    __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
+    CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
+    TUint selectedProgressStage = ac.Int1();
+
+    //Are we here as a result of receiving TStateChange (rather than ECNProgressNotification)?
+    TCFMessage::TStateChange& progress = message_cast<TCFMessage::TStateChange>(iContext.iMessage);
+
+    if (selectedProgressStage == KConnProgressDefault || 
+        selectedProgressStage == progress.iStateChange.iStage || 
+        KErrNone != progress.iStateChange.iError)
+        {
+        //We have found a progress of interest, finish
+        TPckg<TStateChange> progressPkg(progress.iStateChange);
+        ac.WriteL(0,progressPkg);
+        ac.SetIdle(); //We are done
+        }
+    }
+
+
 DEFINE_SMELEMENT(ConnStates::TGenerateConnectionUpProgress, NetStateMachine::MStateTransition, ConnStates::TContext)
 void ConnStates::TGenerateConnectionUpProgress::DoL()
 	{
@@ -657,124 +811,19 @@
 		}
 	}
 
-//
-//Progress & Progress Request
-DEFINE_SMELEMENT(ConnStates::TProcessStateChange, NetStateMachine::MStateTransition, ConnStates::TContext)
-void ConnStates::TProcessStateChange::DoL()
-	{
-	TStateChange& progress = message_cast<TCFMessage::TStateChange>(iContext.iMessage).iStateChange;
-
-	//Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen)
-	// the log only sees the translated version, this goes into the queue, so it alright I suppose.
-	if (progress.iStage == KDataTransferUnblocked )
-		{
-		progress.iStage = KConnectionUp;	// KLinkLayerOpen
-		}
-	if (progress.iError == KErrForceDisconnected)
-		{
-		progress.iError = KErrDisconnected;
-		}
-
-	LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tProgressNotification(TInt aStage %d, TInt aError %d)"),
-		&(iContext.Node()), progress.iStage, progress.iError) );
-
-	//Diagnostic assertion.
-	//If ECFActivityConnectionStateChangeRequest is running, it has not been
-	//presented with the TStateChange message (channel activity id != 0?) which is a serious mistake.
-	__ASSERT_DEBUG(iContext.Node().CountActivities(ECFActivityConnectionStateChangeRequest)==0, User::Panic(KSpecAssert_ESockSSockscnsts, 9));
-
-	CConnection& cc = iContext.Node();
-	if (cc.iLastProgress == progress)
-		{
-		return; //ignore this duplicate
-		}
-	cc.iLastProgress = progress;
-
-	if (progress.iError != KErrNone)
-		{
-        cc.iLastProgressError = progress; //Save last progress in error for use by LastProgressErrorL()
-    	}
-
-	#ifdef ESOCK_LOGGING_ACTIVE
-		// Check to see if the progress queue is full causing older progress to be discarded.
-		// This has the potential to cause problems if a critical progress item is lost.
-		// Normally the queue is large enough such that this doesn't happen but this log entry
-		// serves as a warning if it ever does.
-		if( cc.iProgressQueue.IsFull() )
-			{
-			LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tThe maximum progress queue size of %d has been exceeded - discarding old progress to make space for new item"), this, KMaxProgressQueueLength); )
-			}
-	#endif
-
-	//Add the progress to queue
-	cc.iProgressQueue.Enque(progress);
-	}
-
-DEFINE_SMELEMENT(ConnStates::TProcessProgressRequest, NetStateMachine::MStateTransition, ConnStates::TContext)
-void ConnStates::TProcessProgressRequest::DoL()
-	{
-	__ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
-	CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
-	TUint selectedProgressStage = ac.Int1();
-
-	TStateChange progress;
-	TBool found = EFalse;
-
-	//Are we here as a result of receiving TStateChange (rather than ECNProgressNotification)?
-	TCFMessage::TStateChange* msg = message_cast<TCFMessage::TStateChange>(&iContext.iMessage);
-	if (msg)
-		{ //Yes, we have been triggered by a TStateChange message
-		//Check if this is the progress we are waiting for, otherwise dump the progress
-		//Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen)
-		if (msg->iStateChange.iStage == KDataTransferUnblocked )
-			{
-			msg->iStateChange.iStage = KConnectionUp;	// KLinkLayerOpen
-			}
-		//TODO: Verify if this (connection) is the right place to translate the error
-		if (msg->iStateChange.iError == KErrForceDisconnected)
-			{
-            msg->iStateChange.iError = KErrDisconnected;
-			}
-		if (selectedProgressStage == KConnProgressDefault
-			|| selectedProgressStage == msg->iStateChange.iStage
-				|| KErrNone != msg->iStateChange.iError)
-			{
-			progress = msg->iStateChange;
-			found = ETrue;
-			}
-		}
-	else
-		{ //No, we must have been triggered by a ECNProgressNotification message
-		__ASSERT_DEBUG((subsessmessage_cast<ECNProgressNotification>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
-
-		//Process the queue looking for the progress of interest
-		found = iContext.Node().iProgressQueue.Deque(progress);
-		if (found && selectedProgressStage != KConnProgressDefault)
-			{
-			// For a selected progress request, dequeue entries until we find one which
-			// matches the criteria.  If we dequeue all entries, fall through without
-			// completing the message.  It it not considered useful to retain un-matching
-			// entries on the queue if a selected progress request is pending.
-			while (found)
-				{
-				if (progress.iStage == selectedProgressStage || progress.iError != KErrNone)
-					{
-					break;
-					}
-				found = iContext.Node().iProgressQueue.Deque(progress);
-				}
-			}
-		}
-
-	if (found)
-		{
-		//We have found a progress of interest, finish
-		TPckg<TStateChange> progressPkg(progress);
-		ac.WriteL(0,progressPkg);
-		ac.SetIdle(); //We are done
-		}
-	}
-
+DEFINE_SMELEMENT(ConnStates::TGenerateConnectionUninitialisedProgress, NetStateMachine::MStateTransition, ConnStates::TContext)
+void ConnStates::TGenerateConnectionUninitialisedProgress::DoL()
+    {
+    if (iContext.Node().CountActivities(ECFActivityDestroy) == 0)
+        {//TGenerateConnectionUninitialisedProgress is called when the stack goes away 
+         //below the CConnection's feet and it sometimes goes away because CConnection is
+         //being ECNClosed and therefore sitting on an electric chair. It is risky, but
+         //above all uselsess to send the progress when when app clearly doesn't want
+         //to see it.
+        TCFMessage::TStateChange msg(TStateChange(KConnectionUninitialised, KErrNone));
+        RNodeInterface::OpenPostMessageClose(iContext.Node().Id(), iContext.Node().Id(), msg);
+        }
+    }
 
 //
 //Legacy enumeration
@@ -1602,8 +1651,6 @@
     {
 	if ( iContext.iMessage.IsMessage<TEPeer::TLeaveComplete>() )
 		{
-//		__ASSERT_DEBUG(iContext.Node().GetClientIter(RNodeInterface::ECtrl|RNodeInterface::EData)[0] == NULL,
-//		User::Panic(KCorePRPanic, KPanicClientsStillPresent));
 		if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TCFClientType(TCFClientType::EServProvider)) == NULL)
 			{ // This was the last service provider
 			return NetStateMachine::EForward | MeshMachine::KNoTag;