realtimenetprots/sipfw/ClientResolver/Resolver/src/CSipAcceptContactStrategy.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ClientResolver/Resolver/src/CSipAcceptContactStrategy.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,259 @@
+// Copyright (c) 2006-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          : CSipAcceptContactStrategy.cpp
+// Part of       : SIP Client Resolver
+// Version       : 1.0
+//
+
+
+
+#include "CSipAcceptContactStrategy.h"
+#include "MSipClients.h"
+#include "MSipClient.h"
+#include "sipresponse.h"
+#include "siprequest.h"
+#include "sipacceptcontactheader.h"
+#include "CSIPFeatureSet.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "TSIPClientScore.h"
+#include "SIPCRLogs.h"
+	
+const TUint K480ResponseCode = 480;
+
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::NewL
+// ----------------------------------------------------------------------------
+//
+CSipAcceptContactStrategy* CSipAcceptContactStrategy::NewL(
+    MSipClients& aSipClients,
+    CSipHeaderStrategyBase* aNextStrategy,
+    CSipHeaderStrategyBase* aNextStrategy2 )
+	{
+	CSipAcceptContactStrategy* self = 
+		CSipAcceptContactStrategy::NewLC( aSipClients,
+										  aNextStrategy,
+										  aNextStrategy2 );
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::NewLC
+// ----------------------------------------------------------------------------
+//
+CSipAcceptContactStrategy* CSipAcceptContactStrategy::NewLC(
+    MSipClients& aSipClients,
+    CSipHeaderStrategyBase* aNextStrategy,
+    CSipHeaderStrategyBase* aNextStrategy2 )
+	{
+	CSipAcceptContactStrategy* self = 
+		new(ELeave)CSipAcceptContactStrategy( aSipClients,
+											 aNextStrategy,
+											 aNextStrategy2 );
+	CleanupStack::PushL(self);
+	return self;
+	}
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::CSipAcceptContactStrategy
+// ----------------------------------------------------------------------------
+//
+CSipAcceptContactStrategy::CSipAcceptContactStrategy(
+    MSipClients& aSipClients,
+    CSipHeaderStrategyBase* aNextStrategy,
+    CSipHeaderStrategyBase* aNextStrategy2 ) 
+ : CSipHeaderStrategyBase( aSipClients,aNextStrategy,aNextStrategy2 )
+	{
+	iAcceptContactHeaderName = 
+	    SIPStrings::StringF(SipStrConsts::EAcceptContactHeader);
+	}
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::~CSipAcceptContactStrategy
+// ----------------------------------------------------------------------------
+//
+CSipAcceptContactStrategy::~CSipAcceptContactStrategy ()
+	{
+	}
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::ApplyL
+// ----------------------------------------------------------------------------
+//
+CSIPResponse* CSipAcceptContactStrategy::ApplyL(
+    CSIPRequest& aRequest, 
+    RArray<TUid>& aUids,
+    TBool& aContinueSearch,
+    CSIPClientResolver2& aClientResolver2 )
+	{
+	SIP_CR_LOG("CSipAcceptContactStrategy::ApplyL")
+	CSIPResponse* response = NULL;
+	// The strategy is applied only for requests that contain Accept-Contact
+	if (aRequest.HasHeader(iAcceptContactHeaderName))
+        {
+        RArray<TSIPClientScore> scores(1);
+        CleanupClosePushL(scores);
+        RPointerArray<CSIPFeatureSet> requestFeatureSets = 
+            CreateFeatureSetsL(aRequest);
+        TCleanupItem cleanupItem(DestroyFeatureSets,&requestFeatureSets);
+	    CleanupStack::PushL(cleanupItem);
+	    for (TInt i=0; i < aUids.Count(); i++)
+		    {
+		    TUid uid(aUids[i]);
+		    MSipClient* client = iSipClients.GetByUID(uid);
+		    if (client)
+			    {
+			    TInt score = CalculateScore(*client,requestFeatureSets);
+			    if (score > 0)
+			        {
+			        TSIPClientScore clientScore(score,uid);
+			        // The score is used as a key
+			        scores.InsertInSignedKeyOrderAllowRepeatsL(clientScore);
+			        }
+			    }	
+		    }
+    	CleanupStack::PopAndDestroy(1); // cleanupItem
+    	TInt clientCount = scores.Count();
+    	aUids.Reset(); // empties the array
+	    if (clientCount > 0)
+	        {
+	        // The scores are in increasing order. 
+	        // The last is the best match. Reverse the order.
+	        for (TInt i=scores.Count()-1; i>=0; i--)
+	            {
+	            // In the resulting array the first is the best match
+	            aUids.AppendL(scores[i].iUid);
+	            } 
+	        if (iNextStrategy && clientCount > 1)
+	            {
+	            // Apply the next strategy only if 
+	            // there are still more than one matching clients.
+	            response = iNextStrategy->ApplyL(aRequest,aUids,
+	                                             aContinueSearch,
+	                                             aClientResolver2);
+	            }
+	        }
+	    else
+		    {
+		    if ( iNextStrategy2 )
+		    	{
+		    	response = iNextStrategy2->ApplyL(aRequest,aUids,
+		    									  aContinueSearch,
+		    									  aClientResolver2);
+		    	}
+		    else
+		    	{
+		    	response = CreateResponseL();
+		    	}
+		    
+		    }
+		CleanupStack::PopAndDestroy(1); // scores
+        }
+    else
+        {
+        if (iNextStrategy)
+            {
+	        response = iNextStrategy->ApplyL(aRequest,aUids,aContinueSearch,
+	        												aClientResolver2);
+	        }
+        }
+
+    return response;
+	}
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::CreateResponseL
+// ----------------------------------------------------------------------------
+//
+CSIPResponse* CSipAcceptContactStrategy::CreateResponseL()
+    {
+    return CSIPResponse::NewL(K480ResponseCode,
+        SIPStrings::StringF(SipStrConsts::EPhraseTemporarilyNotAvailable));
+    }
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::CompareHeaders
+// ----------------------------------------------------------------------------
+//
+TBool CSipAcceptContactStrategy::CompareHeaders(
+    CSIPRequest& /*aRequest*/,
+    MSipClient& /*aClient*/)
+	{
+	// Not implemented for this sub-class
+	return EFalse;
+	}
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::CreateFeatureSetsL
+// ----------------------------------------------------------------------------
+//
+RPointerArray<CSIPFeatureSet> CSipAcceptContactStrategy::CreateFeatureSetsL(
+    CSIPRequest& aRequest)
+    {
+    RPointerArray<CSIPFeatureSet> featureSets;
+    TCleanupItem cleanupItem(DestroyFeatureSets,&featureSets);
+	CleanupStack::PushL(cleanupItem);
+	TSglQueIter<CSIPHeaderBase> iter = 
+	    aRequest.Headers(iAcceptContactHeaderName);	
+	while (iter)
+		{
+		CSIPHeaderBase* tmp = iter++;
+		CSIPAcceptContactHeader* acceptContact = 
+		    static_cast<CSIPAcceptContactHeader*>(tmp);
+		CSIPFeatureSet* featureSet = CSIPFeatureSet::NewLC(*acceptContact);
+		featureSets.AppendL(featureSet);
+		CleanupStack::Pop(featureSet);
+		}	
+	CleanupStack::Pop(1); // cleanupItem 
+    return featureSets;
+    }
+
+// ----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::CalculateScore
+// ----------------------------------------------------------------------------
+//	
+TInt CSipAcceptContactStrategy::CalculateScore(
+    MSipClient& aClient,
+    const RPointerArray<CSIPFeatureSet>& aRequestFeatureSets) const
+    {
+    TInt score = 0;
+    CSIPFeatureSet& clientFeatureSet = aClient.SIPFeatureSet();
+    for (TInt i = 0; i < aRequestFeatureSets.Count(); i++)
+        {
+        CSIPFeatureSet& requestFeatureSet = *aRequestFeatureSets[i];
+        TInt tmp = clientFeatureSet.CalculateScore(requestFeatureSet);
+        if (tmp == 0 && requestFeatureSet.Require())
+            {
+            return 0;
+            }
+        score += tmp;
+        }
+    return score;
+    }
+    
+// -----------------------------------------------------------------------------
+// CSipAcceptContactStrategy::DestroyFeatureSets
+// -----------------------------------------------------------------------------
+//
+void CSipAcceptContactStrategy::DestroyFeatureSets(TAny* aFeatureSets)
+	{
+    RPointerArray<CSIPFeatureSet>* featureSets =
+        reinterpret_cast<RPointerArray<CSIPFeatureSet>*>(aFeatureSets);
+    if (featureSets)
+        {
+        featureSets->ResetAndDestroy();
+        }
+	}