tcpiputils/dnd/src/hostname.cpp
changeset 0 af10295192d8
--- /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 <commdb.h>
+#else
+#	include <commsdattypesv1_1.h>
+	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<TLocalHostMap>(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 <nid, name>, 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<CCDNetworkRecord> *networkTable;
+	networkTable = new (ELeave) CMDBRecordSet<CCDNetworkRecord>(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
+	}