realtimenetprots/sipfw/ClientResolver/Server/src/CSIPCRRoutingTable.cpp
changeset 0 307788aac0a8
--- /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 <e32base.h>
+#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<CSIPCRRoutingEntry> 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;       
+    }