diff -r 000000000000 -r af10295192d8 tcpiputils/dnd/src/hostname.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tcpiputils/dnd/src/hostname.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,282 @@ +// Copyright (c) 2004-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: +// hostname.cpp - hostnames of the local node +// + +#include "hostname.h" +#include "inet6log.h" + +#if defined(TCPIP6_USE_COMMDB) +# include +#else +# include + using namespace CommsDat; +#endif + +class CLocalHostName : public CBase + /** + * Stores a local hostname. + * + * The hostnames are stored in separate objects and reference counted. + * The same hostname can be mapped to multiple network ids. + * + */ + { + /** + * Constructor. + * Private, only used from CLocalHostName::New method, due to somewhat + * dubious tricks with TLitC class (to store the name). + */ + CLocalHostName(const THostName &aName, CLocalHostName *aNext) : iNext(aNext) + { + // See _LIT and TLitC for this initializer!!! + iName.iTypeLength = aName.Length(); + TPtr((TText *)&iName.iBuf[0], aName.Length()).Copy(aName); + } + +public: + static CLocalHostName *New(const THostName &aName, CLocalHostName *aNext); + CLocalHostName *iNext; //< Link to the next name. + TInt iRefs; //< The reference count (value 0 implies already one reference). + TLitC<1> iName; //< Host name (<1> is *FAKE*!) + // + // This is followed by the actual name characters. + // CHostName class *CANNOT* be subclassed!!!! + }; + + +CLocalHostName *CLocalHostName::New(const THostName &aName, CLocalHostName *aNext) + { + // note: TLitC<1> causes extra allocation of sizeof(TInt) [depends on align + // settings]. Could try to adjust the extra requested size down by that amount, + // but it would result more complex code... -- msa + return new (aName.Size()) CLocalHostName(aName, aNext); + } + +class TLocalHostMap + { +public: + TLocalHostMap(TUint32 aId, const CLocalHostName *aName) : iId(aId), iName(aName) {} + const TUint32 iId; + const CLocalHostName *iName; + }; + +THostNames::~THostNames() + { + Cleanup(); + } + + + +void THostNames::Cleanup() + { + // note: this does not need to worry about reference counts + // in hostnames, because everything is cleaned. + delete iMap; + iMap = NULL; + + while (iNameList != NULL) + { + CLocalHostName *e = iNameList; + iNameList = e->iNext; + delete e; + } + } + +void THostNames::ReferenceRemoved(const CLocalHostName *aName) + { + for (CLocalHostName **h = &iNameList, *p; (p = *h) != NULL; h = &p->iNext) + { + if (p == aName) + { + if (--p->iRefs < 0) + { + *h = p->iNext; + delete p; + } + return; + } + } + } + + +TInt THostNames::Map(TUint32 aId, const TDesC &aName) + { + // + // Locate or create a hostname entry + // + TInt err = KErrNoMemory; + + CLocalHostName *name = iNameList; + for (;;name = name->iNext) + { + if (name == NULL) + { + name = CLocalHostName::New(aName, iNameList); + if (name == NULL) + return KErrNoMemory; + iNameList = name; + // The initial iRefs = 0 is ok. + break; + } + else if (aName.Compare(name->iName) == 0) + { + // Additional reference to an existing name. + name->iRefs++; + break; + } + } + + if (iMap != NULL || (iMap = new CArrayFixFlat(4)) != NULL) + { + // + // Remove old mapping, if any + // + for (TInt i = iMap->Count(); i > 0; ) + { + TLocalHostMap &m = iMap->At(--i); + if (m.iId == aId) + { + // Id already present, just change the name reference (if changed). + if (m.iName != name) + { + LOG(Log::Printf(_L("\tlocalhost unmapped: <%u, %S(%d)>"), m.iId, &m.iName->iName, m.iName->iRefs)); + ReferenceRemoved(m.iName); + m.iName = name; + } + LOG(Log::Printf(_L("\tlocalhost mapped: <%u, %S(%d)>"), m.iId, &m.iName->iName, m.iName->iRefs)); + return KErrNone; + } + } + // Id was not recorded before this, create a new entry. + TRAP(err, iMap->AppendL(TLocalHostMap(aId, name))); + if (err == KErrNone) + { + LOG(Log::Printf(_L("\tlocalhost mapped: <%u, %S(%d)>"), aId, &name->iName, name->iRefs)); + return KErrNone; + } + } + ReferenceRemoved(name); + return err; + } + + +void THostNames::Unmap(TUint32 aId) + { + // + // Remove old mapping, if any + // + if (iMap) + { + for (TInt i = iMap->Count(); i > 0; ) + { + const TLocalHostMap &m = iMap->At(--i); + if (m.iId == aId) + { + LOG(Log::Printf(_L("\tlocalhost unmapped: <%u, %S(%d)>"), m.iId, &m.iName->iName, m.iName->iRefs)); + ReferenceRemoved(m.iName); + iMap->Delete(i); + break; // There can be only one matching id! + } + } + iMap->Compress(); + } + } + +const TDesC &THostNames::Find(TUint32 aId) const + { + if (iMap) + { + for (TInt i = iMap->Count(); i > 0; ) + { + const TLocalHostMap &m = iMap->At(--i); + if (m.iId == aId) + return m.iName->iName; + } + } + return KNullDesC; + } + +TInt THostNames::Reset(const TDesC &aLocalHost) + { + Cleanup(); + + // Define the return, when network id is not specified. + + Map(0, aLocalHost); + + // ---------------------------------------------- + // Insert here the code to scan the commdb and, + // for each pair , call Map(id, name). + // ---------------------------------------------- + TRAPD(err, GetCommDbDataL(0)); + + return err; + } + +TInt THostNames::Refresh(TUint32 aId) + { + TRAPD(err, GetCommDbDataL(aId)); + return err; + } + + +void THostNames::GetCommDbDataL(TUint32 aId) + { +#if defined(TCPIP6_USE_COMMDB) +# ifdef HOST_NAME + CCommsDatabase* db = CCommsDatabase::NewL(); + CleanupStack::PushL(db); + + CCommsDbTableView* view = db->OpenTableLC(TPtrC(NETWORK)); + for (TInt ret = view->GotoFirstRecord(); ret == KErrNone; ret = view->GotoNextRecord()) + { + THostName name; + TUint32 nid = 0; + TRAP(ret, + view->ReadTextL(TPtrC(HOST_NAME), name); + view->ReadUintL(TPtrC(COMMDB_ID), nid)); + if (ret == KErrNone) + Map(nid, name); + } + CleanupStack::PopAndDestroy(2); +#endif +#else + // . (not tested) +#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + CMDBSession *dB = CMDBSession::NewLC(KCDVersion1_2); +#else + CMDBSession *dB = CMDBSession::NewLC(KCDVersion1_1); +#endif + + + // Reveal hidden or private IAP records if a licensee has chosen to protect a record + // using one of these flags - the API to do this is public so internal components + // have to support the use of such records. + dB->SetAttributeMask( ECDHidden | ECDPrivate ); + + CMDBRecordSet *networkTable; + networkTable = new (ELeave) CMDBRecordSet(KCDTIdNetworkRecord); + CleanupStack::PushL(networkTable); + networkTable->LoadL(*dB); + const TInt totalRecords = networkTable->iRecords.Count(); + for (TInt i = 0; i < totalRecords; ++i) + { + const TUint32 nid = (*networkTable)[i]->RecordId(); + if (aId == 0 || nid == aId) + Map(nid, (*networkTable)[i]->iHostName); + } + CleanupStack::PopAndDestroy(2); +#endif + }