diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/ClientResolver/Server/src/CSIPCRRoutingTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/ClientResolver/Server/src/CSIPCRRoutingTable.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,338 @@ +// Copyright (c) 2005-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: +// Name : CSIPCRRoutingTable.cpp +// Part of : SIP Client Resolver +// Version : 1.0 +// + + + +// INCLUDES +#include +#include "CSIPCRRoutingTable.h" + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::CSIPCRRoutingTable +// ----------------------------------------------------------------------------- +// +CSIPCRRoutingTable::CSIPCRRoutingTable() + { + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::NewL +// ----------------------------------------------------------------------------- +// +CSIPCRRoutingTable* CSIPCRRoutingTable::NewL() + { + CSIPCRRoutingTable* self = new (ELeave) CSIPCRRoutingTable(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::ConstructL +// ----------------------------------------------------------------------------- +// +void CSIPCRRoutingTable::ConstructL() + { + //create the entry object for find operations with dummy id 0 + iFindEntry = CSIPCRRoutingEntry::NewL(TUid::Uid(0)); + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::~CSIPCRRoutingTable +// Destructor +// ----------------------------------------------------------------------------- +// +CSIPCRRoutingTable::~CSIPCRRoutingTable() + { + iTable.ResetAndDestroy(); + delete iFindEntry; + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::AddL +// ----------------------------------------------------------------------------- +// +void CSIPCRRoutingTable::AddL( const TUid& aUid ) + { + // first check that this top level uid does not exist already, + // if it does then we leave with error code KErrAlreadyExists + if (FindEntryIndex(aUid)!=KErrNotFound) + { + User::Leave (KErrAlreadyExists); + } + + TUid topLevelUid; + if (FindToplevelMatch(aUid,topLevelUid)) + { + // This entry is already in the tree, increase reference count + TInt topLevelIndex = FindEntryIndex(topLevelUid); + CSIPCRRoutingEntry* topLevelEntry = iTable[topLevelIndex]; + CSIPCRRoutingEntry* entry = topLevelEntry->FindEntryInTree(aUid); + if (entry) + { + entry->ReferenceCount()++; + } + } + else + { + // Add a new entry in the top level + CSIPCRRoutingEntry* entry = CSIPCRRoutingEntry::NewL(aUid); + CleanupStack::PushL(entry); + iTable.AppendL(entry); + CleanupStack::Pop(entry); + } + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::FindEntryIndex +// ----------------------------------------------------------------------------- +// +TInt CSIPCRRoutingTable::FindEntryIndex(const TUid& aUid) + { + TIdentityRelation compareId(CSIPCRRoutingEntry::Compare); + iFindEntry->SetUID(aUid); + return (iTable.Find(iFindEntry, compareId)); + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::AssociateL +// ----------------------------------------------------------------------------- +// +void CSIPCRRoutingTable::AssociateL( const TUid& aUid, const TUid& aAssociatedUid ) + { + TUid associatedUidTop; + TUid parentUidTop; + TInt index; + CSIPCRRoutingEntry* topLevelEntry = NULL; + CSIPCRRoutingEntry* associatedEntryObject = NULL; + CSIPCRRoutingEntry* uidEntry = NULL; + TBool alreadyExists = EFalse; + + // first check that the parent uid exists.. + // if it does not then we leave with error code KErrNotFound + if (!FindToplevelMatch(aUid, parentUidTop)) + { + User::Leave(KErrNotFound); + } + + // first check if the associated uid exists + // if it does then we may have to move it under the right entry + alreadyExists = FindToplevelMatch(aAssociatedUid, associatedUidTop); + if (alreadyExists) + { + CSIPCRRoutingEntry* currentParent = NULL; + + // search the top level entry + index = FindEntryIndex(associatedUidTop); + topLevelEntry = iTable[index]; + // get associated uid's current parent entry.. + + currentParent = topLevelEntry->FindParent(aAssociatedUid); + + // if the current parent entry is the same + // as the one given, then dont do anything.. + if (currentParent->UID() == aUid) + { + return; + } + + // we need to move the existing associated entry + // to the new location, first remove the old + associatedEntryObject = currentParent->Detach(aAssociatedUid); + CleanupStack::PushL(associatedEntryObject); + } + + // search the parent top level entry + index = FindEntryIndex(parentUidTop); + topLevelEntry = iTable[index]; + + //now get the uid entry if it is not at the top level + if (topLevelEntry->UID() == aUid) + { + uidEntry = topLevelEntry; + } + else + { + uidEntry = topLevelEntry->FindEntryInTree(aUid); + } + + //Finally, add the associated entry + if (associatedEntryObject) + { + // moving the already allocated entry object + // to a new location + uidEntry->AddL(associatedEntryObject); + CleanupStack::Pop(associatedEntryObject); + } + else + { + // first time inserting this uid.. + // no object created yet + uidEntry->AddL(aAssociatedUid); + } + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::Remove +// ----------------------------------------------------------------------------- +// +TInt CSIPCRRoutingTable::Remove( const TUid& aUid ) + { + TUid topLevelUid(TUid::Null()); + if (!FindToplevelMatch(aUid, topLevelUid)) + { + return KErrNotFound; + } + + TInt topLevelIndex = FindEntryIndex(topLevelUid); + CSIPCRRoutingEntry* topLevelEntry = iTable[topLevelIndex]; + + if (topLevelEntry->UID() == aUid) + { + iTable.Remove(topLevelIndex); + delete topLevelEntry; + return KErrNone; + } + + CSIPCRRoutingEntry* entry = topLevelEntry->FindEntryInTree(aUid); + if (--entry->ReferenceCount() == 0) + { + CSIPCRRoutingEntry* parent = topLevelEntry->FindParent(aUid); + return (parent->Remove(aUid)); + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::FindMatch +// ----------------------------------------------------------------------------- +// +TBool CSIPCRRoutingTable::FindMatch( const TUid& aClientUid, + const TUid& aParentUid, + TUid& aNextHopUid ) + { + TUid clientUidTop; + TBool match = EFalse; + TBool fContinue = ETrue; + + // first check that the leaf uid exists.. + // if it does not then return false + if (!FindToplevelMatch(aClientUid, clientUidTop)) + { + return EFalse; + } + + // search the top level entry + TInt index = FindEntryIndex(clientUidTop); + CSIPCRRoutingEntry* topLevelEntry = iTable[index]; + + CSIPCRRoutingEntry*uidEntry = NULL; + TUid uid = aClientUid; + + while (fContinue) + { + uidEntry = topLevelEntry->FindParent(uid); + if (!uidEntry) + { + // no match + return EFalse; + } + + if (uidEntry->UID() == aParentUid) + { + // match.. + match = ETrue; + aNextHopUid = uid; + fContinue = EFalse; + } + else if (uidEntry->UID() == clientUidTop) + { + // we are at the top level.. + // no match + match = EFalse; + fContinue = EFalse; + } + else + { + // no match yet.. + // continue climbing up + uid = uidEntry->UID(); + } + } + + return match; + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::HasUid +// ----------------------------------------------------------------------------- +// +TBool CSIPCRRoutingTable::HasUid( const TUid& aClientUid ) + { + TBool found = EFalse; + TInt count = iTable.Count(); + + for ( TInt i=0; i < count && !found; i++ ) + { + CSIPCRRoutingEntry* entry = iTable[i]; + if ( entry->UID() == aClientUid || + entry->HasClient( aClientUid ) ) + { + found = ETrue; + } + } + + return found; + } + +// ----------------------------------------------------------------------------- +// CSIPCRRoutingTable::FindToplevelMatch +// ----------------------------------------------------------------------------- +// +TBool CSIPCRRoutingTable::FindToplevelMatch( const TUid& aUid, TUid& aTopLevelUid ) + { + TInt count = iTable.Count(); + + if (count > 0) + { + CSIPCRRoutingEntry* entry = NULL; + TInt index; + for (index = 0; index < count; index++) + { + entry = iTable[index]; + + // if the requested uid is top level uid itself, return it.. + if (entry->UID() == aUid) + { + aTopLevelUid = entry->UID(); + return ETrue; + } + + // or else check the clients.. + if (entry->HasClient(aUid)) + { + aTopLevelUid = entry->UID(); + return ETrue; + } + } + } + + return EFalse; + }