--- /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);
+ }
+ }
+