linklayercontrol/networkinterfacemgr/netcfgext/src/netcfgextnbase.cpp
changeset 0 af10295192d8
child 5 1422c6cd3f0c
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements generic base for NIFMAN side of configuration daemon
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file NIFConfigurationControl.cpp
       
    20  @internalTechnology
       
    21 */
       
    22 
       
    23 #include "networkconfigextensionbase.h"
       
    24 #include <comms-infras/nifif.h>
       
    25 #include <comms-infras/ca_startserver.h>
       
    26 #include <cdbcols.h>
       
    27 #include <comms-infras/commsdebugutility.h>
       
    28 
       
    29 
       
    30 #ifdef _DEBUG
       
    31 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    32 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    33 _LIT(KSpecAssert_NifManNetCfgExtn, "NifManNetCfgExtn");
       
    34 #endif
       
    35 
       
    36 _LIT(KIAPId, "IAP\\Id");
       
    37 _LIT(KIAPNetwork, "IAP\\IAPNetwork");
       
    38 
       
    39 
       
    40 /**
       
    41    ADeletionNotifier
       
    42 */
       
    43 ADeletionNotifier::~ADeletionNotifier()
       
    44 	{
       
    45 	iDeletionListener->NotifyDeletionL(this);
       
    46 	}
       
    47 
       
    48 /**
       
    49    ADeferredDeletion
       
    50 */	
       
    51 void ADeferredDeletion::ListenForObjectDeletionL(ADeletionNotifier */*aDelete*/)
       
    52 	{
       
    53 	iDeletionObjectCount++;
       
    54 	}
       
    55 
       
    56 EXPORT_C void ADeferredDeletion::DeleteThis()
       
    57 	{
       
    58 	iDeleteWhenAllObjectsDeleted = ETrue;
       
    59 	if (iDeletionObjectCount == 0)
       
    60 		{
       
    61 		delete this;
       
    62 		}
       
    63 	}
       
    64 
       
    65 EXPORT_C void ADeferredDeletion::NotifyDeletionL(ADeletionNotifier */*aDelete*/)
       
    66 	{
       
    67 	iDeletionObjectCount--;
       
    68 	if (iDeleteWhenAllObjectsDeleted && iDeletionObjectCount == 0)
       
    69 		{
       
    70 		DeleteThis();
       
    71 		}
       
    72 	}
       
    73 
       
    74 NONSHARABLE_CLASS(CAsynchDaemonCancel) : public CActive, public ADeletionNotifier
       
    75 {
       
    76 public:
       
    77    CAsynchDaemonCancel(ADeferredDeletion* aDeletionListener) :
       
    78 	   CActive(EPriorityStandard), ADeletionNotifier(aDeletionListener)
       
    79 	   {
       
    80 	   }
       
    81 
       
    82    void AsyncDelete();
       
    83 
       
    84    void CancelControl(RConfigDaemon& aConfigDaemon, TBool aDeleteOnCompletion);
       
    85    void CancelControl(RConfigDaemon& aConfigDaemon, TInt aOpMask, TBool aDeleteOnCompletion);
       
    86 
       
    87 protected:
       
    88 	virtual void RunL();
       
    89 	virtual void DoCancel();
       
    90 
       
    91 protected:
       
    92 	TBool iDeleteOnCompletion;
       
    93 	};
       
    94 
       
    95 NONSHARABLE_CLASS(CNifDaemonProgress) : public CActive, public ADeletionNotifier, public ADeferredDeletion
       
    96 /**
       
    97  * Active object class used by CNetworkConfigExtensionBase to maintain a persistent 
       
    98  * ProgressNotification call against the daemon. Delete this object only using the 
       
    99  * AsyncDelete method.
       
   100  *
       
   101  * @internalComponent
       
   102  */
       
   103 	{
       
   104 public:
       
   105 	static CNifDaemonProgress* NewL(RConfigDaemon& aConfigDaemon, CNetworkConfigExtensionBase* aProgressDest, ADeferredDeletion* aDeletionListener);
       
   106 	void ProgressNotification();
       
   107    	void AsyncDelete();
       
   108 	void DeleteThis();
       
   109    	void CancelControl();
       
   110 
       
   111 protected:
       
   112 	void RunL();
       
   113 	void DoCancel();
       
   114 
       
   115 	// This is protectde so that you MUST use AsyncDelete.
       
   116 	virtual ~CNifDaemonProgress() {};
       
   117 	
       
   118 private:
       
   119 
       
   120   	void ConstructL();
       
   121    	CNifDaemonProgress(RConfigDaemon& aConfigDaemon, CNetworkConfigExtensionBase* aProgressDest, ADeferredDeletion* aDeletionListener);
       
   122 	/** Reference to the configuration daemon interface. */
       
   123    	RConfigDaemon& iConfigDaemon;
       
   124 	/** Used to asynchrounously cancel any outstanding request on iConfigDaemon so that esock is never blocked. */
       
   125    	CAsynchDaemonCancel* iAsynchDaemonCancel;
       
   126 	/** The target for progress notifications. */
       
   127    	CNetworkConfigExtensionBase* iProgressDest;
       
   128 	/** Stores the progress notification. */
       
   129    	TDaemonProgressBuf iProgressBuf;
       
   130 	/** If ETrue, the object should delete itself when the outstanding request completes. */
       
   131 	TBool iDeleteOnCompletion;
       
   132 	};
       
   133 
       
   134 void CAsynchDaemonCancel::AsyncDelete()
       
   135 /**
       
   136  * Delete the instance of CAsynchDaemonCancel safely.
       
   137  * 
       
   138  * @internalComponent
       
   139  */
       
   140 	{
       
   141 	if (IsActive())
       
   142 		iDeleteOnCompletion = ETrue;
       
   143 	else
       
   144 		delete this;
       
   145 	}
       
   146 
       
   147 void CAsynchDaemonCancel::DoCancel()
       
   148    {//nothing to do
       
   149    }
       
   150 
       
   151 void CAsynchDaemonCancel::CancelControl(RConfigDaemon& aConfigDaemon, TBool aDeleteOnCompletion)
       
   152    {
       
   153       if (!IsActive())
       
   154          {
       
   155          __ASSERT_DEBUG(!IsAdded(), User::Panic(KSpecAssert_NifManNetCfgExtn, 1));	
       
   156          CActiveScheduler::Add(this);
       
   157          aConfigDaemon.Cancel(iStatus);
       
   158          SetActive();
       
   159          }
       
   160       iDeleteOnCompletion = aDeleteOnCompletion;
       
   161    }
       
   162 
       
   163 void CAsynchDaemonCancel::CancelControl(RConfigDaemon& aConfigDaemon, TInt aOpMask, TBool aDeleteOnCompletion)
       
   164 /**
       
   165  * CancelControl - Asynchronously cancels the last server request according to aOpMask.
       
   166  *
       
   167  * @internalComponent
       
   168  */
       
   169    {
       
   170       if (!IsActive())
       
   171          {
       
   172          __ASSERT_DEBUG(!IsAdded(), User::Panic(KSpecAssert_NifManNetCfgExtn, 2));
       
   173          CActiveScheduler::Add(this);
       
   174          aConfigDaemon.Cancel(aOpMask,iStatus);
       
   175          SetActive();
       
   176          }
       
   177       iDeleteOnCompletion = aDeleteOnCompletion;
       
   178    }
       
   179    
       
   180 void CAsynchDaemonCancel::RunL()
       
   181   	{
       
   182 	   if ( iDeleteOnCompletion )
       
   183 		   {
       
   184 		   delete this;
       
   185 		   }
       
   186 	   else
       
   187 		   {
       
   188 		   Deque();
       
   189 		   }
       
   190   	}
       
   191   	
       
   192 CNifDaemonProgress* CNifDaemonProgress::NewL(RConfigDaemon& aConfigDaemon, CNetworkConfigExtensionBase* aProgressDest, ADeferredDeletion* aDeletionListener)
       
   193 /**
       
   194  * Standard NewL for CNifDaemonProgress.
       
   195  * 
       
   196  * @internalComponent
       
   197  *
       
   198  * @param aConfigDaemon	Daemon client to be used.
       
   199  * @param aProgressDest	Destination for progress notifications.
       
   200  * @leave KErrNoMemory if there is insufficient heap.
       
   201  */
       
   202    {
       
   203 	   CNifDaemonProgress* pDaemonProgress = new(ELeave)CNifDaemonProgress(aConfigDaemon, aProgressDest, aDeletionListener);
       
   204    CleanupStack::PushL(pDaemonProgress);
       
   205    pDaemonProgress->ConstructL();
       
   206    CleanupStack::Pop(pDaemonProgress);
       
   207    return pDaemonProgress;
       
   208    }
       
   209 
       
   210 void CNifDaemonProgress::DeleteThis()
       
   211 	{
       
   212 	if (iAsynchDaemonCancel)
       
   213 		{
       
   214 		iAsynchDaemonCancel->AsyncDelete();
       
   215 		iAsynchDaemonCancel = NULL;
       
   216 		}
       
   217 	ADeferredDeletion::DeleteThis();
       
   218 	}
       
   219 
       
   220 void CNifDaemonProgress::ConstructL()
       
   221 /**
       
   222  * Standard ConstructL for CNifDaemonProgress.
       
   223  * 
       
   224  * @internalComponent
       
   225  *
       
   226  * @leave KErrNoMemory if there is insufficient heap.
       
   227  */
       
   228    {
       
   229    iAsynchDaemonCancel = new(ELeave)CAsynchDaemonCancel(this);
       
   230    }
       
   231 
       
   232 CNifDaemonProgress::CNifDaemonProgress(
       
   233 	RConfigDaemon& aConfigDaemon, 
       
   234 	CNetworkConfigExtensionBase* aProgressDest,
       
   235 	ADeferredDeletion* aDeletionListener) :
       
   236 	CActive(EPriorityStandard),
       
   237 	ADeletionNotifier(aDeletionListener),
       
   238    	iConfigDaemon(aConfigDaemon),
       
   239    	iAsynchDaemonCancel(NULL),
       
   240    	iProgressDest(aProgressDest),
       
   241    	iDeleteOnCompletion(EFalse)
       
   242 /**
       
   243  * Construct the progress active object. Adds the active object to the scheduler and 
       
   244  * issues the asynchronous call.
       
   245  * 
       
   246  * @internalComponent
       
   247  *
       
   248  * @param aConfigDaemon	Daemon client to be used.
       
   249  * @param aProgressDest	Destination for progress notifications.
       
   250  */
       
   251     {
       
   252     CActiveScheduler::Add(this);
       
   253     ProgressNotification();       
       
   254     }  	
       
   255   	
       
   256 void CNifDaemonProgress::ProgressNotification()
       
   257 /**
       
   258  * Issues the asynchronous progress notification request.
       
   259  * 
       
   260  * @internalComponent
       
   261  */
       
   262 	{
       
   263 	iConfigDaemon.ProgressNotification(iProgressBuf, iStatus);
       
   264 	SetActive();
       
   265 	}
       
   266   	
       
   267 void CNifDaemonProgress::RunL()
       
   268 /**
       
   269  * Indicates that a progress notification was received. 
       
   270  * The progress info will be found in iProgressBuf.
       
   271  * 
       
   272  * @internalComponent
       
   273  */
       
   274 	{
       
   275 	if (iDeleteOnCompletion)
       
   276 		{
       
   277 		// if iDeleteOnCompletion is true, we are to delete ourselves
       
   278 	  	__FLOG_STATIC0(KLogSubSysNifman, KLogTagCsDaemon, _L("CNifDaemonProgress::RunL - Deleting ourselves."));	
       
   279 		DeleteThis();
       
   280 		}
       
   281 	else if (iStatus.Int() == KErrNone)
       
   282 		{
       
   283 		// We successfully got a progress notification. Pass it
       
   284 		// on the the target and re-issue the request.
       
   285 	  	__FLOG_STATIC1(KLogSubSysNifman, KLogTagCsDaemon, _L("CNifDaemonProgress::RunL - Successfully received progress notification %d. Re-issuing request."),iProgressBuf().iStage);	
       
   286 		iProgressDest->DoOnDaemonProgress(iProgressBuf().iStage, iProgressBuf().iError);
       
   287 		ProgressNotification();	
       
   288 		}
       
   289 	else if (iStatus.Int() == KErrNotReady)
       
   290 		{
       
   291 		// The daemon is starting-up. Re-issue the request.
       
   292 		__FLOG_STATIC0(KLogSubSysNifman, KLogTagCsDaemon, _L("CNifDaemonProgress::RunL - Progress notification. Waiting for server to start."));
       
   293 		ProgressNotification();	
       
   294 		}
       
   295 	else
       
   296 		{
       
   297 		// We failed to get a progress notification.
       
   298 		// The daemon either does not support this request,
       
   299 		// has exited or has died. Do not issue another request. 
       
   300 		// We'll get into a tight loop if we do.
       
   301 	  	__FLOG_STATIC1(KLogSubSysNifman, KLogTagCsDaemon, _L("CNifDaemonProgress::RunL - Failed to get progress notification from daemon. The error was %d"),iStatus.Int());	
       
   302 	  	}
       
   303   	}
       
   304 
       
   305 void CNifDaemonProgress::AsyncDelete()
       
   306 /**
       
   307  * Cancels any outstanding progress notification and optionally 
       
   308  * the instance of CNifDaemonProgress asynchronously to avoid
       
   309  * potential deadlock in Esock.
       
   310  *
       
   311  * @internalComponent
       
   312  */	
       
   313 	{
       
   314    	if (IsActive())
       
   315     	{
       
   316 	  	__FLOG_STATIC0(KLogSubSysNifman, KLogTagCsDaemon, _L("CNifDaemonProgress::AsyncDelete - Waiting for CancelControl to complete"));	
       
   317        	iDeleteOnCompletion = ETrue;
       
   318        	CancelControl();
       
   319        	}
       
   320  	else
       
   321     	{
       
   322 		DeleteThis();
       
   323        	}
       
   324 	}
       
   325 
       
   326 void CNifDaemonProgress::CancelControl()
       
   327 /**
       
   328  * Cancels any outstanding progress asynchronously to avoid
       
   329  * potential deadlock in Esock.
       
   330  *
       
   331  * @internalComponent
       
   332  */
       
   333 	{
       
   334 	if (IsActive())
       
   335 		{
       
   336 		iAsynchDaemonCancel->CancelControl(iConfigDaemon, KConfigDaemonOpMaskProgress, iDeleteOnCompletion);
       
   337 		if (iDeleteOnCompletion)
       
   338 			iAsynchDaemonCancel = NULL;
       
   339 		}
       
   340 	}
       
   341 
       
   342 void CNifDaemonProgress::DoCancel()
       
   343 /**
       
   344  * Standard active object DoCancel.
       
   345  * 
       
   346  * @internalComponent
       
   347  */
       
   348 	{
       
   349 	// DoCancel() is only used by Cancel(), which is can not be 
       
   350 	// used as it will block the ESOCK thread.
       
   351 	__ASSERT_DEBUG(0, User::Panic(KSpecAssert_NifManNetCfgExtn, 3)); 
       
   352 	}
       
   353 
       
   354 CNetworkConfigExtensionBase* CNetworkConfigExtensionBase::NewL( TAny* aMNifIfNotify )
       
   355    {
       
   356    MNifIfNotify* nifIfNotify = reinterpret_cast<MNifIfNotify*>(aMNifIfNotify);
       
   357    CNetworkConfigExtensionBase* pDaemon = new(ELeave)CNetworkConfigExtensionBase( *nifIfNotify );
       
   358 	CleanupStack::PushL(pDaemon);
       
   359    pDaemon->ConstructL();
       
   360 	CleanupStack::Pop(pDaemon);
       
   361    return pDaemon;
       
   362    }
       
   363 
       
   364 EXPORT_C void CNetworkConfigExtensionBase::ConstructL()
       
   365    {
       
   366    __FLOG_STATIC0(KLogSubSysNifman, KLogTagCsDaemon, _L("CNetworkConfigExtensionBase::ConstructL"));
       
   367    iAsynchDaemonCancel = new(ELeave)CAsynchDaemonCancel(this);
       
   368    }
       
   369 
       
   370 EXPORT_C void CNetworkConfigExtensionBase::ConfigureNetworkL()
       
   371 /**
       
   372 ConfigureNetworkL - starts a daemon and issues configuration request
       
   373 @internalTechnology
       
   374 @version 0.02
       
   375 **/
       
   376 	{
       
   377   	__FLOG_STATIC0(KLogSubSysNifman, KLogTagCsDaemon, _L("CNetworkConfigExtensionBase::ConfigureNetworkL"));	
       
   378 	//it could access directly CNifAgentRef::ConnectionInfo but i don't want the class be 
       
   379 	//CNifAgentRef dependent
       
   380    	__ASSERT_DEBUG(iMessage.IsNull(), User::Panic(KSpecAssert_NifManNetCfgExtn, 4));
       
   381 	
       
   382 	User::LeaveIfError(iNifIfNotify->ReadInt(KIAPId(), iConnectionInfoBuf().iIapId));
       
   383 	User::LeaveIfError(iNifIfNotify->ReadInt(KIAPNetwork(), iConnectionInfoBuf().iNetId));
       
   384    	//this is the same read as in CNifConfigurationControl::NewL we do the read rather than storing the
       
   385    	//server name since the db access should really provide an efficient access to the settings
       
   386    	//already selected by NETCON
       
   387 	TBuf<KCommsDbSvrMaxFieldLength> serverName;		/*100 bytes if unicode*/
       
   388 	User::LeaveIfError(iNifIfNotify->ReadDes(TPtrC(SERVICE_CONFIG_DAEMON_NAME), serverName));
       
   389 	// safe to pass stack var here, as its copied down the track...
       
   390 
       
   391 	// For security reasons, ensure that the server name has the "!" prefix - only protected
       
   392 	// servers should be involved with Network Configuration.
       
   393 	
       
   394 	_LIT(KExclamationMark, "!");
       
   395 	if (serverName.Left(1).Compare(KExclamationMark()) != 0)
       
   396 		serverName.Insert(0,KExclamationMark());
       
   397 	
       
   398 	__ASSERT_DEBUG(!ipStartServer, User::Panic(KSpecAssert_NifManNetCfgExtn, 5));
       
   399 	DoOnGenericProgress(KConfigDaemonLoading, KErrNone);
       
   400 	ipStartServer = new(ELeave)CStartServer(iConfigDaemon, iConfigDaemon.Version(), 10);
       
   401 	ipStartServer->Connect(serverName, iStatus);
       
   402 	SetActive();
       
   403 	}
       
   404 
       
   405 EXPORT_C void CNetworkConfigExtensionBase::LinkLayerDown()	
       
   406 /**
       
   407  * Generates an EConfigDaemonLinkLayerDown request. Used to inform the
       
   408  * daemon that link-layer renegotiation has started.
       
   409  * 
       
   410  * @internalComponent
       
   411  */
       
   412 	{
       
   413 	if (iSuccessfullyCreatedDaemon)
       
   414 		iConfigDaemon.LinkLayerDown();
       
   415 	}
       
   416 
       
   417 EXPORT_C void CNetworkConfigExtensionBase::LinkLayerUp()	
       
   418 /**
       
   419  * Generates an EConfigDaemonLinkLayerUp request. Used to inform the
       
   420  * daemon that link-layer renegotiation has completed.
       
   421  * 
       
   422  * @internalComponent
       
   423  */
       
   424 	{
       
   425 	if (iSuccessfullyCreatedDaemon)
       
   426 		iConfigDaemon.LinkLayerUp();
       
   427 	}
       
   428 
       
   429 EXPORT_C void CNetworkConfigExtensionBase::Deregister(
       
   430 	TInt aCause)	
       
   431 /**
       
   432  * Generates a deregistration request.
       
   433  * 
       
   434  * @internalComponent
       
   435  *
       
   436  * @param aCause Specifies what caused the deregistration request (idle timer or Stop call)
       
   437  */
       
   438 	{
       
   439 	if (IsActive())
       
   440 		{
       
   441 		// if a deregistration request isn't queued up, queue one up
       
   442 		if (!iDeregisterOnCompletionOfRequest)
       
   443 			{
       
   444 			iDeregisterOnCompletionOfRequest = ETrue;
       
   445 			iDeregistrationCauseCode = aCause;
       
   446 			}
       
   447 		}
       
   448 	else if (!iSuccessfullyCreatedDaemon)
       
   449 		{
       
   450 		// note that there is no longer a queued deregistration
       
   451 		// request
       
   452 		iDeregisterOnCompletionOfRequest = EFalse;
       
   453 		// fake the behaviour of the daemon and report 
       
   454 		// KErrNotFound to be compatible with the previous
       
   455 		// behaviour expected by the DHCP tests - KErrNotFound
       
   456 		// as in the daemon "was not found"
       
   457 		DoOnGenericProgress(KConfigDaemonStartingDeregistration, KErrNone);
       
   458 		DoOnGenericProgress(KConfigDaemonFinishedDeregistrationStop, KErrNotFound);		
       
   459 		}
       
   460 	else
       
   461 		{
       
   462 		// note that there is no longer a queued deregistration
       
   463 		// request
       
   464 		iDeregisterOnCompletionOfRequest = EFalse;
       
   465 		// progress notification before the operation
       
   466 		DoOnGenericProgress(KConfigDaemonStartingDeregistration, KErrNone);
       
   467 		// ask the daemon to deregister
       
   468 		iConfigDaemon.Deregister(aCause, &iDesDeregActionStatus, iStatus);
       
   469 		SetActive();
       
   470 		}    	
       
   471 	}
       
   472 
       
   473 EXPORT_C void CNetworkConfigExtensionBase::SendIoctlMessageL(const ESock::RLegacyResponseMsg& aMessage)
       
   474 /**
       
   475 * SendIoctlMessageL forwards Ioctl request to the daemon and activates the AO to wait for response
       
   476 * 
       
   477 @internalTechnology
       
   478 @version 0.02
       
   479 @param aMessage[in] a message to be processed (it's the caller's resposibility to forward just Ioctl
       
   480 *                   messages)
       
   481 **/
       
   482 	{
       
   483    	__FLOG_STATIC0(KLogSubSysNifman, KLogTagCsDaemon, _L("CNetworkConfigExtensionBase::SendIoctlMessageL"));	
       
   484 	if (static_cast<TUint>(aMessage.Int0()) != KCOLConfiguration)
       
   485 		{
       
   486 		User::Leave(KErrNotSupported);
       
   487 		}
       
   488    	else
       
   489 		{
       
   490 		if (!IsActive())
       
   491 			{
       
   492 			TDes8* ptr = NULL;
       
   493 			// may not always have a buffer to read...
       
   494 			if (aMessage.Ptr2())
       
   495 				{
       
   496 
       
   497             	delete iIoBuf;
       
   498             	iIoBuf = NULL;
       
   499             	TInt maxLength = aMessage.GetDesMaxLengthL(2);
       
   500 				iIoBuf=HBufC8::NewMaxL(maxLength);
       
   501 				iIoPtr.Set(iIoBuf->Des());
       
   502 				aMessage.ReadL(2, iIoPtr);
       
   503 				
       
   504 				TInt length = aMessage.GetDesLength(2);
       
   505 				if (length<1) //length could be -ve due to error return from GetDesLength
       
   506 					{
       
   507 					iIoPtr.SetLength(maxLength);
       
   508 					}
       
   509 				else
       
   510 					{
       
   511 					iIoPtr.SetLength(length);
       
   512 					}
       
   513 				ptr = &iIoPtr;
       
   514 				}
       
   515 			//store msg after ReadDescriptorL which could leave
       
   516 			iMessage = aMessage;
       
   517 			iConfigDaemon.Ioctl(aMessage.Int0(), aMessage.Int1(), iStatus, ptr);
       
   518 			SetActive();      
       
   519 			}
       
   520 		else
       
   521 			{
       
   522 			User::Leave(KErrInUse);
       
   523 			}
       
   524 		}
       
   525 	}
       
   526 	
       
   527 EXPORT_C void CNetworkConfigExtensionBase::AsyncDelete()
       
   528 /**
       
   529 Provide a clever method for deletion and 
       
   530 asynchronously cancelling any outstanding event
       
   531 so as to avoid any problems of deadlock
       
   532 **/	
       
   533 	{
       
   534 	if (IsActive()) //are we waiting?
       
   535     	{
       
   536        	//yes
       
   537 		// complete any blocked client message immediately - no sense in keeping them hanging on and in a session close 
       
   538 		// case the dealer may race us to this
       
   539 		if (!iMessage.IsNull())
       
   540 			{
       
   541 			iMessage.Complete(KErrCancel);
       
   542 			}
       
   543        	iDeleteOnCompletion = ETrue;
       
   544        	CancelControl();
       
   545        	// Zero our reference to the NIFMAN CNifAgentRef as it can be destroyed
       
   546        	// ahead of us (this problem manifests itself during cycles of connection
       
   547        	// start immediately followed by connection stop).
       
   548        	iNifIfNotify = NULL;
       
   549        	}
       
   550  	else
       
   551     	{
       
   552 		DeleteThis();
       
   553        	}
       
   554 	}
       
   555 
       
   556 EXPORT_C void CNetworkConfigExtensionBase::CancelControl()
       
   557 /**
       
   558  CancelControl - cancels request asynchronously to avoid deadlock
       
   559  @internalAll
       
   560  @version 0.01
       
   561 **/
       
   562 	{
       
   563 	if (IsActive()) //are we waiting?
       
   564 		{
       
   565 		//yes
       
   566 		if (ipStartServer)
       
   567 			{
       
   568 			ipStartServer->Cancel(); //it'll set an error code to KErrCancel meaning that 
       
   569          //the requests will complete with KErrCancel
       
   570 			}
       
   571 		else
       
   572 			{
       
   573 			if(iLastGenericProgressStage != KConfigDaemonStartingDeregistration)
       
   574 				{
       
   575 				iAsynchDaemonCancel->CancelControl(iConfigDaemon, iDeleteOnCompletion);
       
   576 				if ( iDeleteOnCompletion )
       
   577 					{
       
   578 					iAsynchDaemonCancel = NULL;
       
   579 					}
       
   580 				}
       
   581 			}
       
   582 		//the RunL method will be called on the original request cancellation
       
   583 		}
       
   584 	}
       
   585 
       
   586 EXPORT_C void CNetworkConfigExtensionBase::DoCancel()
       
   587 /**
       
   588 DoCancel - cancels current request
       
   589 @internalTechnology
       
   590 @version 0.01
       
   591 @see CActive::DoCancel
       
   592 **/
       
   593 	{
       
   594   	__ASSERT_DEBUG(0, User::Panic(KSpecAssert_NifManNetCfgExtn, 6)); //we shouldn't ever get here, would block NIFMAN/ESOCK thread
       
   595 	}
       
   596 
       
   597 EXPORT_C void CNetworkConfigExtensionBase::RunL()
       
   598 /**
       
   599 RunL - called when request completes
       
   600 @internalTechnology
       
   601 @version 0.03
       
   602 @see CActive::RunL
       
   603 **/
       
   604 	{
       
   605   	//__FLOG_STATIC0(KLogSubSysNifman, KLogTagCsDaemon, _L("CNetworkConfigExtensionBase::RunL"));	
       
   606   	
       
   607 	if (iDeleteOnCompletion)
       
   608 		{
       
   609 		// if iDeleteOnCompletion is true, we are to delete ourselves
       
   610 		
       
   611 		// if there was an outstanding IOCTL request, complete the message
       
   612 		if (!iMessage.IsNull())
       
   613 			{
       
   614 			// client request completion
       
   615 			const TAny* ptr = iMessage.Ptr2();
       
   616 			if (ptr)
       
   617 				{
       
   618 				__ASSERT_DEBUG(iIoBuf, User::Panic(KSpecAssert_NifManNetCfgExtn, 7));
       
   619 				iMessage.WriteL(2, *iIoBuf);
       
   620 				delete iIoBuf; //no longer needed
       
   621 				iIoBuf = NULL;
       
   622 				}
       
   623 			iMessage.Complete(iStatus.Int());
       
   624 			}
       
   625 
       
   626       	__ASSERT_DEBUG(!ipStartServer || !ipStartServer->IsActive(), User::Panic(KSpecAssert_NifManNetCfgExtn, 8));
       
   627 		delete ipStartServer; //no needed any more
       
   628 		ipStartServer = NULL;
       
   629 		DeleteThis();
       
   630 		// *********************************************
       
   631 		// CAREFUL... don't do anything after this point
       
   632 		// because this object has been deleted
       
   633 		// *********************************************		
       
   634 		}
       
   635 	else if (ipStartServer)
       
   636 		{
       
   637 		// the daemon server was created (or the creation failed)
       
   638 		
       
   639 		// if ipStartServer is not null, then the server has just been
       
   640 		// started
       
   641 		delete ipStartServer; //no needed any more
       
   642 		ipStartServer = NULL;
       
   643 		if (iStatus.Int() == KErrNone)
       
   644 			{
       
   645 			// record the fact that the daemon was successfully 
       
   646 			// launched
       
   647 			iSuccessfullyCreatedDaemon = ETrue;
       
   648 			// signal that the daemon was loaded successfully		
       
   649 			DoOnGenericProgress(KConfigDaemonLoaded, KErrNone);
       
   650 			// create progress instance - this registers for daemon progress notifications
       
   651  		 	iDaemonProgress = CNifDaemonProgress::NewL(iConfigDaemon, this, this);
       
   652 			// signal before the Configure method is called		
       
   653 			DoOnGenericProgress(KConfigDaemonStartingRegistration, KErrNone);
       
   654 			//complete connection
       
   655 			iConfigDaemon.Configure(iConnectionInfoBuf, iStatus);
       
   656 			SetActive();
       
   657 			//wait for the Configure to complete
       
   658 			}
       
   659 		else
       
   660 			{
       
   661 			//we're done with en error
       
   662 			iNifIfNotify->IfProgress(KLinkLayerOpen, iStatus.Int());
       
   663 			}
       
   664 		}
       
   665 	else if (!iMessage.IsNull())
       
   666 		{
       
   667 		// the ioctl request completed
       
   668 		
       
   669 		// complete the message
       
   670 		const TAny* ptr = iMessage.Ptr2();
       
   671 		if (ptr)
       
   672 			{
       
   673 			__ASSERT_DEBUG(iIoBuf, User::Panic(KSpecAssert_NifManNetCfgExtn, 9));
       
   674 			iMessage.WriteL(2, *iIoBuf);
       
   675 			delete iIoBuf; //no longer needed
       
   676 			iIoBuf = NULL;
       
   677 			}
       
   678 		iMessage.Complete(iStatus.Int());
       
   679 		
       
   680  		// start to deregister if we happen to have one queued
       
   681  		if (iDeregisterOnCompletionOfRequest)
       
   682  			Deregister(iDeregistrationCauseCode);
       
   683 		}
       
   684 	else if (iLastGenericProgressStage == KConfigDaemonStartingRegistration)
       
   685 		{
       
   686 		// the configure call completed
       
   687 		
       
   688 		// signal the completed Configure call
       
   689 		DoOnGenericProgress(KConfigDaemonFinishedRegistration, iStatus.Int());
       
   690 		//no user request => must be configuration completion => signal it up
       
   691 		 iNifIfNotify->IfProgress(KLinkLayerOpen, iStatus.Int());
       
   692  		// start to deregister if we happen to have one queued
       
   693  		if (iDeregisterOnCompletionOfRequest)
       
   694  			Deregister(iDeregistrationCauseCode);
       
   695 		}
       
   696 	else if (iLastGenericProgressStage == KConfigDaemonStartingDeregistration)
       
   697 		{
       
   698 		// the deregistration request completed
       
   699 		
       
   700 		// if any error occurred, we should assume stop
       
   701 		// is the desired result
       
   702 		if (iStatus.Int() != KErrNone)
       
   703 			iDeregActionStatus = EConfigDaemonDeregisterActionStop;
       
   704 		// if the daemon doesn't support deregistration,
       
   705 		// we act as if everything succeeded
       
   706 		if (iStatus.Int() == KErrNotSupported)
       
   707 			iStatus = KErrNone;
       
   708 		// handle the result
       
   709 		switch (iDeregActionStatus)
       
   710 			{
       
   711 		case EConfigDaemonDeregisterActionStop:
       
   712 			// progress notification - note that this specific
       
   713 			// notification will delete this object
       
   714 			DoOnGenericProgress(KConfigDaemonFinishedDeregistrationStop, iStatus.Int());		
       
   715 			// *****************************************************
       
   716 			// CAREFUL... don't do anything after this point because 
       
   717 			// this object has been deleted as a result of this
       
   718 			// progress notification
       
   719 			// *****************************************************
       
   720 			break;
       
   721 		case EConfigDaemonDeregisterActionPreserve:
       
   722 			// progress notification
       
   723 			DoOnGenericProgress(KConfigDaemonFinishedDeregistrationPreserve, iStatus.Int());		
       
   724 	 		// start to deregister if we happen to have one queued
       
   725 	 		if (iDeregisterOnCompletionOfRequest)
       
   726 	 			Deregister(iDeregistrationCauseCode);
       
   727 			break;
       
   728 		default:
       
   729 			User::Leave(KErrNotSupported);
       
   730 			break;
       
   731 			}			
       
   732 		}
       
   733 	else
       
   734 		{
       
   735 		// should never get here.
       
   736 		__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_NifManNetCfgExtn, 10));
       
   737 		}
       
   738 	// ********************************************
       
   739 	// CAREFUL... consider the possible deletion of
       
   740 	// this object in the code above before adding
       
   741 	// anything down here
       
   742 	// ********************************************			
       
   743 	}
       
   744 	
       
   745 EXPORT_C TInt CNetworkConfigExtensionBase::RunError(TInt aError)
       
   746 	{//see CNetworkConfigExtensionBase::RunL the only case it can leave is when iMessage is valid
       
   747    	if (!iMessage.IsNull())
       
   748 		{
       
   749 		iMessage.Complete(aError);
       
   750 		}
       
   751    	return KErrNone;
       
   752 	}	
       
   753 
       
   754 EXPORT_C void CNetworkConfigExtensionBase::DeleteThis()
       
   755 	{
       
   756 	// delete safely the progress request    
       
   757 	if (iDaemonProgress)
       
   758 		{
       
   759 		iDaemonProgress->AsyncDelete();
       
   760 		iDaemonProgress = NULL;
       
   761 		}
       
   762 
       
   763 	// delete safely the cancel request
       
   764    	if (iAsynchDaemonCancel)
       
   765    		{
       
   766    		iAsynchDaemonCancel->AsyncDelete();
       
   767    		iAsynchDaemonCancel = NULL;
       
   768    		}
       
   769 
       
   770 	ADeferredDeletion::DeleteThis();
       
   771 /*	iDeleteWhenAllObjectsDeleted = ETrue;
       
   772 	if (iDeletionObjectCount == 0)
       
   773 		{
       
   774 		delete this;
       
   775 		}*/
       
   776 	}
       
   777 
       
   778 EXPORT_C CNetworkConfigExtensionBase::~CNetworkConfigExtensionBase()
       
   779 /**
       
   780 ~CNetworkConfigExtensionBase - destructor
       
   781 @internalTechnology
       
   782 @version 0.02
       
   783 **/
       
   784 	{
       
   785 	// complete any outstanding messages
       
   786 	if (!iMessage.IsNull())
       
   787 		{
       
   788 		//client request completion - no point to write any data back to client here
       
   789 		iMessage.Complete(KErrCancel);
       
   790 		}
       
   791    	__ASSERT_DEBUG(!ipStartServer, User::Panic(KSpecAssert_NifManNetCfgExtn, 11));
       
   792 
       
   793 	// unload the daemon		
       
   794     DoOnGenericProgress(KConfigDaemonUnloading, KErrNone);
       
   795    	iConfigDaemon.Close();
       
   796     DoOnGenericProgress(KConfigDaemonUnloaded, KErrNone);
       
   797        		
       
   798    	delete iIoBuf;
       
   799 	}	
       
   800 
       
   801 EXPORT_C void CNetworkConfigExtensionBase::EventNotification(TNetworkAdaptorEventType /*aEventType*/, TUint /*aEvent*/, const TDesC8& /*aEventData*/, TAny* /*aSource*/)
       
   802 /**
       
   803  Notification - does nothing. Needs to be implemented by deriving class to achieve functionality.
       
   804  @internalTechnology
       
   805  @version 0.01
       
   806 **/
       
   807 	{}
       
   808 	
       
   809 void CNetworkConfigExtensionBase::DoOnDaemonProgress(TInt aStage, TInt aError)
       
   810 /**
       
   811  * Called by CNifDaemonProgress when it receives a progress notification. 
       
   812  * Passes the notification to CNifAgentRef.
       
   813  * 
       
   814  * @internalComponent
       
   815  * 
       
   816  * @param aStage Progress stage reported by the daemon
       
   817  * @param aError Error code associated with the stage
       
   818  */
       
   819 	{
       
   820 	if (iNifIfNotify)				// see comment in AsyncDelete()
       
   821 		{
       
   822 		iNifIfNotify->IfProgress(aStage, aError);
       
   823 		}
       
   824 	}
       
   825 
       
   826 void CNetworkConfigExtensionBase::DoOnGenericProgress(TInt aStage, TInt aError)
       
   827 /**
       
   828  * Called to generate the cs_daemon generic progress notifications.
       
   829  * 
       
   830  * @internalComponent
       
   831  * 
       
   832  * @param aStage Generic progress stage
       
   833  * @param aError Error code associated with the stage
       
   834  */
       
   835 	{
       
   836 	iLastGenericProgressStage = aStage;
       
   837 	if (iNifIfNotify)				// see comment in AsyncDelete()
       
   838 		{
       
   839 		iNifIfNotify->IfProgress(aStage, aError);
       
   840 		}
       
   841 	}
       
   842