Committing ZeroConf for 10.1 to the FCL.
/*
* Copyright (c) 2010 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 "cmdnscachemap.h"
#include "mdnsrecordinfo.h"
#include <mdns/crdtypesrv.h>
#include <mdns/crdtypea.h>
#include <mdns/crdtypeptr.h>
#include <mdns/crdtypetxt.h>
__FLOG_STMT(_LIT8(KComponent,"MDNSCache");)
CMDNSCacheMap* CMDNSCacheMap::NewL(TUint aMaxCacheEntries)
{
CMDNSCacheMap* self = CMDNSCacheMap::NewLC(aMaxCacheEntries);
CleanupStack::Pop(self);
return self;
}
CMDNSCacheMap* CMDNSCacheMap::NewLC(TUint aMaxCacheEntries)
{
CMDNSCacheMap* self = new (ELeave)CMDNSCacheMap(aMaxCacheEntries);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
void CMDNSCacheMap::ConstructL()
{
__FLOG_OPEN(KMDNSSubsystem, KComponent);
__FLOG(_L8("ConstructL - Entry"));
__FLOG(_L8("ConstructL - Exit"));
}
CMDNSCacheMap::CMDNSCacheMap(TUint aMaxCacheEntries):iCacheEntries(HashInfo::TPtrC8Hash,HashInfo::TPtrC8Ident),iterate(iCacheEntries)
{
iMaxCacheEntries = aMaxCacheEntries;
}
CMDNSCacheMap::~CMDNSCacheMap()
{
__FLOG(_L8("Destructor - Entry"));
RHashMap<TPtrC8,CServiceInfo*>::TIter iter(iCacheEntries);
TInt count(0);
TInt entriesToDelete(iCacheEntries.Count());
for(count=0; count<entriesToDelete; count++)
{
delete *iter.NextValue();
}
iCacheEntries.Close();
__FLOG(_L8("Destructor - Exit"));
__FLOG_CLOSE;
}
TUint32 HashInfo::TPtrC8Hash(const TPtrC8& aPtr)
{
return DefaultHash::Des8(aPtr);
}
TBool HashInfo::TPtrC8Ident(const TPtrC8& aL, const TPtrC8& aR)
{
return DefaultIdentity::Des8(aL, aR);
}
void CMDNSCacheMap::UpdateL(const TDesC8& aName, CServiceInfo* aEntry)
{
__FLOG(_L8("Insert - Entry"));
TTime currentTime;
currentTime.UniversalTime();
aEntry->SetAccessTime(currentTime);
TBool authoritative = aEntry->IsAuthoritative();
//Save the key
aEntry->SetKeyL(aName);
if(NumberOfEntries()<=iMaxCacheEntries)
{
iCacheEntries.InsertL(aEntry->Key(),aEntry);
}
else
{
if(aEntry->IsAuthoritative() && DeleteLeastRecentlyUsed())
{
iCacheEntries.InsertL(aEntry->Key(),aEntry);
}
else
{
delete aEntry;
__FLOG_VA((_L8("--------User::Leave on Insert = %d--------"),KErrNoMemory));
User::Leave(KErrNoMemory);
}
}
__FLOG(_L8("Insert - Exit"));
}
CServiceInfo* CMDNSCacheMap::Find(const TDesC8& aName)
{
TTime currentTime;
RBuf8 key;
key.CreateL(aName);
//All keys are in LowerCase
key.LowerCase();
CServiceInfo** foundEntry = NULL;
foundEntry = iCacheEntries.Find(key);
key.Close();
currentTime.UniversalTime();
if(foundEntry)
{
(*foundEntry)->SetAccessTime(currentTime);
return *foundEntry;
}
return NULL;
}
void CMDNSCacheMap::FindEntries(const TDesC8& aName,RPointerArray <const CServiceInfo> & aEntries)
{
_LIT8(KRegExp,"*");
TInt error;
TBuf8 <256> serviceType(KRegExp);
TTime currentTime;
serviceType.Append(aName);
THashMapIter<TPtrC8,CServiceInfo*> iter(iCacheEntries);
TInt count;
for(count=0; count<iCacheEntries.Count(); count++)
{
TPtrC8 nextKey=*iter.NextKey();
//Match by the regular expression to get all Services by type
error=nextKey.MatchF(serviceType);
if( error != KErrNotFound)
{
CServiceInfo* currentEntry= *iter.CurrentValue();
aEntries.Append(currentEntry);
currentTime.UniversalTime();
currentEntry->SetAccessTime(currentTime);
}
}
}
/*Not Used : Currently*/
void CMDNSCacheMap::AuthoritativeRecordsL(RPointerArray <const CServiceInfo> & aEntries)
{
THashMapIter<TPtrC8,CServiceInfo*> iter(iCacheEntries);
TInt count;
TTime currentTime;
for(count=0; count<iCacheEntries.Count(); count++)
{
CServiceInfo* entry=*iter.NextValue();
if(entry->IsAuthoritative())
{
aEntries.AppendL(entry);
currentTime.UniversalTime();
entry->SetAccessTime(currentTime);
}
}
}
TInt CMDNSCacheMap::DeleteL(const TDesC8& aName)
{
__FLOG(_L8("CMDNSCacheMap::DeleteL - Entry"));
TInt error = KErrNone;
TBuf8 <256> key(aName);
//All keys are in LowerCase
key.LowerCase();
#ifdef __FLOG_ACTIVE
HBufC8* buf(HBufC8::NewLC(aName.Length()));
buf->Des().Copy(aName);
__FLOG_VA((_L8("Deleted Entry = %S "),buf));
CleanupStack::PopAndDestroy(buf);
#endif
CServiceInfo* entryToDelete = NULL;
TRAPD(err,entryToDelete=iCacheEntries.FindL(key));
if(err!=KErrNotFound)
{
error = iCacheEntries.Remove(key);
delete entryToDelete;
__FLOG(_L8("CMDNSCacheMap::DeleteL - Delete Cache Entry Successful"));
__FLOG(_L8("CMDNSCacheMap::DeleteL - Exit"));
}
else
{
__FLOG(_L8("CMDNSCacheMap::DeleteL - Entry not found in Cache"));
}
return error;
}
void CMDNSCacheMap::DeleteAllEntries()
{
THashMapIter<TPtrC8,CServiceInfo*> iter(iCacheEntries);
TInt count;
for(count=0; count<iCacheEntries.Count(); count++)
{
TPtrC8 key=*iter.NextKey();
/*TODO: check if object is properly deleted;
* destructors are called*/
iCacheEntries.Remove(key);
delete *iter.NextValue();
}
}
/* Scenarios:
1. All are authoritative in Cache, authoritative record comes for insertion : No Memory
2. All are authoritative in Cache, non-authoritative comes : No Memory
3. One or more non-authoritative, non-authoritative comes : No Memory
4. All are non-authoritative,authoritative comes, one of the records
based on LRU (not accurate)of which is deleted, but authoritative WILL BE
put into cache
*/
TBool CMDNSCacheMap::DeleteLeastRecentlyUsed()
{
THashMapIter<TPtrC8,CServiceInfo*> iter(iCacheEntries);
TInt count;
TTime accessTime,timeOfLRUEntry;
CServiceInfo* entryToDelete = NULL;
TBuf8<255> keyToDelete;
TBool cacheFull = ETrue;
for(count=0; count<iCacheEntries.Count(); count++)
{
CServiceInfo* nextEntry = *iter.NextValue();
accessTime = nextEntry->LastAccessTime();
if(count==0)
{
timeOfLRUEntry = accessTime;
if(!nextEntry->IsAuthoritative())
{
keyToDelete = *iter.CurrentKey();
entryToDelete = nextEntry;
}
}
else
{
if((accessTime < timeOfLRUEntry) && !nextEntry->IsAuthoritative() )
{
timeOfLRUEntry = accessTime;
keyToDelete = *iter.CurrentKey();
entryToDelete = nextEntry;
}
}
}
TInt error = iCacheEntries.Remove(keyToDelete);
if(error != KErrNone)
{
cacheFull = EFalse;
}
else
{
#ifdef __FLOG_ACTIVE
__FLOG_VA((_L8("Deleting Least Recently Used = %S "),&keyToDelete));
#endif
}
delete entryToDelete;
return cacheFull;
}
TUint32 CMDNSCacheMap::NumberOfEntries()
{
return iCacheEntries.Count();
}
CServiceInfo* CMDNSCacheMap::NextStaleEntry(TBool aActiveCacheMgmtEnabled,TBool aIteratorReset)
{
/*
if(aIteratorReset)
{
iterate.Reset();
}
CServiceInfo* nextEntry=*iterate.NextValue();
if(nextEntry->EntryExpired() || nextEntry->EntryToBeQueried())
{
__FLOG(_L8("Stale Entry Found"));
return nextEntry;
}
return NULL;
*/
THashMapIter<TPtrC8,CServiceInfo*> itr(iCacheEntries);
CServiceInfo*const* nextEntry=itr.NextValue();
while(nextEntry!=NULL)
{
if((*nextEntry)->EntryExpired())
{
__FLOG(_L8("Stale Entry Found"));
return (*nextEntry);
}
nextEntry=itr.NextValue();
}
return NULL;
}
void CMDNSCacheMap::DumpCacheL()
{
RHashMap<TPtrC8,CServiceInfo*>::TIter iter(iCacheEntries);
__FLOG(_L8("!!!!!!!!!!!!!!!!!! BEGIN CACHE DUMP !!!!!!!!!!!!!!!!!!!!!"));
for(TInt count=0; count<iCacheEntries.Count(); count++)
{
CServiceInfo* entry = *iter.NextValue();
__FLOG_VA((_L8("--------------------Begin Entry = %d------------------"),count));
TPtrC8 key(*iter.CurrentKey());
__FLOG_VA((_L8("--------------------Key is = %S------------------"),&key));
if(entry->ServiceRecord())
{
__FLOG(_L8("--------Service-Record Data-----"));
HBufC8* buf(HBufC8::NewLC(entry->ServiceRecord()->Name().Length()));
buf->Des().Copy(entry->ServiceRecord()->Name());
__FLOG_VA((_L8("Service Name = %S "),buf));
HBufC8* target(HBufC8::NewLC(entry->ServiceRecord()->Target().Length()));
target->Des().Copy(entry->ServiceRecord()->Target());
__FLOG_VA((_L8("Target Machine = %S "),target));
__FLOG_VA((_L8("Priority = %d "),entry->ServiceRecord()->Priority()));
__FLOG_VA((_L8("Port = %d "),entry->ServiceRecord()->Port()));
__FLOG_VA((_L8("TTL = %d "),entry->ServiceRecord()->Ttl()));
CleanupStack::PopAndDestroy(target);
CleanupStack::PopAndDestroy(buf);
}
if(entry->AddressRecord())
{
__FLOG(_L8("-------Address-Record Data--------"));
HBufC8* buf(HBufC8::NewLC(entry->AddressRecord()->Name().Length()));
buf->Des().Copy(entry->AddressRecord()->Name());
__FLOG_VA((_L8("Host Name = %S "),buf));
const TInetAddr addr(entry->AddressRecord()->Address());
TBuf <255> ipaddr;
addr.Output(ipaddr);
__FLOG_VA((_L("Inet Address = %S "),&ipaddr));
__FLOG_VA((_L8("TTL = %d "),entry->AddressRecord()->Ttl()));
CleanupStack::PopAndDestroy(buf);
}
if(entry->PtrRecord())
{
__FLOG(_L8("-------Ptr-Record Data-----------"));
HBufC8* buf(HBufC8::NewLC(entry->PtrRecord()->Name().Length()));
buf->Des().Copy(entry->PtrRecord()->Name());
__FLOG_VA((_L8("PTR Name= %S "),buf));
HBufC8* domainName(HBufC8::NewLC(entry->PtrRecord()->DomainName().Length()));
domainName->Des().Copy(entry->PtrRecord()->DomainName());
__FLOG_VA((_L8("PTR Domain Name = %S "),domainName));
__FLOG_VA((_L8("Type = %d "),entry->PtrRecord()->Type()));
__FLOG_VA((_L8("TTL = %d "),entry->PtrRecord()->Ttl()));
CleanupStack::PopAndDestroy(domainName);
CleanupStack::PopAndDestroy(buf);
}
if(entry->TxtRecord())
{
__FLOG(_L8("--------Txt-Record Data---------"));
const RArray <RBuf8>& array = entry->TxtRecord()->Text();
HBufC8* name(HBufC8::NewLC(entry->TxtRecord()->Name().Length()));
name->Des().Copy(entry->TxtRecord()->Name());
__FLOG_VA((_L8("Text Name= %S "),name));
CleanupStack::PopAndDestroy(name);
for (TInt count=0;count<array.Count();count++)
{
HBufC8* text(HBufC8::NewLC(array[count].Length()));
text->Des().Copy(array[count]);
__FLOG_VA((_L8("Text Info = %S "),text));
CleanupStack::PopAndDestroy(text);
}
__FLOG_VA((_L8("TTL = %d "),entry->TxtRecord()->Ttl()));
}
__FLOG_VA((_L8("--------Entry is Authoritative?? = %d--------"),entry->IsAuthoritative()));
__FLOG_VA((_L8("--------Last Access Time = %ld--------"),entry->LastAccessTime()));
}
__FLOG_VA((_L8("--------Total number of entries = %d--------"),iCacheEntries.Count()));
}