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() |