datacommsserver/esockserver/ssock/ss_connstates.cpp
branchRCL_3
changeset 14 4ccf8e394726
parent 12 8b5d60ce1e94
child 15 51722b10598b
equal deleted inserted replaced
13:0b0e9fce0b58 14:4ccf8e394726
   623         }
   623         }
   624     iContext.iMessage.ClearMessageId();
   624     iContext.iMessage.ClearMessageId();
   625     return EFalse;
   625     return EFalse;
   626 	}
   626 	}
   627 
   627 
       
   628 
       
   629 
       
   630 //----------------------------------------------------
       
   631 //Handling Progress/TStateChange
       
   632 DEFINE_SMELEMENT(ConnStates::TAwaitingStateChange, NetStateMachine::MState, ConnStates::TContext)
       
   633 TBool ConnStates::TAwaitingStateChange::Accept()
       
   634     {
       
   635     TCFMessage::TStateChange* progressMsg = message_cast<TCFMessage::TStateChange>(&iContext.iMessage);
       
   636     if (progressMsg)
       
   637         {
       
   638         TStateChange& progress = progressMsg->iStateChange;
       
   639         
       
   640         if (iContext.iSender != iContext.Node().Id())
       
   641             {
       
   642             //CConnection trusts that locally generated progresses are to be trusted,
       
   643             //but some of the legacy progresses coming from the stack need some filtering.
       
   644             //Here's the filtering.
       
   645         
       
   646             // Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen)
       
   647             // the log only sees the translated version, this goes into the queue, so it alright I suppose.
       
   648             if (progress.iStage == KDataTransferUnblocked )
       
   649                 {
       
   650                 progress.iStage = KConnectionUp;    // KLinkLayerOpen
       
   651                 }
       
   652             if (progress.iError == KErrForceDisconnected)
       
   653                 {
       
   654                 progress.iError = KErrDisconnected;
       
   655                 }
       
   656             
       
   657             if (progress.iStage == KConnectionUninitialised)
       
   658                 {
       
   659                 //KConnectionUninitialised has been deprecated in the stack and it will be ignored
       
   660                 //when reported by it. It is still valid towards the application. Here it is being reported by the stack.
       
   661                 //The original KConnectionUninitialised denoted CAgentReference destruction and as such speculated too
       
   662                 //much about the sturcture of the stack (notably: there isn't necesserily an agent anymore.
       
   663                 //As defined KConnectionUninitialised would need to be reported after TCFControlClient::TGoneDown or TCFServiceProvider::TStopped,
       
   664                 //except the stack decomposes after TCFControlClient::TGoneDown or TCFServiceProvider::TStopped and the progress path along with
       
   665                 //it. It is therefore impossible for the stack to generate KConnectionUninitialised after
       
   666                 //TCFControlClient::TGoneDown or TCFServiceProvider::TStopped. CConnection takes over and will generate KConnectionUninitialised
       
   667                 //when detatching from the service providers (see ConnStates::TGenerateConnectionUninitialisedProgress)
       
   668                 LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tProgressNotification(TInt aStage %d, TInt aError %d) - deprecated progress, ignoring"),
       
   669                         &(iContext.Node()), progress.iStage, progress.iError) );
       
   670                 progressMsg->ClearMessageId();
       
   671                 return EFalse;
       
   672                 }   
       
   673             }
       
   674         LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tProgressNotification(TInt aStage %d, TInt aError %d)"),
       
   675             &(iContext.Node()), progress.iStage, progress.iError) );
       
   676         
       
   677         CConnection& cc = iContext.Node();
       
   678         if (cc.iLastProgress == progress)
       
   679             {
       
   680             progressMsg->ClearMessageId();            
       
   681             return EFalse; //ignore this duplicate
       
   682             }
       
   683         cc.iLastProgress = progress;
       
   684 
       
   685         if (progress.iError != KErrNone)
       
   686             {
       
   687             cc.iLastProgressError = progress; //Save last progress in error for use by LastProgressErrorL()
       
   688             }
       
   689         return ETrue;
       
   690         }
       
   691     return EFalse;
       
   692     }
       
   693 
       
   694 //Progress & Progress Request
       
   695 DEFINE_SMELEMENT(ConnStates::TEnqueueStateChange, NetStateMachine::MStateTransition, ConnStates::TContext)
       
   696 void ConnStates::TEnqueueStateChange::DoL()
       
   697     {
       
   698     TStateChange& progress = message_cast<TCFMessage::TStateChange>(iContext.iMessage).iStateChange;
       
   699     //Diagnostic assertion.
       
   700     
       
   701     //If ECFActivityConnectionStateChangeRequest is running, it has not been
       
   702     //presented with the TStateChange message (channel activity id != 0?) which is a serious mistake.
       
   703     __ASSERT_DEBUG(iContext.Node().CountActivities(ECFActivityConnectionStateChangeRequest)==0, User::Panic(KSpecAssert_ESockSSockscnsts, 9));
       
   704 
       
   705     CConnection& cc = iContext.Node();
       
   706 #ifdef ESOCK_LOGGING_ACTIVE
       
   707     // Check to see if the progress queue is full causing older progress to be discarded.
       
   708     // This has the potential to cause problems if a critical progress item is lost.
       
   709     // Normally the queue is large enough such that this doesn't happen but this log entry
       
   710     // serves as a warning if it ever does.
       
   711     if( cc.iProgressQueue.IsFull() )
       
   712         {
       
   713         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); )
       
   714         }
       
   715 #endif
       
   716     
       
   717     //Add the progress to queue
       
   718     cc.iProgressQueue.Enque(progress);
       
   719     }
       
   720 
       
   721 
       
   722 DEFINE_SMELEMENT(ConnStates::TProcessProgressRequest, NetStateMachine::MStateTransition, ConnStates::TContext)
       
   723 void ConnStates::TProcessProgressRequest::DoL()
       
   724     {
       
   725     __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
       
   726     CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
       
   727     TUint selectedProgressStage = ac.Int1();
       
   728     TStateChange progress;
       
   729     TBool found = EFalse;
       
   730 
       
   731     __ASSERT_DEBUG((subsessmessage_cast<ECNProgressNotification>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
       
   732     
       
   733     //Process the queue looking for the progress of interest
       
   734     found = iContext.Node().iProgressQueue.Deque(progress);
       
   735     if (found && selectedProgressStage != KConnProgressDefault)
       
   736         {
       
   737         // For a selected progress request, dequeue entries until we find one which
       
   738         // matches the criteria.  If we dequeue all entries, fall through without
       
   739         // completing the message.  It it not considered useful to retain un-matching
       
   740         // entries on the queue if a selected progress request is pending.
       
   741         while (found)
       
   742             {
       
   743             if (progress.iStage == selectedProgressStage || progress.iError != KErrNone)
       
   744                 {
       
   745                 break;
       
   746                 }
       
   747             found = iContext.Node().iProgressQueue.Deque(progress);
       
   748             }
       
   749         }
       
   750 
       
   751     if (found)
       
   752         {
       
   753         //We have found a progress of interest, finish
       
   754         TPckg<TStateChange> progressPkg(progress);
       
   755         ac.WriteL(0,progressPkg);
       
   756         ac.SetIdle(); //We are done
       
   757         }
       
   758     }
       
   759 
       
   760 DEFINE_SMELEMENT(ConnStates::TProcessStateChange, NetStateMachine::MStateTransition, ConnStates::TContext)
       
   761 void ConnStates::TProcessStateChange::DoL()
       
   762     {
       
   763     __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
       
   764     CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
       
   765     TUint selectedProgressStage = ac.Int1();
       
   766 
       
   767     //Are we here as a result of receiving TStateChange (rather than ECNProgressNotification)?
       
   768     TCFMessage::TStateChange& progress = message_cast<TCFMessage::TStateChange>(iContext.iMessage);
       
   769 
       
   770     if (selectedProgressStage == KConnProgressDefault || 
       
   771         selectedProgressStage == progress.iStateChange.iStage || 
       
   772         KErrNone != progress.iStateChange.iError)
       
   773         {
       
   774         //We have found a progress of interest, finish
       
   775         TPckg<TStateChange> progressPkg(progress.iStateChange);
       
   776         ac.WriteL(0,progressPkg);
       
   777         ac.SetIdle(); //We are done
       
   778         }
       
   779     }
       
   780 
       
   781 
   628 DEFINE_SMELEMENT(ConnStates::TGenerateConnectionUpProgress, NetStateMachine::MStateTransition, ConnStates::TContext)
   782 DEFINE_SMELEMENT(ConnStates::TGenerateConnectionUpProgress, NetStateMachine::MStateTransition, ConnStates::TContext)
   629 void ConnStates::TGenerateConnectionUpProgress::DoL()
   783 void ConnStates::TGenerateConnectionUpProgress::DoL()
   630 	{
   784 	{
   631 	TCFMessage::TStateChange msg(TStateChange(KConnectionUp, KErrNone));
   785 	TCFMessage::TStateChange msg(TStateChange(KConnectionUp, KErrNone));
   632 	RNodeInterface::OpenPostMessageClose(iContext.Node().Id(), iContext.Node().Id(), msg);
   786 	RNodeInterface::OpenPostMessageClose(iContext.Node().Id(), iContext.Node().Id(), msg);
   655 		CConnection& cc = iContext.Node();
   809 		CConnection& cc = iContext.Node();
   656 		RNodeInterface::OpenPostMessageClose(cc.Id(), cc.Id(), msg);
   810 		RNodeInterface::OpenPostMessageClose(cc.Id(), cc.Id(), msg);
   657 		}
   811 		}
   658 	}
   812 	}
   659 
   813 
   660 //
   814 DEFINE_SMELEMENT(ConnStates::TGenerateConnectionUninitialisedProgress, NetStateMachine::MStateTransition, ConnStates::TContext)
   661 //Progress & Progress Request
   815 void ConnStates::TGenerateConnectionUninitialisedProgress::DoL()
   662 DEFINE_SMELEMENT(ConnStates::TProcessStateChange, NetStateMachine::MStateTransition, ConnStates::TContext)
   816     {
   663 void ConnStates::TProcessStateChange::DoL()
   817     if (iContext.Node().CountActivities(ECFActivityDestroy) == 0)
   664 	{
   818         {//TGenerateConnectionUninitialisedProgress is called when the stack goes away 
   665 	TStateChange& progress = message_cast<TCFMessage::TStateChange>(iContext.iMessage).iStateChange;
   819          //below the CConnection's feet and it sometimes goes away because CConnection is
   666 
   820          //being ECNClosed and therefore sitting on an electric chair. It is risky, but
   667 	//Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen)
   821          //above all uselsess to send the progress when when app clearly doesn't want
   668 	// the log only sees the translated version, this goes into the queue, so it alright I suppose.
   822          //to see it.
   669 	if (progress.iStage == KDataTransferUnblocked )
   823         TCFMessage::TStateChange msg(TStateChange(KConnectionUninitialised, KErrNone));
   670 		{
   824         RNodeInterface::OpenPostMessageClose(iContext.Node().Id(), iContext.Node().Id(), msg);
   671 		progress.iStage = KConnectionUp;	// KLinkLayerOpen
   825         }
   672 		}
   826     }
   673 	if (progress.iError == KErrForceDisconnected)
       
   674 		{
       
   675 		progress.iError = KErrDisconnected;
       
   676 		}
       
   677 
       
   678 	LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tProgressNotification(TInt aStage %d, TInt aError %d)"),
       
   679 		&(iContext.Node()), progress.iStage, progress.iError) );
       
   680 
       
   681 	//Diagnostic assertion.
       
   682 	//If ECFActivityConnectionStateChangeRequest is running, it has not been
       
   683 	//presented with the TStateChange message (channel activity id != 0?) which is a serious mistake.
       
   684 	__ASSERT_DEBUG(iContext.Node().CountActivities(ECFActivityConnectionStateChangeRequest)==0, User::Panic(KSpecAssert_ESockSSockscnsts, 9));
       
   685 
       
   686 	CConnection& cc = iContext.Node();
       
   687 	if (cc.iLastProgress == progress)
       
   688 		{
       
   689 		return; //ignore this duplicate
       
   690 		}
       
   691 	cc.iLastProgress = progress;
       
   692 
       
   693 	if (progress.iError != KErrNone)
       
   694 		{
       
   695         cc.iLastProgressError = progress; //Save last progress in error for use by LastProgressErrorL()
       
   696     	}
       
   697 
       
   698 	#ifdef ESOCK_LOGGING_ACTIVE
       
   699 		// Check to see if the progress queue is full causing older progress to be discarded.
       
   700 		// This has the potential to cause problems if a critical progress item is lost.
       
   701 		// Normally the queue is large enough such that this doesn't happen but this log entry
       
   702 		// serves as a warning if it ever does.
       
   703 		if( cc.iProgressQueue.IsFull() )
       
   704 			{
       
   705 			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); )
       
   706 			}
       
   707 	#endif
       
   708 
       
   709 	//Add the progress to queue
       
   710 	cc.iProgressQueue.Enque(progress);
       
   711 	}
       
   712 
       
   713 DEFINE_SMELEMENT(ConnStates::TProcessProgressRequest, NetStateMachine::MStateTransition, ConnStates::TContext)
       
   714 void ConnStates::TProcessProgressRequest::DoL()
       
   715 	{
       
   716 	__ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
       
   717 	CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
       
   718 	TUint selectedProgressStage = ac.Int1();
       
   719 
       
   720 	TStateChange progress;
       
   721 	TBool found = EFalse;
       
   722 
       
   723 	//Are we here as a result of receiving TStateChange (rather than ECNProgressNotification)?
       
   724 	TCFMessage::TStateChange* msg = message_cast<TCFMessage::TStateChange>(&iContext.iMessage);
       
   725 	if (msg)
       
   726 		{ //Yes, we have been triggered by a TStateChange message
       
   727 		//Check if this is the progress we are waiting for, otherwise dump the progress
       
   728 		//Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen)
       
   729 		if (msg->iStateChange.iStage == KDataTransferUnblocked )
       
   730 			{
       
   731 			msg->iStateChange.iStage = KConnectionUp;	// KLinkLayerOpen
       
   732 			}
       
   733 		//TODO: Verify if this (connection) is the right place to translate the error
       
   734 		if (msg->iStateChange.iError == KErrForceDisconnected)
       
   735 			{
       
   736             msg->iStateChange.iError = KErrDisconnected;
       
   737 			}
       
   738 		if (selectedProgressStage == KConnProgressDefault
       
   739 			|| selectedProgressStage == msg->iStateChange.iStage
       
   740 				|| KErrNone != msg->iStateChange.iError)
       
   741 			{
       
   742 			progress = msg->iStateChange;
       
   743 			found = ETrue;
       
   744 			}
       
   745 		}
       
   746 	else
       
   747 		{ //No, we must have been triggered by a ECNProgressNotification message
       
   748 		__ASSERT_DEBUG((subsessmessage_cast<ECNProgressNotification>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
       
   749 
       
   750 		//Process the queue looking for the progress of interest
       
   751 		found = iContext.Node().iProgressQueue.Deque(progress);
       
   752 		if (found && selectedProgressStage != KConnProgressDefault)
       
   753 			{
       
   754 			// For a selected progress request, dequeue entries until we find one which
       
   755 			// matches the criteria.  If we dequeue all entries, fall through without
       
   756 			// completing the message.  It it not considered useful to retain un-matching
       
   757 			// entries on the queue if a selected progress request is pending.
       
   758 			while (found)
       
   759 				{
       
   760 				if (progress.iStage == selectedProgressStage || progress.iError != KErrNone)
       
   761 					{
       
   762 					break;
       
   763 					}
       
   764 				found = iContext.Node().iProgressQueue.Deque(progress);
       
   765 				}
       
   766 			}
       
   767 		}
       
   768 
       
   769 	if (found)
       
   770 		{
       
   771 		//We have found a progress of interest, finish
       
   772 		TPckg<TStateChange> progressPkg(progress);
       
   773 		ac.WriteL(0,progressPkg);
       
   774 		ac.SetIdle(); //We are done
       
   775 		}
       
   776 	}
       
   777 
       
   778 
   827 
   779 //
   828 //
   780 //Legacy enumeration
   829 //Legacy enumeration
   781 DEFINE_SMELEMENT(ConnStates::TAwaitingEnumResponse, NetStateMachine::MState, ConnStates::TContext)
   830 DEFINE_SMELEMENT(ConnStates::TAwaitingEnumResponse, NetStateMachine::MState, ConnStates::TContext)
   782 TBool ConnStates::TAwaitingEnumResponse::Accept()
   831 TBool ConnStates::TAwaitingEnumResponse::Accept()
  1600 DEFINE_SMELEMENT(ConnectionCleanupActivities::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, TContext)
  1649 DEFINE_SMELEMENT(ConnectionCleanupActivities::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, TContext)
  1601 TInt ConnectionCleanupActivities::TNoTagOrNoTagBackwards::TransitionTag()
  1650 TInt ConnectionCleanupActivities::TNoTagOrNoTagBackwards::TransitionTag()
  1602     {
  1651     {
  1603 	if ( iContext.iMessage.IsMessage<TEPeer::TLeaveComplete>() )
  1652 	if ( iContext.iMessage.IsMessage<TEPeer::TLeaveComplete>() )
  1604 		{
  1653 		{
  1605 //		__ASSERT_DEBUG(iContext.Node().GetClientIter(RNodeInterface::ECtrl|RNodeInterface::EData)[0] == NULL,
       
  1606 //		User::Panic(KCorePRPanic, KPanicClientsStillPresent));
       
  1607 		if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TCFClientType(TCFClientType::EServProvider)) == NULL)
  1654 		if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TCFClientType(TCFClientType::EServProvider)) == NULL)
  1608 			{ // This was the last service provider
  1655 			{ // This was the last service provider
  1609 			return NetStateMachine::EForward | MeshMachine::KNoTag;
  1656 			return NetStateMachine::EForward | MeshMachine::KNoTag;
  1610 			}
  1657 			}
  1611 		// There are more service providers to expect 'leave complete' from so
  1658 		// There are more service providers to expect 'leave complete' from so