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