linklayercontrol/networkinterfacemgr/agentprcore/src/agentscpr.cpp
changeset 0 af10295192d8
child 9 343eee2d4450
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linklayercontrol/networkinterfacemgr/agentprcore/src/agentscpr.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,493 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalTechnology
+ @prototype
+*/
+
+#include <comms-infras/ss_log.h>
+#include <elements/sm_core.h>
+#include <comms-infras/linkmessages.h>
+#include <elements/nm_messages_base.h>
+
+#include <comms-infras/ss_nodemessages_dataclient.h>
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <comms-infras/nifagt_internal.h>
+#endif
+
+#include "agentscpr.h"
+#include "agentscprstates.h"
+#include "agentscpractivities.h"
+#include "CAgentAdapter.h"
+#include "agentmessages.h"
+
+#include <comms-infras/ss_msgintercept.h>
+
+
+#ifdef _DEBUG
+// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
+// (if it could happen through user error then you should give it an explicit, documented, category + code)
+_LIT(KSpecAssert_NifManAgtPrCgnts, "NifManAgtPrCgnts");
+#endif
+
+#if defined __CFLOG_ACTIVE || defined SYMBIAN_TRACE_ENABLE
+#define KAgentSCprTag KESockSubConnectionTag
+_LIT8(KAgentSCprSubTag, "agentscpr");
+#endif
+
+
+using namespace Messages;
+using namespace MeshMachine;
+using namespace ESock;
+using namespace NetStateMachine;
+
+//We reserve space for two preallocated activities that may start concurrently on the SCPR
+//node: destroy and data client stop.
+static const TUint KDefaultMaxPreallocatedActivityCount = 2;
+static const TUint KMaxPreallocatedActivitySize = sizeof(MeshMachine::CNodeRetryParallelActivity) + sizeof(MeshMachine::APreallocatedOriginators<4>);
+static const TUint KAgentSCPRPreallocatedActivityBufferSize = KDefaultMaxPreallocatedActivityCount * KMaxPreallocatedActivitySize;
+
+/**
+Creates an Agent SubConnection Provider
+@param aFactory The parent factory which has created the SCPr
+@return Pointer to the newly created SCPr
+*/
+EXPORT_C CAgentSubConnectionProvider* CAgentSubConnectionProvider::NewL(ESock::CSubConnectionProviderFactoryBase& aFactory)
+	{
+	CAgentSubConnectionProvider* self = new (ELeave) CAgentSubConnectionProvider(aFactory, AgentSCprActivities::agentSCprActivities::Self());
+	CleanupStack::PushL(self);
+	self->ConstructL(KAgentSCPRPreallocatedActivityBufferSize);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+
+/**
+Constructor for the Agent SubConnection Provider
+@param aFactory The parent factory which created this SCPr
+*/
+EXPORT_C CAgentSubConnectionProvider::CAgentSubConnectionProvider(CSubConnectionProviderFactoryBase& aFactory,
+    const MeshMachine::TNodeActivityMap& aActivityMap)
+   : CCoreSubConnectionProvider(aFactory, aActivityMap)
+	{
+	LOG_NODE_CREATE(KAgentSCprTag, CAgentSubConnectionProvider);
+	}
+
+
+/**
+D'tor
+*/
+EXPORT_C CAgentSubConnectionProvider::~CAgentSubConnectionProvider()
+    {
+	CleanupProvisioningInfo();
+    LOG_NODE_DESTROY(KAgentSCprTag, CAgentSubConnectionProvider);
+	}
+
+
+EXPORT_C void CAgentSubConnectionProvider::CleanupProvisioningInfo()
+    {
+    if (iAuthenticateInProgress && AgentProvisionInfo()->AgentAdapter())
+	   {
+	   iAuthenticateInProgress = EFalse;
+	   AgentProvisionInfo()->AgentAdapter()->CancelAuthenticate();
+	   }
+
+	CAgentAdapter* agentAdapter(AgentProvisionInfo()->AgentAdapter());
+	const_cast<CAgentProvisionInfo*>(AgentProvisionInfo())->SetAgentAdapter(NULL);
+	delete agentAdapter;
+
+	// Remove ourselves from the notification handler, or delete it entirely if we own it
+	CAgentNotificationHandler* handler = AgentProvisionInfo()->AgentNotificationHandler();
+	if (handler)
+	    {
+	    if (iScprOwnedNotificationHandler)
+	        {
+	        const_cast<CAgentProvisionInfo*>(AgentProvisionInfo())->SetAgentNotificationHandler(NULL);
+	        delete handler;
+	        }
+        else
+            {
+            handler->Initialise(NULL);
+            }
+	    }
+    }
+
+/**
+Mesh machine message entry point
+*/
+EXPORT_C void CAgentSubConnectionProvider::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+	{
+	ESOCK_DEBUG_MESSAGE_INTERCEPT(aSender, aMessage, aRecipient);
+
+	TNodeContext<CAgentSubConnectionProvider> ctx(*this, aMessage, aSender, aRecipient);
+	CCoreSubConnectionProvider::Received(ctx);
+	User::LeaveIfError(ctx.iReturn);
+	}
+
+
+TInt CAgentSubConnectionProvider::PostMessageToFlow(const TRuntimeCtxId& aSender, const TSignatureBase& aMessage)
+   {
+   // There can only ever be one flow for an AgentSCpr
+   RNodeInterface* dataClient = this->GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData));
+   if (!dataClient)
+      {
+      return KErrNotFound;
+      }
+   dataClient->PostMessage(aSender, aMessage);
+   return KErrNone;
+   }
+
+
+/**
+Retrieves the Agent Provider specific provisioning information as given by the MCPr
+transition.
+
+@internalTechnology
+*/
+EXPORT_C const CAgentProvisionInfo* CAgentSubConnectionProvider::AgentProvisionInfo() const
+    {
+    const CAgentProvisionInfo* agentProvisionInfo = static_cast<const CAgentProvisionInfo*>(AccessPointConfig().FindExtension(CAgentProvisionInfo::TypeId()));
+	__ASSERT_DEBUG(agentProvisionInfo, User::Panic(KSpecAssert_NifManAgtPrCgnts, 1));
+    return agentProvisionInfo;
+    }
+
+
+/**
+Starts the agent connection process
+*/
+EXPORT_C void CAgentSubConnectionProvider::ConnectAgent(TAgentConnectType aConnectType)
+    {
+    AgentProvisionInfo()->AgentAdapter()->ConnectAgent(aConnectType);
+    }
+
+
+/**
+Notifies an event to the AgentSCpr's Agent via the AgentAdapter
+*/
+EXPORT_C TInt CAgentSubConnectionProvider::NotificationToAgent(TFlowToAgentEventType aEvent, TAny* aInfo)
+    {
+    return AgentProvisionInfo()->AgentAdapter()->NotificationToAgent(aEvent, aInfo);
+    }
+
+
+/**
+Called from the StartAgent state transition
+*/
+void CAgentSubConnectionProvider::StartAgentL()
+    {
+    SetActivityIdForAdapter(ECFActivityStartDataClient);
+
+    if (!AgentProvisionInfo()->AgentAdapter())
+        {
+        CAgentNotificationHandler* handler = AgentProvisionInfo()->AgentNotificationHandler();
+        if (!handler)
+            {
+            // Ensure something is present to forward msgs to the flow
+            // Normally the MCPr will own the handler, we must only delete if we created it
+            handler = CAgentNotificationHandler::NewL();
+            iScprOwnedNotificationHandler = ETrue;
+            const_cast<CAgentProvisionInfo*>(AgentProvisionInfo())->SetAgentNotificationHandler(handler);
+            }
+        handler->Initialise (this);
+
+        const_cast<CAgentProvisionInfo*>(AgentProvisionInfo())->SetAgentAdapter (CAgentAdapter::NewL(*this, AgentProvisionInfo()->AgentName()));
+        }
+
+	CAgentAdapter::TAgentState agtState = AgentProvisionInfo()->AgentAdapter()->AgentState();
+
+    // Should never get a TStart whilst we are disconnecting
+    __ASSERT_DEBUG(agtState != CAgentAdapter::EDisconnecting, User::Panic(KSpecAssert_NifManAgtPrCgnts, 2));
+
+	if (agtState == CAgentAdapter::EDisconnected)
+        {
+        ConnectAgent(EAgentStartDialOut);
+        }
+    else if (agtState == CAgentAdapter::EConnected)
+        {
+        RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(ECFActivityStartDataClient, Id()), TCFServiceProvider::TStarted().CRef());
+        iActivityIdForAdapter = KActivityNull;
+        }
+    // else if AgentState() is EConnecting or EReconnecting we wait for the TStarted
+    //      from that operation
+   }
+
+/**
+Called from the StopAgent state transition
+*/
+void CAgentSubConnectionProvider::StopAgent(TInt aReason)
+    {
+    // Agent should have been started, so the agent adapter should exist
+    __ASSERT_DEBUG(AgentProvisionInfo()->AgentAdapter(), User::Panic(KSpecAssert_NifManAgtPrCgnts, 3));
+
+    if (AgentProvisionInfo()->AgentAdapter()->AgentState() == CAgentAdapter::EDisconnected)
+        {
+        RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(iActivityIdForAdapter, Id()), TCFDataClient::TStopped(KErrDisconnected).CRef());
+        iActivityIdForAdapter = KActivityNull;
+        }
+    else
+        {
+        iStopRequested = ETrue;
+        iStoppingReason = aReason;
+        AgentProvisionInfo()->AgentAdapter()->DisconnectAgent(aReason);
+        }
+    }
+
+/**
+Upcall from the agent
+*/
+void CAgentSubConnectionProvider::ServiceStarted()
+   {
+   CAgentNotificationHandler* handler = AgentProvisionInfo()->AgentNotificationHandler();
+   if (handler)
+      {
+      handler->ServiceStarted ();
+      }
+   }
+
+
+/**
+Called from the CAgentAdapter. Gets information required by flow into a TCommsBinder
+and posts it into this node's mesh machine with a TStarted message
+*/
+void CAgentSubConnectionProvider::ConnectionUpL()
+	{
+	__CFLOG_VAR((KAgentSCprTag, KAgentSCprSubTag, _L8("CAgentSubConnectionProvider::ConnectionUpL() - Agent has started")));
+
+    CAgentNotificationHandler* handler = AgentProvisionInfo()->AgentNotificationHandler();
+    if (handler)
+        {
+        handler->ConnectCompleteL();
+        }
+
+    // Send connection up message to the SCPr
+    RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(ECFActivityStartDataClient, Id()), TCFServiceProvider::TStarted().CRef());
+    iActivityIdForAdapter = KActivityNull;
+	}
+
+
+
+/**
+Called from the CAgentAdapter. Indicates that the agent is now disconnected.
+*/
+void CAgentSubConnectionProvider::ConnectionDownL()
+	{
+	// Only send ourselves a DataClientStopped message if we really want to forward
+	// it up. That translates to: have we been asked to StopConnection and are
+	// we expecting the agent to disconnect, if so then kick the mesh machine
+	// with a TStopped message
+	if (iStopRequested)
+	    {
+    	__CFLOG_VAR((KAgentSCprTag, KAgentSCprSubTag, _L8("CAgentSubConnectionProvider::ConnectionDownL() - Agent has stopped by request")));
+    	// Send connection down message to self (this is really like the TStopped message coming up from a lower layer)
+
+    	RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(iActivityIdForAdapter, Id()), TCFServiceProvider::TStopped(iStoppingReason).CRef());
+    	iActivityIdForAdapter = KActivityNull;
+    	iStopRequested = EFalse;
+	    }
+	else
+	    {
+	    // Agent has stopped and disconnected without this node telling it to
+	    // Could be an error in the agent initiating a disconnect
+    	__CFLOG_VAR((KAgentSCprTag, KAgentSCprSubTag, _L8("CAgentSubConnectionProvider::ConnectionDownL() - Agent has stopped unexpectedly")));
+	    ControlProvider()->PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(KErrDisconnected).CRef());
+	    }
+	}
+
+
+/**
+Called from the CAgentAdapter. Indicates that the agent has finished getting
+authentication data by whatever means it chooses.
+*/
+void CAgentSubConnectionProvider::AuthenticateCompleteL(TInt aStatus)
+   {
+   __ASSERT_DEBUG(iActivityIdForAdapter == ECFActivityAuthentication, User::Panic(KSpecAssert_NifManAgtPrCgnts, 4));
+
+   CCredentialsConfig* credentials = AgentProvisionInfo()->Credentials();
+   credentials->SetResult (aStatus);
+
+   if (aStatus == KErrNone)
+      {
+      credentials->SetUserName (iUsername);
+      credentials->SetPassword (iPassword);
+      }
+      else
+      {
+      credentials->SetUserName (_L(""));
+      credentials->SetPassword (_L(""));
+      }
+
+   RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(ECFActivityAuthentication, Id()), TLinkMessage::TAuthenticateResponse().CRef());
+   iAuthenticateInProgress = EFalse;
+   iActivityIdForAdapter = KActivityNull;
+   }
+
+
+/**
+Called from the CAgentAdapter. Indicates that the agent has had a response from
+the user deciding whether or not to reconnect
+*/
+void CAgentSubConnectionProvider::PromptForReconnectComplete(TInt aStatus)
+    {
+    if (aStatus == KErrNone)
+        {
+        // Response was to reconnect
+        ConnectAgent(EAgentReconnect);
+        }
+    else
+        {
+        AgentProvisionInfo()->AgentAdapter()->DisconnectAgent(aStatus);
+        }
+    }
+
+
+/**
+Posts the progress to the Control Client (SCPr above). There should only ever be
+one Control Client for this SCPr.
+*/
+void CAgentSubConnectionProvider::ProgressL(TInt aStage)
+    {
+    iLastProgress.iStage = aStage;
+    iLastProgress.iError = KErrNone;
+    RClientInterface::OpenPostMessageClose(Id(), Id(),
+    	TCFMessage::TStateChange(iLastProgress).CRef());
+    }
+
+
+
+/**
+Posts the error to the control clients (Up)
+*/
+void CAgentSubConnectionProvider::Error(const Elements::TStateChange& aProgress)
+    {
+    __ASSERT_DEBUG(aProgress.iError, User::Panic(KSpecAssert_NifManAgtPrCgnts, 5));
+
+    iLastProgress = aProgress;
+    if (iActivityIdForAdapter != KActivityNull)
+        {
+        RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(iActivityIdForAdapter, Id()),
+        	TEBase::TError(TCFDataClient::TStart::Id(), iLastProgress.iError).CRef());
+        iActivityIdForAdapter = KActivityNull;
+        }
+
+    if (CountActivities(ECFActivityStartDataClient))
+        {
+        __ASSERT_DEBUG(CountActivities(ECFActivityStartDataClient) == 1, User::Panic(KSpecAssert_NifManAgtPrCgnts, 6));
+        MeshMachine::CNodeActivityBase* startDataClientActivty = FindActivityById(ECFActivityStartDataClient);
+        startDataClientActivty->SetError(iLastProgress.iError);
+        TEBase::TCancel cancelMsg;
+		TNodeCtxId sender(startDataClientActivty->ActivityId(), Id());
+		TNodeCtxId recipient(0, Id());
+	    TNodeContext<CAgentSubConnectionProvider> ctx(*this, cancelMsg, sender, recipient);
+        startDataClientActivty->Cancel(ctx);
+        }
+    }
+
+
+void CAgentSubConnectionProvider::NetworkAdaptorEvent(TNetworkAdaptorEventType aEventType, TUint aEvent, const TDesC8& aEventData, TAny* /*aSource*/)
+    {
+	if(aEventType == EAgentOriginatedConnectionCommand)
+	// added to allow agent to generate connection control commands, such as Stop()
+		{
+		if(aEvent == EAgentConnectionCommandStop)
+			{
+			__ASSERT_DEBUG(aEventData.Length()==sizeof(TInt), User::Panic(KSpecAssert_NifManAgtPrCgnts, 7));
+			TInt errorCode = *(reinterpret_cast<const TInt*>(aEventData.Ptr()));
+			CancelStartOrSendStopToSelf(errorCode);
+			}
+		}
+	else if(aEventType == EEtelEvent)
+		{
+		if (aEvent == ECurrentNetworkChangeEvent)
+			{
+			// This is a very specific event for CDMA2000 which is essentially for backwards
+			// compatibility with old architecture.  The PSD Agent generates this event to indicate
+			// a zone change.  This event needs to be propagated to the Network Config Daemon (NetCfgExt),
+			// which is done here.  Technically, the PSD Agent should not be listening for this
+			// specific ETel event - the NetCfgExt should be listening directly for the event and handling it
+			// itself.  However, this change isn't currently the case hence this forwarding code is present.
+			// This should be removed if zone change events are (ever) moved from PSD Agent to NetCfg Daemon.
+			TLinkMessage::TAgentEventNotification msg(aEventType, aEvent);
+	        PostToClients<TDefaultClientMatchPolicy>(Id(), msg, TClientType(TCFClientType::ECtrl));
+			}
+		}
+    }
+
+void CAgentSubConnectionProvider:: CancelStartOrSendStopToSelf(TInt aError)
+/**
+Issue a TCFDataClient::TStop message to ourselves.
+
+Used to initiate the stop activity internally when requested from an Agent.
+
+@param aError error code in TCFDataClient::TStop message.
+*/
+	{
+#ifdef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT	
+	if(CountActivities(ECFActivityStartDataClient))
+		{
+		Elements::TStateChange aProgress;
+		aProgress.iError=aError;
+		Error(aProgress);
+		}
+	else
+		{
+		RClientInterface::OpenPostMessageClose(Id(), Id(), TCFDataClient::TStop(aError).CRef());
+		}
+#else
+		RClientInterface::OpenPostMessageClose(Id(), Id(), TCFDataClient::TStop(aError).CRef());
+#endif	
+	}
+
+TInt CAgentSubConnectionProvider::NotificationFromAgent(TAgentToFlowEventType aEvent, TAny* aInfo)
+    {
+    if (aEvent == EAgentToNifEventTypeDisableConnection)
+    	{
+#ifdef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT		
+		TInt errorCode = KErrCancel;
+		if (NULL != aInfo)
+			{			
+			errorCode = reinterpret_cast<const TInt>(aInfo);
+			__ASSERT_DEBUG(errorCode < KErrNone, User::Panic(KSpecAssert_NifManAgtPrCgnts, 8));
+			}
+		// Request from agent to disconnect using error code specified from agent
+		CancelStartOrSendStopToSelf(errorCode);
+#else
+		CancelStartOrSendStopToSelf(KErrCancel);
+#endif
+    	}
+    else
+    	{
+	    CAgentNotificationHandler* handler = AgentProvisionInfo()->AgentNotificationHandler();
+	    if (handler)
+	        {
+	        return handler->NotificationFromAgent(aEvent, aInfo);
+	        }
+    	}
+
+    return KErrNotSupported;
+    }
+
+
+void CAgentSubConnectionProvider::NotificationFromFlow(TFlowToAgentEventType aEvent)
+    {
+   	CAgentNotificationHandler* handler = AgentProvisionInfo()->AgentNotificationHandler();
+   	if (handler)
+       	{
+       	handler->NotificationFromFlow(aEvent);
+       	}
+    }
+