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