diff -r 39bb7c3571e9 -r 052078dda061 networkcontrol/ipcpr/src/ipcprfactory.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkcontrol/ipcpr/src/ipcprfactory.cpp Tue Jun 29 19:20:22 2010 +0530 @@ -0,0 +1,486 @@ +// Copyright (c) 2005-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: +// This is part of an ECOM plug-in +// +// + +#include +#include "ipcprfactory.h" // CIPNetworkProviderFactory +#include "ipcprprovider.h" +#include // KCommsNetworkLayerId +#include +#include +#include +#include // TConnPref +#include // CommsDat +#include +#include //KAfInet + +using namespace CommsDat; +using namespace ESock; + +const TInt KIPConnectionProviderImplementationUid=0x102070EF; + +/** +Data required for instantiating ECOM Plugin +*/ +const TImplementationProxy ImplementationTable[] = + { + IMPLEMENTATION_PROXY_ENTRY(KIPConnectionProviderImplementationUid, CIPNetworkProviderFactory::NewL) + }; + +/** +ECOM Implementation Factory +*/ +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) + { + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + return ImplementationTable; + } + +CIPNetworkProviderFactory* CIPNetworkProviderFactory::NewL(TAny* aParentContainer) + { + return new (ELeave) CIPNetworkProviderFactory(KIPConnectionProviderFactoryId, *(reinterpret_cast(aParentContainer))); + } + +CIPNetworkProviderFactory::CIPNetworkProviderFactory(TUint aFactoryId, CConnectionFactoryContainer& aParentContainer) + : CConnectionProviderFactoryBase(aFactoryId,aParentContainer) + { + } + +CConnectionProviderBase* CIPNetworkProviderFactory::DoCreateProviderL() + { + return CIPNetworkConnectionProvider::NewL(*this); + } + +MProviderSelector* CIPNetworkProviderFactory::DoSelectProvider( Meta::SMetaData& aPreferences, ISelectionNotify& aSelectionNotify, const RMessagePtr2* aMessage ) + { + //create self destructing object to select a provider + CIPConnectionSelector* selector = new CIPConnectionSelector(aSelectionNotify,*this); + TInt error; + if (selector == 0) + { + error = KErrNoMemory; + } + else + { + error = selector->Select(aPreferences, aMessage); + } + + if (error != KErrNone) + { + aSelectionNotify.SelectComplete(0, error); + selector = NULL; //The selector will delete itself. + } + + + return selector; + } + +MProviderSelector* CIPNetworkProviderFactory::DoSelectNextLayerProvider( Meta::SMetaData& aPreferences, ISelectionNotify& aSelectionNotify, const RMessagePtr2* /*aMessage*/ ) + {//at the moment always uses the CConnectionProviderFactoryShim::SelectProviderL + (void)aPreferences; + (void)aSelectionNotify; + return NULL; + } + +void CIPNetworkProviderFactory::DoEnumerateConnectionsL(RPointerArray& aConnectionInfoPtrArray) + { + CConnectionFactoryContainer* connectionFactories = SockManGlobals::Get()->iConnectionFactories; + ASSERT(connectionFactories); + CConnectionProviderFactoryBase* factory = connectionFactories->FindFactory(KShimConnectionProviderFactoryId); + ASSERT(factory); + factory->EnumerateConnectionsL(aConnectionInfoPtrArray); + } + + +//CIPConnectionSelector-- +TInt CIPConnectionSelector::Cancel() + { + return Cancel(KErrCancel,NULL); + } + +TInt CIPConnectionSelector::Cancel(TInt aReason, const RMessage2* aMessage) + { + CActive::Cancel(); // There may be an outstanding selection request. + + //CIPConnectionSelector will be deleted from Detach(). + //Detach will always be called as a result of Cancel() in the same call stack, + //but only after all progress notifications have been passed up towards the + //CConnection. + TInt ret = KErrNotReady; + if(iNextLayerSelector !=NULL) + { + ret = iNextLayerSelector->Cancel(aReason, aMessage); + } + + iNotify.Detach(); //"PrevLayer"::Detach() will be called only once in the same call stack. + return ret; + } + +TInt CIPConnectionSelector::Select(Meta::SMetaData& aPreferences, const RMessagePtr2* aMessage) + { + __FLOG_OPEN(KIpcprTag, KIpcprSubTag); + __FLOG_1(_L8("CIPConnectionSelector::Select() %08x"), this); + + STypeId tId = STypeId::CreateSTypeId(aPreferences.GetTypeId()); + ASSERT(tId.iUid.iUid == KESockMessagesImplementationUid); + ASSERT(tId.iType == EESockMessageConnStart); + + if (aMessage) + iSelectMessage = *aMessage; // aMessage will be passed on to shim +#ifdef SYMBIAN_NETWORKING_UMTSR5 + //Here secure Id of application is stored and will be kept with + if(!iSelectMessage.IsNull()) + { + iAppSecureId=iSelectMessage.SecureId(); + } +#endif // SYMBIAN_NETWORKING_UMTSR5 + + TRAPD(r, SelectL(aPreferences)); + + if (r!=KErrNone && iNextLayerSelector==NULL) + { + __FLOG_1(_L8("Error during selection of current - should detech now %08x"), this); + Detach(); + return r; + } + + TRAP(r,SelectLinkLayerL()); + if (r != KErrNone) + { + __FLOG_1(_L8("Error during select of link layer - detach should be called by the link layer %08x"), this); + } + + return r; + } + +void CIPConnectionSelector::SelectL(Meta::SMetaData& aPreferences) + { + ASSERT(iDbs==0); +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + iDbs = CMDBSession::NewL(KCDVersion1_2); +#else + iDbs = CMDBSession::NewL(KCDVersion1_1); +#endif + + // Reveal hidden or private IAP records if a licensee has chosen to protect a record + // using one of these flags - the API to do this is public so internal components + // have to support the use of such records. + iDbs->SetAttributeMask( ECDHidden | ECDPrivate ); + + ASSERT(iConnStart==0); + iConnStart = CConnStart::NewL(); + iConnStart->Copy(aPreferences); + + // Get "defaultSnap" and "promptForSnap" from CommsDat. + CCDGlobalSettingsRecord* gs = LoadGlobalSettingsRecordLC(); + TBool promptForSnap = gs->iPromptForSnap; + iAPid = gs->iDefaultSnap; // Unless reassigned, iAPid becomes the default access point. + CleanupStack::PopAndDestroy(gs); + + __FLOG_STMT(_LIT(K, "SelectL() Prompt%d Def%d")); + __FLOG_2(K, promptForSnap, iAPid); + + if (iAPid != 0) + // System is access point aware. + { + TConnStartType selectType(iConnStart->StartType()); + TConnPref* selectPrefs = iConnStart->ConnPrefs(); + + if (selectType == EConnStartImplicit || + selectPrefs == 0 || selectPrefs->ExtensionId() == TConnPref::EConnPrefUnknown) + // Use default access point or dialogue if enabled. + { + __FLOG_STMT(_LIT(K, "SelectL() Default Type%d Prefs%d")); + __FLOG_2(K, selectType, selectPrefs); + + // Use the default access point unless promptForSnap is ETrue in which case prompt + // for the access point. + if (promptForSnap) + { + User::LeaveIfError(iDlgServ.Connect()); + iDlgServ.AccessPointConnection(iAPid,KAfInet,iStatus); + SetActive(); + return; // Don't do selection until RunL() gets the dialogue results. + } + + CCDIAPPrioritySelectionPolicyRecord* policy = LoadPolicyRecordLC(iAPid); + FillListL(*policy); + CleanupStack::PopAndDestroy(policy); + } + else if (selectPrefs && selectPrefs->ExtensionId() == TConnPref::EConnPrefSnap) + // Use access point id from preferences. + { + iAPid = static_cast(selectPrefs)->Snap(); + + __FLOG_STMT(_LIT(K, "SelectL() Type%d TConnPrefSnap AccessPoint%d ")); + __FLOG_2(K, selectType, iAPid); + + CCDIAPPrioritySelectionPolicyRecord* policy = LoadPolicyRecordLC(iAPid); + FillListL(*policy); + CleanupStack::PopAndDestroy(policy); + } + } + } + +void CIPConnectionSelector::FillListL(CCDIAPPrioritySelectionPolicyRecord& aPolicy) + { + __FLOG_0(_L("FillListL()")); + + // Make sure we have the TCommIdList. + + // Create the new Prefs on the heap so that they are always available + // even in the asynchronous promptForSnap Active Object callback + // The copy of the original Prefs are overwritten here + // The original Prefs are deleted in esock. + // The new Prefs are deleted on destruction of CIPConnectionSelector + + iConnStart->SetConnPrefs(NULL); + iConnStart->SetConnPrefs(new (ELeave) TCommIdList); + + // Store Prefs for deletion on destruction of CIPConnectionSelector + ASSERT(iPrefs==0); + iPrefs = iConnStart->ConnPrefs(); + + TCommIdList& list = *static_cast(iPrefs); + + CMDBRecordLink* theIap = &aPolicy.iIap1; + CMDBField* theCount = &aPolicy.iIapCount; + TInt count = static_cast(*theCount); + if (count > CCDIAPPrioritySelectionPolicyRecord::EMaxNrOfIaps) + { + // The number of IAP's specified is more than allowed. Fix your table :-) + ASSERT(EFalse); + count = CCDIAPPrioritySelectionPolicyRecord::EMaxNrOfIaps; + } + for (TInt i = 0; i < count; i++, theIap++) + { + TInt theIapNumber = static_cast(*theIap); + ASSERT(theIapNumber>0); + __FLOG_STMT(_LIT(K, "aList[%d].Append(%d)")); + __FLOG_2(K, list.Count(), theIapNumber); + list.Append(theIapNumber); + } + } + +void CIPConnectionSelector::SelectLinkLayerL() + { + CConnectionFactoryContainer* connectionFactories = SockManGlobals::Get()->iConnectionFactories; + ASSERT(connectionFactories); + CConnectionProviderFactoryBase* factory = connectionFactories->FindFactory(KShimConnectionProviderFactoryId); + ASSERT(factory); + ISelectionNotify selectNotify( this, TSelectionNotify::SelectComplete, + TProgressNotify::ProgressNotification, + TServiceChangeNotify::ServiceChangeNotification, + TLayerUp::LayerUp, + TSubConnectionEventTmpl::SubConnectionEvent, NULL); + selectNotify.RegisterDetach(TDetachNotify::Detach); + + if (iNextLayerSelector!=NULL) + iNextLayerSelector->Cancel(); + + // Select next (link) layer's provider. + ASSERT(iNextLayerSelector==NULL); + ASSERT(iConnStart!=NULL); + + iNextLayerSelector = factory->SelectProvider(*iConnStart, selectNotify, iSelectMessage.IsNull()? NULL : &iSelectMessage); + + if (iNextLayerSelector == NULL) + { + User::Leave(KErrGeneral); + } + + } + +void CIPConnectionSelector::SelectComplete(CConnectionProviderBase* aConnProvider, TInt aError) + { + CIPNetworkConnectionProvider* connProvider = NULL; + if (aError == KErrNone) + { + ASSERT(aConnProvider); + XConnectionIPFactoryQuery query(aConnProvider); + + TRAP( aError, connProvider = static_cast(iFactory.FindOrCreateProviderL(query))); + if (aError == KErrNone && connProvider->NextLayer() == NULL) + { + +#ifdef SYMBIAN_NETWORKING_UMTSR5 + // This piece of code is added to keep the information about the application secure ID in the + // IP Connection provider. So that when the information is required form the subconnection provider + // we can do a fetch interface and get the App Secure ID to decide on to the Socket Blocking + + connProvider->SetAppSecurId(iAppSecureId.iId); + + +#endif // SYMBIAN_NETWORKING_UMTSR5 + + // The factory returned a new instance - must set the lower layer. + TRAP(aError,connProvider->JoinNextLayerL(aConnProvider)); + } + } + iNotify.SelectComplete(connProvider, aError); + } + +void CIPConnectionSelector::ProgressNotification(TInt aStage, TInt aError) + { + //The original ISelectionNotifier (iNotify) might be interested in the + //progress, but we aren't. + iNotify.ProgressNotification(aStage, aError); + } + +void CIPConnectionSelector::LayerUp(TInt aError) + { + iNotify.LayerUp(aError); + } + +void CIPConnectionSelector::SubConnectionEvent(CSubConnectionProviderBase* aSubConnNextLayerProvider, const TSubConnectionEvent& aSubConnectionEvent) + { + iNotify.SubConnectionEvent(aSubConnNextLayerProvider, aSubConnectionEvent); + } + +void CIPConnectionSelector::ServiceChangeNotification(TUint32 aId, const TDesC& aType) + { + //The original ISelectionNotifier (iNotify) might be interested in the + //notification, but we aren't. + iNotify.ServiceChangeNotification(aId, aType); + } + +void CIPConnectionSelector::Detach() + { + iNextLayerSelector = NULL; + //Ensure the asynch destructor is ready to use. + //If its not, then we have probably been already deleted which should never happen. + //Detach is the only place we should be deleted from. + ASSERT(!iAsyncDestructor.IsActive()); + __FLOG_1(_L8("CIPConnectionSelector %08x::Detach()"), this); + iAsyncDestructor.Call(); + } + +CIPConnectionSelector::CIPConnectionSelector(ISelectionNotify& aNotify, CIPNetworkProviderFactory& aFactory) +: CActive(CActive::EPriorityUserInput), + iNotify(aNotify), + iFactory(aFactory), + iAsyncDestructor(CActive::EPriorityLow) + { + __FLOG_1(_L8("CIPConnectionSelector %08x::CIPConnectionSelector()"), this); + CActiveScheduler::Add(this); + iAsyncDestructor.Set(TCallBack(CIPConnectionSelector::DestroyMyself, this)); + + } + +TInt CIPConnectionSelector::DestroyMyself(TAny* aSelf) + { + delete static_cast(aSelf); + return KErrNone; + } + +CIPConnectionSelector::~CIPConnectionSelector() + { + __FLOG_CLOSE; + CActive::Cancel(); // There may be an outstanding selection request. + + // This destructor is private and is meant to be called asynchronously via Detach() or Cancel() only. + // If is was called from anywhere else, the iNextLayerSelector would not be deleted! + // Please note that deleting iNextLayerSelector here needs revision on the link layer selectors, + // and specifically of the shim selector which - in such case - must not call Detach from its + // synchronous destructor! + ASSERT(iNextLayerSelector==NULL); // If still a valid pointer - probably not called via Detach() or Cancel(). + + delete iDbs; + + // Tidy up iConnStart and related objects + delete iPrefs; + delete iConnStart; + + iDlgServ.Close(); + + // Notify detach. + iNotify.Detach(); + } + +void CIPConnectionSelector::RunL() + // The dialogue has been presented. + // Normally completes with KErrNone or KErrCancel + // Could, however, complete with another system error e.g. KErrOutOfMemory + { + __FLOG_STMT(_LIT(K, "RunL() Err%d Snap%d")); + __FLOG_2(K, iStatus.Int(), iAPid); + + User::LeaveIfError(iStatus.Int()); + ASSERT(iAPid); //Should not be 0 now. + CCDIAPPrioritySelectionPolicyRecord* policy = LoadPolicyRecordLC(iAPid); + FillListL(*policy); + CleanupStack::PopAndDestroy(policy); + SelectLinkLayerL(); + } + +TInt CIPConnectionSelector::RunError(TInt aError) + // Either the dialogue, the FillListL() or the SelectLinkLayerL() failed. + // In each case the selection request is completed with the apropriate result code. + { + iNotify.SelectComplete(0, aError); + + //If we have failed before the call to iNextLayerSelector->Select() or it wasn't successful + //we need to initiate the detach sequence by calling Detach(). + if (iNextLayerSelector==NULL) + { + Detach(); //It will result in self deletion. + } + return KErrNone; + } + +void CIPConnectionSelector::DoCancel() + { + iDlgServ.CancelAccessPointConnection(); + } + +CCDGlobalSettingsRecord* CIPConnectionSelector::LoadGlobalSettingsRecordLC() + { + CCDGlobalSettingsRecord* gs = static_cast(CCDConnectionPrefsRecord::RecordFactoryL(KCDTIdGlobalSettingsRecord)); + CleanupStack::PushL(gs); + gs->SetRecordId(1); + gs->LoadL(*iDbs); + ASSERT(gs->iDefaultSnap.TypeId() == KCDTIdDefaultSnap); // Panics if built against incorrect CommsDat. + return gs; + } + +CCDIAPPrioritySelectionPolicyRecord* CIPConnectionSelector::LoadPolicyRecordLC(TInt aAccessPoint) + { + // Get access point from CommsDat. + CCDAccessPointRecord* apRecord = static_cast + (CCDConnectionPrefsRecord::RecordFactoryL(KCDTIdAccessPointRecord)); + CleanupStack::PushL(apRecord); + apRecord->SetRecordId(aAccessPoint); + apRecord->LoadL(*iDbs); + TUint32 policyNumber = apRecord->iSelectionPolicy; + CleanupStack::PopAndDestroy(apRecord); + + ASSERT((policyNumber & KCDMaskShowRecordType) == KCDTIdIapPrioritySelectionPolicyRecord); + + CCDIAPPrioritySelectionPolicyRecord* policy = static_cast + (CCDConnectionPrefsRecord::RecordFactoryL(KCDTIdIapPrioritySelectionPolicyRecord)); + CleanupStack::PushL(policy); + policy->SetElementId(policyNumber); + policy->LoadL(*iDbs); + return policy; + } + +MCommsFactoryQuery::TMatchResult XConnectionIPFactoryQuery::Match( TFactoryObjectInfo& aProviderInfo ) + { + CConnectionProviderBase* prov = static_cast(aProviderInfo.iInfo.iFactoryObject); + //if the next layer is the same as the one returned by the shim selection we have a match + return prov->NextLayer() == iConnectionProviderBase ? EMatch : EContinue; + } +