--- /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
+ }