telephonyprotocols/pdplayer/umts/test/mbufgobblerlayer/src/mbufgobblerflow.cpp
branchRCL_3
changeset 82 042fd2753b8f
equal deleted inserted replaced
74:9200f38b1324 82:042fd2753b8f
       
     1 // Copyright (c) 2010 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 // Flow / Binder
       
    15 //  (data plane)
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include <comms-infras/ss_activities.h>
       
    24 #include <comms-infras/ss_logext.h>
       
    25 #include <es_mbman.h>
       
    26 #include <mbufgobblerpubsub.h>
       
    27 #include "mbufgobblerflow.h"
       
    28 #include "mbufgobblerlog.h"
       
    29 
       
    30 // for panics
       
    31 _LIT(KPanicCategory, "MbufGobblerLayer");
       
    32 enum
       
    33 	{
       
    34 	KPanic_DestroyReceivedBeforeUnbind = 2001
       
    35 	};
       
    36 
       
    37 _LIT8(KNodeName, "CMbufGobblerFlow");
       
    38 
       
    39 
       
    40 ///////////////////////////
       
    41 // class CMbufGobblerFlow  //
       
    42 ///////////////////////////
       
    43 
       
    44 CMbufGobblerFlow* CMbufGobblerFlow::NewL(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf)
       
    45     {
       
    46     CMbufGobblerFlow* inst = new(ELeave) CMbufGobblerFlow(aFactory, aSubConnId, aProtocolIntf);
       
    47     CleanupStack::PushL(inst);
       
    48     inst->ConstructL();
       
    49     CleanupStack::Pop(inst);
       
    50     return inst;    
       
    51     }
       
    52     
       
    53 CMbufGobblerFlow::CMbufGobblerFlow(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf)
       
    54 /**
       
    55  * Constructor.
       
    56  *
       
    57  * @param aFactory Reference to the factory which created this object.
       
    58  * @param aTheLogger The logging object, ownership is passed to this object
       
    59  */
       
    60 	:ESock::CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf)
       
    61 	{
       
    62 	MBUFGOBBLER_LOG_NODE_CREATE(KMbufGobblerFlowSubTag, CMbufGobblerFlow, KNodeName, this->NodeId().Ptr());
       
    63 	}
       
    64 
       
    65 void CMbufGobblerFlow::ConstructL()
       
    66     {
       
    67     iPassThroughMBufGobbler = CMBufGobbler::NewL();
       
    68     }
       
    69     
       
    70 CMbufGobblerFlow::~CMbufGobblerFlow()
       
    71 	{
       
    72 	MBUFGOBBLER_LOG_NODE_DESTROY(KMbufGobblerFlowSubTag, CMbufGobblerFlow, KNodeName, this->NodeId().Ptr());
       
    73 	iBinders.ResetAndDestroy();
       
    74 	delete iPassThroughMBufGobbler;
       
    75 	}
       
    76 
       
    77 
       
    78 
       
    79 ///////////////////////////////////////////
       
    80 // Methods from CSubConnectionFlowBase:  //
       
    81 ///////////////////////////////////////////
       
    82 
       
    83 ESock::MFlowBinderControl* CMbufGobblerFlow::DoGetBinderControlL()
       
    84 	{
       
    85 	return this;
       
    86 	}
       
    87 
       
    88 
       
    89 // Messages::ANode
       
    90 void CMbufGobblerFlow::ReceivedL(
       
    91 	const Messages::TRuntimeCtxId& aSender,
       
    92 	const Messages::TNodeId& aRecipient,
       
    93 	Messages::TSignatureBase& aMessage
       
    94 	)
       
    95 /**
       
    96 Method called on incoming SCPR messages
       
    97 
       
    98 @param aCFMessage message base
       
    99 */
       
   100     {
       
   101    
       
   102     LOGMESSAGE(KMbufGobblerFlowSubTag, KNodeName, this, aSender, aRecipient, aMessage);
       
   103     //LOG_NODE_INFO(KMbufGobblerFlowSubTag, KNodeName, *this); does not compile as flow inheritance is different to other nodes
       
   104     CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
       
   105 
       
   106 	// Dispatch the message locally
       
   107 	if (ESock::TCFDataClient::ERealmId == aMessage.MessageId().Realm())
       
   108 		{
       
   109 		switch (aMessage.MessageId().MessageId())
       
   110 			{
       
   111 
       
   112 			case ESock::TCFDataClient::TStart::EId :
       
   113 				{
       
   114 				iSubConnectionProvider.RNodeInterface::PostMessage(
       
   115 					Id(),
       
   116 					ESock::TCFDataClient::TStarted().CRef()
       
   117 					);
       
   118 				}
       
   119 				break;
       
   120 
       
   121 			case ESock::TCFDataClient::TStop::EId :
       
   122 				{
       
   123 				TInt i;
       
   124 				for (i=iBinders.Count()-1;i>=0;--i)
       
   125 					{
       
   126 				    CMbufGobblerBinder* mbufGobblerBinder = iBinders[i];
       
   127 				    mbufGobblerBinder->UnbindFromLowerFlow();
       
   128 					delete mbufGobblerBinder;
       
   129 					iBinders.Remove(i);
       
   130 					}
       
   131 				iSubConnectionProvider.PostMessage(Id(), ESock::TCFDataClient::TStopped(KErrNone).CRef());
       
   132 				}
       
   133 				break;
       
   134 
       
   135 			case ESock::TCFDataClient::TProvisionConfig::EId :
       
   136 				{
       
   137 				ESock::TCFDataClient::TProvisionConfig& aMess = Messages::message_cast<ESock::TCFDataClient::TProvisionConfig>(aMessage);
       
   138 				iAccessPointConfig.Close();
       
   139 				iAccessPointConfig.Open(aMess.iConfig);
       
   140 				}
       
   141 				break;
       
   142 
       
   143 			case ESock::TCFDataClient::TBindTo::EId :
       
   144 				{
       
   145 				ESock::TCFDataClient::TBindTo& bindToReq = Messages::message_cast<ESock::TCFDataClient::TBindTo>(aMessage);
       
   146 				if (bindToReq.iNodeId == Messages::TNodeId::NullId())
       
   147 					{
       
   148 					User::Leave(KErrNotSupported);
       
   149 					}
       
   150 
       
   151 				const Messages::TNodeId& commsId = bindToReq.iNodeId;
       
   152 				CSubConnectionFlowBase* lowerFlow = Messages::mnode_cast<CSubConnectionFlowBase>(&commsId.Node());
       
   153 
       
   154 				MFlowBinderControl* lowerBinderControl = lowerFlow->GetBinderControlL();
       
   155 				ASSERT(lowerBinderControl);
       
   156 
       
   157 				TInt i;
       
   158 				for (i=0;i<iBinders.Count();++i)
       
   159 					{
       
   160 					// binder for each protocol will request binder for same protocol from lower binder controller using this fn.
       
   161 					iBinders[i]->BindToLowerFlowL(*lowerBinderControl);
       
   162 					}
       
   163 				ASSERT(i); // there should be some binders!
       
   164 
       
   165 				Messages::RClientInterface::OpenPostMessageClose(
       
   166 					Id(),
       
   167 					aSender,
       
   168 					ESock::TCFDataClient::TBindToComplete().CRef()
       
   169 					);
       
   170 				}
       
   171 				break;
       
   172 
       
   173 			default:
       
   174 				ASSERT(EFalse);
       
   175 			}
       
   176 		}
       
   177 	else if (Messages::TEChild::ERealmId == aMessage.MessageId().Realm())
       
   178 		{
       
   179 		switch (aMessage.MessageId().MessageId())
       
   180 			{
       
   181 			case Messages::TEChild::TDestroy::EId :
       
   182 				{
       
   183 				TInt i;
       
   184 				for (i=0;i<iBinders.Count();++i)
       
   185 					{
       
   186 					// ensure all binders unbound
       
   187 					if (iBinders[i]->InUse())
       
   188 						{
       
   189 						//__CFLOG_0(KLogTag1, KLogTag2,_L("something is sending TDestroy to CMbufGobblerFlow before unbinding."));
       
   190 						User::Panic(KPanicCategory,KPanic_DestroyReceivedBeforeUnbind);
       
   191 						}
       
   192 						
       
   193 					// EXAMPLE CODE: cancel requests here if necessary...
       
   194 					//iBinders[i]->Cancel();
       
   195 					
       
   196 					}
       
   197 				if (i==iBinders.Count()) // all unbound
       
   198 					{
       
   199 					DeleteThisFlow();
       
   200 					}
       
   201 				}
       
   202 				break;
       
   203 
       
   204 			default:
       
   205 				ASSERT(EFalse);
       
   206 			}
       
   207 		}
       
   208 	// realm != TCFMessage::ERealmId
       
   209 	else
       
   210 		{
       
   211 		ASSERT(EFalse);
       
   212 		}
       
   213     }
       
   214 
       
   215 
       
   216 ///////////////////////////////////////
       
   217 // Methods from MFlowBinderControl:  //
       
   218 ///////////////////////////////////////
       
   219 
       
   220 ESock::MLowerControl* CMbufGobblerFlow::GetControlL(const TDesC8& aProtocol)
       
   221 /**
       
   222 Create and return an MLowerControl instance of the specified binder type.
       
   223 
       
   224 Called from upper layer during binding procedure.
       
   225 
       
   226 @param aProtocol Protocol type of the binder
       
   227 @return MLowerControl instance of the protocol type
       
   228 */
       
   229 	{
       
   230 	ESock::MLowerControl* lowerControl = FindOrCreateBinderL(aProtocol);
       
   231 	ASSERT(lowerControl);
       
   232 	return lowerControl;		
       
   233 	}
       
   234 
       
   235 
       
   236 ESock::MLowerDataSender* CMbufGobblerFlow::BindL(const TDesC8& aProtocol, ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl)
       
   237 	{
       
   238 	CMbufGobblerBinder* binder = FindOrCreateBinderL(aProtocol);
       
   239 	ASSERT(binder);
       
   240 	binder->BindToUpperL( *aReceiver, *aControl );
       
   241 
       
   242 	iSubConnectionProvider.RNodeInterface::PostMessage(
       
   243 		Id(),
       
   244 		ESock::TCFControlProvider::TActive().CRef()
       
   245 		);
       
   246 
       
   247 	return binder;
       
   248 	}
       
   249 
       
   250 void CMbufGobblerFlow::Unbind( ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl)
       
   251 	{
       
   252 	ASSERT(aReceiver);
       
   253 	ASSERT(aControl);
       
   254 	TInt i;
       
   255 	TInt numberUnbound=0;
       
   256 	for (i=0;i<iBinders.Count();++i)
       
   257 		{
       
   258 		numberUnbound += (iBinders[i]->UnbindFromUpper(*aReceiver,*aControl) ? 1 : 0);
       
   259 		}
       
   260 	ASSERT(i); // there should be some binders!
       
   261 	ASSERT(numberUnbound<=1); // only 1 unbind should have happened
       
   262 
       
   263 	iSubConnectionProvider.RNodeInterface::PostMessage(
       
   264 		Id(),
       
   265 		ESock::TCFControlProvider::TIdle().CRef()
       
   266 		);
       
   267 	}
       
   268 
       
   269 ESock::CSubConnectionFlowBase* CMbufGobblerFlow::Flow()
       
   270 	{
       
   271 	return this;
       
   272 	}
       
   273 
       
   274 
       
   275 /////////////////
       
   276 // Own methods //
       
   277 /////////////////
       
   278 
       
   279 CMbufGobblerBinder* CMbufGobblerFlow::FindOrCreateBinderL(const TDesC8& aProtocol)
       
   280 	{
       
   281 	
       
   282 	// EXAMPLE CODE: perhaps you only want this protocol to work with IPv4
       
   283 	//if (aProtocol.Compare(KIp4ProtocolName))
       
   284 	//	{  // only work with IPv4
       
   285 	//	User::Leave(KErrNotSupported);
       
   286 	//	}
       
   287 
       
   288 	for (TInt i=0;i<iBinders.Count();++i)
       
   289 		{
       
   290 		if(iBinders[i]->ProtocolName() == aProtocol)
       
   291 			{
       
   292 			return iBinders[i];
       
   293 			}
       
   294 		}
       
   295 	// not found.. create it.
       
   296 	CMbufGobblerBinder* newBinder = CMbufGobblerBinder::NewL(aProtocol);
       
   297 	CleanupStack::PushL(newBinder);
       
   298 	iBinders.AppendL(newBinder);
       
   299 	CleanupStack::Pop(newBinder);
       
   300 	return newBinder;
       
   301 	}
       
   302 	
       
   303     
       
   304 
       
   305 	
       
   306 
       
   307 //##################################################################################################
       
   308 	
       
   309 /////////////////////////////
       
   310 // class CMbufGobblerBinder  //
       
   311 /////////////////////////////
       
   312 
       
   313 
       
   314 ////////////////////
       
   315 // My constructor //
       
   316 ////////////////////
       
   317 
       
   318 CMbufGobblerBinder::CMbufGobblerBinder(const TDesC8& aProtocolName):
       
   319 	iLowerControl(NULL),
       
   320 	iLowerDataSender(NULL),
       
   321 	iUpperControl(NULL),
       
   322 	iUpperDataReceiver(NULL),
       
   323 	iProtocolName(aProtocolName)
       
   324 	{}
       
   325 
       
   326 CMbufGobblerBinder* CMbufGobblerBinder::NewL(const TDesC8& aProtocolName)
       
   327 	{
       
   328 	CMbufGobblerBinder* inst = new(ELeave) CMbufGobblerBinder(aProtocolName);
       
   329 	CleanupStack::PushL(inst);
       
   330 	inst->ConstructL();
       
   331 	CleanupStack::Pop(inst);
       
   332 	return inst;
       
   333 	}
       
   334 
       
   335 void CMbufGobblerBinder::ConstructL()
       
   336 	{
       
   337 	MBUFGOBBLER_TEST_DATA_INIT
       
   338 #if 0
       
   339 	// EXAMPLE CODE - set up everything you need to in this method.
       
   340 	//  Perhaps you have some kind of test control interface using pub/sub.. if so you'd do something like below..
       
   341 	//   Diff this file with networking/netperf/delaymeterproto/src/delaymeterflow.cpp for a full working implementation of such a control interface...
       
   342 	CActiveScheduler::Add(this);
       
   343 	DefinePubSubKeysL();
       
   344 	// watch for incoming commands
       
   345 	User::LeaveIfError(iProperty.Attach(TUid::Uid(KDelayMeterControlLevel), KCommandToDelayMeter));
       
   346 	iProperty.Subscribe(iStatus);
       
   347 	SetActive();
       
   348 #endif	
       
   349 	}
       
   350 
       
   351 /*virtual*/
       
   352 CMbufGobblerBinder::~CMbufGobblerBinder()
       
   353 	{
       
   354 	}
       
   355 
       
   356 
       
   357 
       
   358 ////////////////////////////////////////
       
   359 // Methods from ESock::MLowerControl: //
       
   360 ////////////////////////////////////////
       
   361 
       
   362 TInt CMbufGobblerBinder::GetName(TDes& aName)
       
   363 	{
       
   364 	TBuf16<10> tmp;
       
   365 	tmp.Copy(ProtocolName());
       
   366 	aName.Format(_L("mbufgobbler[%S][0x%08x]"), &tmp, this);
       
   367 	
       
   368 	return KErrNone;
       
   369 	}
       
   370 
       
   371 TInt CMbufGobblerBinder::BlockFlow(TBlockOption aOption)
       
   372 	{
       
   373 	if (iLowerControl==NULL)
       
   374 		{
       
   375 		return KErrNotReady;
       
   376 		}
       
   377 	return iLowerControl->BlockFlow(aOption) ;
       
   378 	}
       
   379 
       
   380 TInt CMbufGobblerBinder::GetConfig(TBinderConfig& aConfig)
       
   381 	{
       
   382 	if (iLowerControl==NULL)
       
   383 		{
       
   384 		return KErrNotReady;
       
   385 		}
       
   386 	return iLowerControl->GetConfig(aConfig) ;
       
   387 	}
       
   388 
       
   389 TInt CMbufGobblerBinder::Control(TUint aLevel, TUint aName, TDes8& aOption)
       
   390 	{
       
   391 	// Pass it on..
       
   392 	if (iLowerControl==NULL)
       
   393 		{
       
   394 		return KErrNotReady;
       
   395 		}
       
   396 	return iLowerControl->Control(aLevel,aName,aOption);
       
   397 	}
       
   398 	
       
   399 
       
   400 ///////////////////////////////////////////
       
   401 // Methods from ESock::MLowerDataSender: //
       
   402 ///////////////////////////////////////////
       
   403 
       
   404 ESock::MLowerDataSender::TSendResult CMbufGobblerBinder::Send(RMBufChain& aData)
       
   405 	{
       
   406 	// EXAMPLE NOTE:
       
   407 	//  This is where your protocol will do its work on outgoing data.
       
   408 
       
   409     MBUFGOBBLER_TEST_POINT(KBinderSend,KErrNone)
       
   410 
       
   411 	if (iLowerControl==NULL)
       
   412 		{
       
   413 		return ESendBlocked; // returning this obliges us to send an unblock later..
       
   414 								// so perhaps it'd be better to just swallow the packet?
       
   415 		}
       
   416 	return iLowerDataSender->Send(aData);
       
   417 	}
       
   418 
       
   419 
       
   420 ////////////////////////////////////////
       
   421 // Methods from ESock::MUpperControl: //
       
   422 ////////////////////////////////////////
       
   423 
       
   424 /*virtual*/
       
   425 void CMbufGobblerBinder::StartSending()
       
   426 	{
       
   427 	if (iUpperControl)
       
   428 		{
       
   429 		iUpperControl->StartSending();
       
   430 		}
       
   431 	else
       
   432 		{
       
   433 		ASSERT(1); // to allow setting a breakpoint
       
   434 		//__CFLOG_0(KLogTag1, KLogTag2,_L("CMbufGobblerBinder::StartSending: upper control not yet known!"));
       
   435 		}
       
   436 	}
       
   437 
       
   438 /*virtual*/
       
   439 void CMbufGobblerBinder::Error(TInt anError)
       
   440 	{
       
   441 	if (iUpperControl)
       
   442 		{
       
   443 		iUpperControl->Error(anError);
       
   444 		}
       
   445 	else
       
   446 		{
       
   447 		ASSERT(1); // to set a breakpoint
       
   448 		//__CFLOG_0(KLogTag1, KLogTag2,_L("CMbufGobblerBinder::Error: upper control not yet known!"));
       
   449 		}
       
   450 	}
       
   451 
       
   452 
       
   453 /////////////////////////////////////////////
       
   454 // Methods from ESock::MUpperDataReceiver: //
       
   455 /////////////////////////////////////////////
       
   456 
       
   457 /*virtual*/
       
   458 void CMbufGobblerBinder::Process(RMBufChain& aData)
       
   459 	{
       
   460 	// EXAMPLE NOTE:
       
   461 	//  This is where your protocol will do its work on incoming data.
       
   462 
       
   463     MBUFGOBBLER_TEST_POINT(KBinderReceive,KErrNone)
       
   464 
       
   465 	if (iUpperDataReceiver == NULL)
       
   466 		{
       
   467 		// Why is the guy below still sending data to me when I'm not bound above?
       
   468 		//   Try to ignore it
       
   469 		ASSERT(1); // so a breakpoint can be set if necessary
       
   470 		//__CFLOG_0(KLogTag1, KLogTag2,_L("CMbufGobblerBinder::Process: incoming traffic discarded as upper data receiver not (or no longer) set"));
       
   471 		return;
       
   472 		}
       
   473 	iUpperDataReceiver->Process(aData);
       
   474 	}
       
   475 
       
   476 
       
   477 //////////////////////////
       
   478 // and my own methods.. //
       
   479 //////////////////////////
       
   480 
       
   481 // called by layer above calling my flow's BindL
       
   482 void CMbufGobblerBinder::BindToUpperL(MUpperDataReceiver& aUpperDataReceiver, MUpperControl& aUpperControl)
       
   483 	{
       
   484 	if(iUpperDataReceiver || iUpperControl) {User::Leave(KErrInUse);}
       
   485 	iUpperDataReceiver=&aUpperDataReceiver;
       
   486 	iUpperControl=&aUpperControl;
       
   487     MBUFGOBBLER_TEST_POINT(KBind,KErrNone)
       
   488 	}
       
   489 
       
   490 // called by layer above calling my flow's Unbind. Returns ETrue if unbind happened here, EFalse otherwise
       
   491 TBool CMbufGobblerBinder::UnbindFromUpper(MUpperDataReceiver& aUpperDataReceiver, MUpperControl& aUpperControl)
       
   492 	{
       
   493 	if(&aUpperDataReceiver == iUpperDataReceiver && &aUpperControl == iUpperControl)
       
   494 		{
       
   495 		iUpperDataReceiver=0;
       
   496 		iUpperControl=0;
       
   497 		return ETrue;
       
   498 		}
       
   499 	return EFalse;
       
   500 	}
       
   501 
       
   502 // called by my flow receiving a BinderRequest
       
   503 void CMbufGobblerBinder::BindToLowerFlowL(ESock::MFlowBinderControl& aLowerBinderControl)
       
   504 	{
       
   505 //	__CFLOG_0(KLogTag1, KLogTag2, _L("CMbufGobblerBinder::BindToLowerFlowL")); 
       
   506 	if(iLowerControl || iLowerDataSender)
       
   507 		{
       
   508 		User::Leave(KErrInUse);
       
   509 		}
       
   510 	
       
   511 	iBinderControl = &aLowerBinderControl;
       
   512 	iLowerControl = aLowerBinderControl.GetControlL(ProtocolName());
       
   513 	iLowerDataSender = aLowerBinderControl.BindL(ProtocolName(), this, this);
       
   514 	}
       
   515 
       
   516 void CMbufGobblerBinder::UnbindFromLowerFlow()
       
   517     {
       
   518     if (!iBinderControl)
       
   519         return;
       
   520     
       
   521     iBinderControl->Unbind(this, this);
       
   522     iBinderControl = NULL;
       
   523 
       
   524     iLowerControl = NULL;
       
   525     iLowerDataSender = NULL;
       
   526     }
       
   527 
       
   528 const TDesC8& CMbufGobblerBinder::ProtocolName() const
       
   529 	{
       
   530 	return iProtocolName;
       
   531 	}
       
   532 
       
   533 CMBufGobbler::CMBufGobbler():
       
   534     CActive(CActive::EPriorityStandard)
       
   535     {
       
   536     }   
       
   537     
       
   538 CMBufGobbler* CMBufGobbler::NewL()
       
   539     {
       
   540     CMBufGobbler* inst = new(ELeave) CMBufGobbler;
       
   541     CleanupStack::PushL(inst);
       
   542     inst->ConstructL();
       
   543     CleanupStack::Pop(inst);
       
   544     return inst;
       
   545     }
       
   546 
       
   547 void CMBufGobbler::ConstructL()
       
   548     {
       
   549     iChain.AllocL(128);
       
   550     
       
   551     CActiveScheduler::Add(this);
       
   552 
       
   553     TInt result = RProperty::Define(TUid::Uid(EMBufGobbler), EAdjustNumberOfMBufsRemainingInPool, RProperty::EInt);
       
   554     // Only want 1 instance of a MBufGobbler Layer, so just leave if KErrAlreadyExists returned
       
   555     User::LeaveIfError(result);
       
   556 
       
   557     // watch for incoming commands
       
   558     User::LeaveIfError(iProperty.Attach(TUid::Uid(EMBufGobbler), EAdjustNumberOfMBufsRemainingInPool));
       
   559 
       
   560     iProperty.Subscribe(iStatus);
       
   561     SetActive();
       
   562     }
       
   563 
       
   564 /*virtual*/ CMBufGobbler::~CMBufGobbler()
       
   565     {
       
   566     if (IsActive())
       
   567         {
       
   568         Cancel();   
       
   569         }
       
   570 
       
   571     iChain.Free();
       
   572     
       
   573     TInt result = RProperty::Delete(TUid::Uid(EMBufGobbler), EAdjustNumberOfMBufsRemainingInPool);  
       
   574     if (result != KErrNone)
       
   575         {
       
   576         RDebug::Print(_L("CMBufGobbler::~CMBufGobbler() %d"), result);
       
   577         }
       
   578     }
       
   579 
       
   580 /*virtual*/ void CMBufGobbler::DoCancel()
       
   581     {
       
   582     iProperty.Cancel();
       
   583     }
       
   584 
       
   585 /*virtual*/ void CMBufGobbler::RunL()
       
   586     {
       
   587     // Resubscribe to ensure that next pub/sub notification is picked up
       
   588     iProperty.Subscribe(iStatus);
       
   589     SetActive();
       
   590     
       
   591     TInt request=EGobbleAllMBufs;
       
   592     TInt pubSubRet = iProperty.Get(request);
       
   593     if (pubSubRet == KErrNone)
       
   594         {
       
   595         switch(request)
       
   596             {
       
   597             case EGobbleAllMBufs:
       
   598                 {
       
   599                 RMBufAllocator allocator;
       
   600                 RMBufChain chain;
       
   601                 TInt size = allocator.NextMBufSize(0);
       
   602                 while (size != KErrNotFound)
       
   603                     {
       
   604                     TInt ret = KErrNone;
       
   605                     while (ret == KErrNone)
       
   606                         {
       
   607                         ret = chain.Alloc(size);
       
   608                         if (ret==KErrNone )
       
   609                             {
       
   610                             iChain.Append(chain);
       
   611                             }
       
   612                         }
       
   613                     size = allocator.NextMBufSize(size);
       
   614                     }
       
   615                 TInt length = iChain.Length();
       
   616                 RDebug::Print(_L("Out of MBuf Memory... Total MBuf memory in use %d"), length);
       
   617                 TInt numBufs = iChain.NumBufs();
       
   618                 RDebug::Print(_L("Out of MBuf Memory... Total MBufs in use %d"), numBufs);
       
   619                 break;
       
   620                 }
       
   621             case EReleaseAllMBufs:
       
   622                 {
       
   623                 if(!iChain.IsEmpty())
       
   624                      {
       
   625                      iChain.Free();
       
   626                      ASSERT(!iChain.Length());
       
   627                     }
       
   628                 break;
       
   629                 }
       
   630             case EReleaseASingleMBuf:
       
   631                 {            
       
   632                 TInt length = iChain.Length();
       
   633                 if (length != 0)
       
   634                     {
       
   635                     TInt trimOffset = length - iChain.Last()->Size();
       
   636                     iChain.TrimEnd(trimOffset);
       
   637                     }
       
   638     
       
   639                 length = iChain.Length();
       
   640                 RDebug::Print(_L("MBufMemory De-Allocated... Total MBuf memory in use %d"), length);
       
   641                 break;
       
   642                 }
       
   643             default:
       
   644                 {
       
   645                 RDebug::Print(_L("CMBufGobbler::RunL(), invalid request %d"), request);
       
   646                 break;
       
   647                 }
       
   648             }
       
   649         }
       
   650     else
       
   651         {
       
   652         RDebug::Print(_L("Attempt to process MBufGobbler publish/subscribe failed with value for  %d"), pubSubRet);
       
   653         }
       
   654     }
       
   655 
       
   656 
       
   657 	
       
   658 	
       
   659