commsfwsupport/commselements/commsfw/src/cfutil.cpp
changeset 0 dfb7c4ff071f
child 24 51722b10598b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwsupport/commselements/commsfw/src/cfutil.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,627 @@
+// Copyright (c) 2003-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:
+//
+
+#include <cfutil.h>
+#include <cfextras.h>
+#include <elements/cfmacro.h>
+#include <cflog.h>
+#include <cfforwardmsg.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_ElemCommsFwcftl, "ElemCommsFwcftl.");
+#endif
+
+using namespace CommsFW;
+
+EXPORT_C TInt CCFModuleChannelHandler::Send(const CommsFW::TCFMessage &aMessage)
+/** Send a message on the outgoing channel, blocks until the message has been sent.
+The rootserver is expected to run at high priority and retrieve pending messages
+quickly, also this exchange usually only happens at module startup and shutdown so
+it can usually be considered safe to block here.
+@param aMessage Message to send on the outgoing channel.
+@publishedPartner
+@released
+*/
+    {
+	TRequestStatus status;
+	iChannelPair.NotifySpaceAvailable(status);
+	User::WaitForRequest(status);
+	return iChannelPair.Send(aMessage);
+    }
+
+EXPORT_C CCFModuleChannelHandler::~CCFModuleChannelHandler()
+/** D'tor. Dequeues this instance from the active scheduler.
+@publishedPartner
+@released
+*/
+    {
+	Cancel();
+    }
+
+EXPORT_C CCFModuleChannelHandler::CCFModuleChannelHandler(TInt aPriority):CActive(aPriority)
+/** C'tor. Initialise the parent CActive.
+@publishedPartner
+@released
+*/
+    {
+	// Do nothing
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::CFMessageDiscover(const CommsFW::TCFDiscoverMsg& aMessage)
+/** Default implementation of the TCFDiscoverMsg message. It will send a response indicating 
+there is no sub-modules in this module. Should be overridden if sub-modules are present in the module.
+@param aMessage The Discovery message which has been received from the Rootserver.
+@publishedPartner
+@released
+*/
+    {
+	// Default is no submodules, so we just return KErrNone
+	TCFDiscoverRespMsg resp(aMessage.Identifier(), KErrNone, EFalse);
+	TInt err = Send(resp);
+	if(KErrNone != err)
+		{
+		__CFLOG_1(KLogCommsFw, KLogWarning, _L8("CCFModuleChannelHandler::CFMessageDiscover(): Send returned %d"), err);
+		CFChannelError(err);
+		}
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::CFMessageBind(const CommsFW::TCFBindMsg& aMessage)
+/** Default implementation of the TCFBindMsg message. It will send a response indicating 
+there is no submodules to bind to in this module. Should be overridden if sub-modules are present 
+in the module.
+@param aMessage The Bind message which has been received from the Rootserver.
+@publishedPartner
+@released
+*/
+    {
+	// Default is no submodules, so we just return KErrNotFound
+	TCFBindCompleteMsg resp(aMessage.Identifier(), KErrNotFound);
+	TInt err = Send(resp);
+	if(KErrNone != err)
+		{
+		__CFLOG_1(KLogCommsFw, KLogWarning, _L8("CCFModuleChannelHandler::CFMessageBind(): Send returned %d"), err);
+		CFChannelError(err);
+		}
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::CFMessageUnbind(const CommsFW::TCFUnbindMsg& aMessage)
+/** Default implementation of the TCFUnbindMsg message. It will send a response indicating 
+there is no submodules to unbind from in this module. Should be overridden if sub-modules are present 
+in the module.
+@param aMessage The Unbind message which has been received from the Rootserver.
+@publishedPartner
+@released
+*/
+    {
+	// Default is no submodules, so we just return KErrNotFound
+	TCFUnbindCompleteMsg resp(aMessage.Identifier(), KErrNotFound);
+	TInt err = Send(resp);
+	if(KErrNone != err)
+		{
+		__CFLOG_1(KLogCommsFw, KLogWarning, _L8("CCFModuleChannelHandler::CFMessageUnbind(): Send returned %d"), err);
+		CFChannelError(err);
+		}
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::CFMessageShutdown(const CommsFW::TCFShutdownMsg& aMessage)
+/** Default implementation of the TCFShutdownMsg message. it will do nothing. Should be overridden 
+if the module supports Shutdown.
+@param aMessage The Shutdown message which has been received from the Rootserver.
+@publishedPartner
+@released
+*/
+    {
+	(void) aMessage; // Avoid compiler warnings
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::CFMessageForward(const CommsFW::TCFForwardMsg& aMessage)
+/** Default implementation of the CFMessageForward message. it will do nothing. Should be overridden 
+if the module supports Message Forwarding.
+@param aMessage The Forward message which has been received from the Rootserver.
+@publishedPartner
+@released
+*/
+    {
+    aMessage.Msg().Complete( KErrNotSupported );
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::CFMessageUnknown(const CommsFW::TCFMessage& aMessage)
+/** Default implementation for handling unknown messages. it will do nothing. Should be overridden 
+if the module wants to implement some handling for receiving unknown messages.
+@param aMessage The message which has been received from the Rootserver.
+@publishedPartner
+@released
+*/
+    {
+	(void) aMessage; // Avoid compiler warnings
+    }
+
+EXPORT_C void CCFModuleChannelHandler::ConstructL(CommsFW::RCFChannel::TMsgQueues &aRxQueues, CommsFW::RCFChannel::TMsgQueues &aTxQueues)
+/** Second level constructor, must be called from derived implementations or the module 
+will PANIC when attempting to use the channels.
+@param aRxQueues Queues on which to listen for incoming messages.
+@param aTxQueues Queues on which to send outgoing messages.
+@publishedPartner
+@released
+*/
+    {
+	TInt ret;
+	if((ret = iChannelPair.CreateRecv(aRxQueues)) != KErrNone ||
+	   (ret = iChannelPair.CreateSend(aTxQueues)) != KErrNone)
+		{
+		User::Leave(ret);
+		}
+	CActiveScheduler::Add(this);
+	SetActive();
+	iChannelPair.NotifyDataAvailable(*this);
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::DoCancel()
+/** Cancel function, will be called during destruction. Closes the channels contained.
+@internalComponent
+*/
+    {
+ 	iChannelPair.CancelDataAvailable();
+ 	iChannelPair.CloseNonGracefully();
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::CFChannelError(TInt aError)
+/** Called when errors are encountered on using the channels. Does nothing but
+creating a log entry for [CommsFw,Warning]. Should be overridden if the module
+wants to supports handling of errors.
+@param aError The errorcode.
+@publishedPartner
+@released
+*/
+    {
+	// Do nothing is default, maybe instead we should panic?
+	(void) aError;
+	__CFLOG_1(KLogCommsFw, KLogWarning, _L8("ERROR CCFModuleChannelHandler::CFChannelError(%d)!"), aError);
+    }
+
+EXPORT_C /*virtual*/ void CCFModuleChannelHandler::RunL()
+/** Receive a message and register for listening for more data on the incoming channel.
+wants to supports handling of errors.
+@internalComponent
+*/
+    {
+	if (iStatus != KErrNone)
+		{
+		__CFLOG_1(KLogCommsFw, KLogWarning, _L8("CCFModuleChannelHandler::RunL(): NotifyDataAvailable returned %d"), iStatus.Int());
+		CFChannelError(iStatus.Int());
+		return;
+		}
+	
+	// No error. Take the message from the channel.
+	TCFMessage msg;
+	TInt err(iChannelPair.Receive(msg));
+	if (KErrNone != err)
+		{
+		__CFLOG_1(KLogCommsFw, KLogWarning, _L8("CCFModuleChannelHandler::RunL(): Receive returned %d"), iStatus.Int());
+		CFChannelError(err);
+		return;
+		}
+
+	switch (msg.Code())
+		{
+		case TCFCommsMessage::ECodeDiscover:
+		CFMessageDiscover(reinterpret_cast<const TCFDiscoverMsg&>(msg));
+		break;
+		
+		case TCFCommsMessage::ECodeBind:
+		CFMessageBind(reinterpret_cast<const TCFBindMsg&>(msg));
+		break;
+		
+		case TCFCommsMessage::ECodeUnbind:
+		CFMessageUnbind(reinterpret_cast<const TCFUnbindMsg&>(msg));
+		break;
+		
+		case TCFCommsMessage::ECodeShutdown:
+		CFMessageShutdown(reinterpret_cast<const TCFShutdownMsg&>(msg));
+		break;
+
+		case TCFCommsMessage::ECodeForward:
+		CFMessageForward(reinterpret_cast<const TCFForwardMsg&>(msg));
+		break;
+
+		default:
+		CFMessageUnknown(msg);
+		break;
+		}
+
+	//Pend again
+	SetActive();
+	iChannelPair.NotifyDataAvailable(*this);
+	}
+
+
+EXPORT_C TBool CommsFW::GetVarFromIniData(const TDesC8& aIniData, const TDesC8& aSection, const TDesC8& aVarName, TPtrC8& aResult)
+/** Find a variable's value given a section name and a var name.
+@param aSection The section to search.
+@param aVarName The name to find.
+@param aResult The value.
+@return Success or fail.
+*/
+	{
+	__ASSERT_DEBUG(aSection.Length() <= KMaxIniDataSectionNameLength, User::Panic(KSpecAssert_ElemCommsFwcftl, 1));
+	__ASSERT_DEBUG(aVarName.Length() <= KMaxIniDataSectionNameLength, User::Panic(KSpecAssert_ElemCommsFwcftl, 2));
+
+	TBuf8<KMaxIniDataSectionNameLength + 2> sectionToken;			// 2 extra chars for [sectionName]
+	TInt sectionStart = 0;
+	TInt sectionLen = 0;	// reassure compiler
+	TPtrC8 section;
+	// Sections are optional
+	if(aSection.Length() > 0)
+		{
+		_LIT8(KSectionTokenString,"[%S]");
+		sectionToken.Format(KSectionTokenString,&aSection);
+#ifdef SYMBIAN_NETWORKING_CFTRANSPORT
+		sectionStart = aIniData.FindF(sectionToken);
+#else
+		sectionStart = aIniData.Find(sectionToken);
+#endif
+		if (sectionStart == KErrNotFound)
+			return EFalse;
+		section.Set(aIniData.Mid(sectionStart));
+#ifdef SYMBIAN_NETWORKING_CFTRANSPORT
+		sectionStart += section.FindF(TPtrC8(_S8("]")));
+#else
+		sectionStart += section.Find(TPtrC8(_S8("]")));
+#endif
+		if (sectionStart == KErrNotFound)
+			return EFalse;
+		sectionStart++;
+		section.Set(aIniData.Mid(sectionStart));
+		
+#ifdef SYMBIAN_NETWORKING_CFTRANSPORT
+		sectionLen = section.FindF(TPtrC8(_S8("[")));
+#else
+		sectionLen = section.Find(TPtrC8(_S8("[")));
+#endif
+		if (sectionLen == KErrNotFound)
+			sectionLen = section.Length();
+		}
+	else
+		{
+		sectionLen = aIniData.Length();
+		}
+	TInt pos = 0;
+	FOREVER
+		{
+		section.Set(aIniData.Mid(sectionStart, sectionLen));
+#ifdef SYMBIAN_NETWORKING_CFTRANSPORT
+		pos = section.FindF(aVarName);
+#else
+		pos = section.Find(aVarName);
+#endif
+		if (pos==KErrNotFound)
+			return EFalse;
+		// Check that the token is at the start of the line, to avoid finding
+		// substrings or commented statements). If it isn't then continue
+		// searching from that point
+		TUint8 precedingChar;
+		if (pos == 0 ||
+			(precedingChar = section[pos - 1]) == '\n' ||
+			precedingChar == '\r')
+			{
+			break;
+			}
+		sectionStart += (pos + 1);
+		sectionLen -= (pos + 1);
+		}
+
+	section.Set(section.Mid(pos));
+    // Found token - now find position of '='
+	pos = section.Locate('=');
+	if((KErrNotFound==pos) || ((pos+1)==section.Length()))
+		{
+		return EFalse;
+		}
+
+	// Shrink section to start after'='
+	TLex8 lex(section.Mid(++pos));
+	section.Set(section.Mid(pos));
+//	sectionStart+=pos;
+
+	// Set length of section to be to end of line or end of file
+	TInt length=section.Locate('\r');
+	if(length==KErrNotFound)
+		{
+		(void)lex.NextToken();
+		length=lex.MarkedToken().Length();
+		}
+	aResult.Set(section.Ptr(), length);
+	return(ETrue);
+	}
+
+//@TODO - why Configurator can't move to using same?
+EXPORT_C TBool CommsFW::GetVarFromIniData(const TDesC8& aIniData, const TDesC8 &aSection, const TDesC8 &aVarName, TInt &aResult)
+	{
+	TPtrC8 ptr;
+	if (CommsFW::GetVarFromIniData(aIniData, aSection, aVarName, ptr))
+		{
+		TUint32 result;
+		if (CommsFW::ConvertVal(ptr, result)==KErrNone)
+			{
+			aResult = result;
+			return(ETrue);
+			}
+		}
+	return(EFalse);
+	}
+
+//
+// COwnEntryList
+//
+
+EXPORT_C COwnEntryList::TOwnEntry::TOwnEntry(const TParse& aPath, const TEntry& aEntry)
+	{
+	TPtr fullName(iName.Des());
+	fullName.Copy(aPath.DriveAndPath());
+	fullName.Append(aEntry.iName);
+	}
+
+EXPORT_C COwnEntryList::COwnEntryList(TInt aGranularity)
+: iArray(aGranularity)
+	{
+	}
+
+EXPORT_C COwnEntryList::~COwnEntryList()
+	{
+	iArray.Close();
+	}
+
+/*
+EXPORT_C COwnEntryList* COwnEntryList::NewL(TInt aGranularity)
+	{
+	COwnEntryList* self = new(ELeave) COwnEntryList(aGranularity);
+	CleanupStack::PushL(self);
+	if(aDir)
+		{
+		self->AddL(*aDir);
+		}
+	CleanupStack::Pop(self);
+	return self;
+	}
+*/
+
+EXPORT_C TInt COwnEntryList::Count() const
+	{
+	return iArray.Count();
+	}
+
+EXPORT_C const COwnEntryList::TOwnEntry& COwnEntryList::operator[](TInt anIndex) const
+	{
+	return iArray[anIndex];
+	}
+
+EXPORT_C void COwnEntryList::AddL(const TOwnEntry& aEntry)
+	{
+	User::LeaveIfError(iArray.Append(aEntry));
+	}
+
+EXPORT_C void COwnEntryList::AddL(const COwnEntryList& aDir)
+	{
+	const TInt cnt = aDir.Count();
+	for(TInt i = 0; i < cnt; ++i)
+		{
+		AddL(aDir[i]);
+		}
+	}
+
+EXPORT_C void COwnEntryList::WildScanAcrossDrivesL(const TDesC& aDir, const TDesC& aFileMask)
+	{
+	iArray.Reset();
+	TAutoClose<RFs> fs;
+	User::LeaveIfError(fs.iObj.Connect());
+	fs.PushL();
+	TFindFile ff(fs.iObj);
+	TParse fullEntry;
+	CDir* dir;
+	if(ff.FindWildByDir(aFileMask, aDir, dir) == KErrNone)
+		{
+		do 
+			{
+			const TInt cnt = dir->Count();
+			for(TInt i = 0; i < cnt; ++i)
+				{
+				const TEntry& entry = (*dir)[i];
+				fullEntry.Set(entry.iName, &ff.File(), NULL);      
+				AddL(TOwnEntry(fullEntry, entry));
+				}
+			delete dir;
+			}
+		while(ff.FindWild(dir) == KErrNone);
+		}	
+	fs.Pop();
+	}
+
+EXPORT_C void COwnEntryList::UniqueWildScanAcrossDrivesL(const TDesC& aDir, const TDesC& aFileMask)
+/**
+ * Function is used to scan unique files from drives starting from Y: to A: then last Z:. The scanning 
+ * is done by module name.Files with unique name module name will be scanned.This function is used by Rootserver to 
+ * scan cmi files unique by name.It can be used by other internal components for the similar use.
+ * 
+ * @internalComponent
+ */
+	{
+	iArray.Reset();
+	TAutoClose<RFs> fs;
+	User::LeaveIfError(fs.iObj.Connect());
+	fs.PushL();
+	TFindFile ff(fs.iObj);
+	TParse fullEntry;
+	CDir* dir;
+	RArray<TEntry> files;
+	TBool found;
+	if(ff.FindWildByDir(aFileMask, aDir, dir) == KErrNone)
+		{
+		do 
+			{
+			const TInt cnt = dir->Count();
+			for(TInt i = 0; i < cnt; ++i)
+				{
+				const TEntry& entry = (*dir)[i];
+		               if(files.Count()!=0)
+				      {
+					found = EFalse;
+					for( TInt Index=0;Index<files.Count();Index++)
+			    	           {
+						if(files[Index].iName.CompareF(entry.iName)==0)
+						     {
+							found = ETrue;
+					             }
+				             }
+	                            if(!found)
+	    	                         {
+				    	   files.Append(entry);
+					   fullEntry.Set(entry.iName, &ff.File(), NULL);      
+					   AddL(TOwnEntry(fullEntry, entry));
+				    	     }
+				       }
+		        	else
+			          {
+			           files.Append(entry);
+				    fullEntry.Set(entry.iName, &ff.File(), NULL);      
+				    AddL(TOwnEntry(fullEntry, entry));
+				    }		
+							
+		         }
+		     delete dir;
+			
+	           }
+	           while(ff.FindWild(dir) == KErrNone);
+        	}	
+	files.Close();	
+	fs.Pop();
+	}
+
+//
+// class RCFHeap
+//
+
+#if defined(__CFLOG_ACTIVE) || defined(SYMBIAN_TRACE_ENABLE)
+
+void RCFSharedHeap::WalkFunc(TAny* aContext, TCellType aType, TAny* aBase, TInt /*aSize*/)
+	{
+	(void)aBase;
+	if(aType == EGoodAllocatedCell)
+		{
+		TLogInfo* logInfo = reinterpret_cast<TLogInfo*>(aContext);
+		__CFLOG_VAR((logInfo->iSubSystem, logInfo->iComponent, _L8("  0x%x"), (TUint) aBase + (TUint) RHeap::EAllocCellSize));
+		
+#ifdef SYMBIAN_TRACE_ENABLE
+	TLogTextBuf buf;
+	TBool loggingSuccess = EFalse;
+	if(logInfo->iSubSystem.Length() < KMaxLogTextLength)
+		{
+		buf.Append(logInfo->iSubSystem);
+		_LIT8(KSpace, " ");
+		if(buf.Length() + KSpace().Length() < KMaxLogTextLength)
+			{			
+			buf.Append(KSpace);			
+			if(buf.Length() + logInfo->iComponent.Length() < KMaxLogTextLength)
+				{
+				buf.Append(logInfo->iComponent);
+				if(buf.Length() + KSpace().Length() < KMaxLogTextLength)
+					{			
+					buf.Append(KSpace);	
+					_LIT8(KHexNumberFormat, " 0x%x");
+					buf.AppendFormatIgnoreOverflow(KHexNumberFormat, (TUint) aBase + (TUint) RHeap::EAllocCellSize);
+					loggingSuccess = UTracePfAny(KPrimaryFilter, KText, ETrue, EFalse, 0, buf.Ptr(), buf.Length());	
+					}
+				}	
+			}	
+		}
+		if(loggingSuccess == EFalse) //May happen if buffer length exceeds KMaxLogTextLength due to longer names of logInfo->iSubSystem and/or logInfo->iComponent 
+									 //Atleast the below log helps to identify that there is a leak
+			{
+			_LIT8(KCantLogNames, "??? ??? 0x%x"); //Atleast this should fit
+			buf.Zero();
+			buf.AppendFormatIgnoreOverflow(KCantLogNames, (TUint) aBase + (TUint) RHeap::EAllocCellSize);
+			loggingSuccess = UTracePfAny(KPrimaryFilter, KText, ETrue, EFalse, 0, buf.Ptr(), buf.Length());		
+			}
+#endif //SYMBIAN_TRACE_ENABLE			
+		}
+	}
+
+#endif //defined(__CFLOG_ACTIVE) || defined(SYMBIAN_TRACE_ENABLE)
+
+EXPORT_C TInt RCFSharedHeap::AccessCount() const 
+	{
+	return iAccessCount;
+	}
+
+EXPORT_C void RCFSharedHeap::LogAllocatedCells(const TDesC8& aSubSystem, const TDesC8& aComponent)
+	{
+#if defined(__CFLOG_ACTIVE) || defined(SYMBIAN_TRACE_ENABLE)
+	TLogInfo logInfo(aSubSystem, aComponent);
+	DebugFunction(EWalk, (TAny*)WalkFunc, &logInfo);
+#else
+	(void) aSubSystem;
+	(void) aComponent;
+#endif
+	}
+
+
+//
+// Other utils
+//
+
+namespace CommsFW
+{
+
+EXPORT_C TInt ConvertVal(const TDesC8& aVar, TUint32& aResult)
+	{
+	TPtrC8 ptr(aVar);
+	TRadix radix;
+	_LIT8(KHexPrefix, "0x");
+	if(ptr.Left(2).CompareF(KHexPrefix) == 0)
+		{
+		ptr.Set(ptr.Mid(2));
+		radix = EHex;
+		}
+	else
+		{
+		radix = EDecimal;
+		}
+	TLex8 lex(ptr);
+	TUint32 result;
+	TInt err = lex.Val(result, radix);
+	if (err==KErrNone)
+		{
+		aResult = result;
+		}
+	return err;
+	}
+
+EXPORT_C TInt ConvertVal(const TDesC8& aVar, TUint16& aResult)
+	{
+	TUint32 result = 0xFFFFFFFF;
+	TInt err = ConvertVal(aVar, result);
+	if (err==KErrNone && result<=0xFFFF)
+		{
+		aResult = result;
+		}
+	return err;
+	}
+
+}
+
+