realtimenetprots/sipfw/ClientResolver/Server/src/CSIPCRServerSession.cpp
changeset 0 307788aac0a8
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Name          : CSIPCRServerSession.cpp
       
    15 // Part of       : SIP Client Resolver
       
    16 // Version       : 1.0 
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDES
       
    22 #include <e32math.h>
       
    23 #include "CSipCRServerSession.h"
       
    24 #include "CSIPCRRoutingTable.h"
       
    25 #include "CSIPClientResolver.h"
       
    26 #include "CSIPCRITCUtility.h"
       
    27 #include "CSIPCRSessionReceiver.h"
       
    28 #include "CSipCRServer.h"
       
    29 #include "sipCRclientserver.h"
       
    30 #include "CSIPCRRequestItem.h"
       
    31 #include "siprequest.h"
       
    32 #include "sipresponse.h"
       
    33 #include "TSipClient.h"
       
    34 #include "sipresolvedclient.h"
       
    35 #include "sipcontenttypeheader.h"
       
    36 #include "sipstrconsts.h"
       
    37 #include "sipstrings.h"
       
    38 #include "uricontainer.h"
       
    39 #include "SIPCRSerializer.h"
       
    40 #include "sipresolvedclient2.h"
       
    41 #include "sipcrworkerao.h"
       
    42 #include "sipcrrequestqueuecleanupdata.h"
       
    43 
       
    44 const TUint K480ResponseCode = 480;
       
    45 const TUint K503ResponseCode = 503;
       
    46 
       
    47 _LIT(KWorkerThreadName, "SIPClientResolverSessionWorker");
       
    48 
       
    49 // ----------------------------------------------------------------------------
       
    50 // CSIPCRServerSession::NewL
       
    51 // ----------------------------------------------------------------------------
       
    52 //
       
    53 CSIPCRServerSession* CSIPCRServerSession::NewL(CSIPCRServer& aCRServer)
       
    54     {
       
    55     CSIPCRServerSession* self = CSIPCRServerSession::NewLC(aCRServer);
       
    56     CleanupStack::Pop (self);
       
    57     return self;
       
    58     }
       
    59 
       
    60 // ----------------------------------------------------------------------------
       
    61 // CSIPCRServerSession::NewLC
       
    62 // ----------------------------------------------------------------------------
       
    63 //
       
    64 CSIPCRServerSession* CSIPCRServerSession::NewLC(CSIPCRServer& aCRServer)
       
    65     {
       
    66     CSIPCRServerSession* self = new(ELeave)CSIPCRServerSession(aCRServer);
       
    67     CleanupStack::PushL(self);
       
    68     self->ConstructL();
       
    69     return self;
       
    70     }
       
    71     
       
    72 // ----------------------------------------------------------------------------
       
    73 // CSIPCRServerSession::CSIPCRServerSession
       
    74 // ----------------------------------------------------------------------------
       
    75 //
       
    76 CSIPCRServerSession::CSIPCRServerSession(CSIPCRServer& aCRServer)
       
    77  : iClientUid(TUid::Null()),
       
    78    iClientUidSet(EFalse),
       
    79    iCRServer(aCRServer)
       
    80     {
       
    81     iCRServer.IncrementSessions();
       
    82     }    
       
    83     
       
    84 // ----------------------------------------------------------------------------
       
    85 // CSIPCRServerSession::ConstructL
       
    86 // ----------------------------------------------------------------------------
       
    87 //
       
    88 void CSIPCRServerSession::ConstructL()
       
    89     {
       
    90     User::LeaveIfError(iRequestQueueMutex.CreateLocal());
       
    91     iReceiver = CSIPCRSessionReceiver::NewL(iCRServer.ITCUtility());
       
    92     }
       
    93 
       
    94 // ----------------------------------------------------------------------------
       
    95 // CSIPCRServerSession::~CSIPCRServerSession
       
    96 // ----------------------------------------------------------------------------
       
    97 //
       
    98 CSIPCRServerSession::~CSIPCRServerSession ()
       
    99     {
       
   100     iWorkerAos.ResetAndDestroy();    
       
   101     delete iReceiver;
       
   102     iRequestQueue.ResetAndDestroy();
       
   103     iCRServer.DecrementSessions();
       
   104     if (iClientUidSet)
       
   105         {
       
   106         iCRServer.RoutingTable().Remove(iClientUid);   
       
   107         }
       
   108     iRequestQueueMutex.Close();
       
   109     }
       
   110     
       
   111 // ----------------------------------------------------------------------------
       
   112 // CSIPCRServerSession::ServiceL
       
   113 // ----------------------------------------------------------------------------
       
   114 //
       
   115 void CSIPCRServerSession::ServiceL(const RMessage2& aMessage)
       
   116     {
       
   117     DoServiceL(aMessage.Function(),aMessage);
       
   118     }
       
   119 
       
   120 // ----------------------------------------------------------------------------
       
   121 // CSIPCRServerSession::WorkerAoRequestCompleted
       
   122 // ----------------------------------------------------------------------------
       
   123 //
       
   124 void CSIPCRServerSession::WorkerAoRequestCompleted(CSipCrWorkerAo* aWorkerAo)
       
   125     {
       
   126     TInt err = aWorkerAo->CompletionCode();
       
   127     TUint32 requestId = aWorkerAo->RequestId();
       
   128     if (err != KErrNone && requestId > 0)
       
   129         {
       
   130         TRAP_IGNORE(iReceiver->ErrorReceivedL(requestId,err))
       
   131         }
       
   132     TInt index = iWorkerAos.Find(aWorkerAo);
       
   133     if (index >= 0)
       
   134         {
       
   135         iWorkerAos.Remove(index);
       
   136         }
       
   137     delete aWorkerAo;
       
   138     }
       
   139     
       
   140 // ----------------------------------------------------------------------------
       
   141 // CSIPCRServerSession::RoutingEntryAddedL
       
   142 // ----------------------------------------------------------------------------
       
   143 //
       
   144 void CSIPCRServerSession::RoutingEntryAddedL(const TUid& aUid)
       
   145     {
       
   146     CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex);    
       
   147     
       
   148     // Complete pending requests for aUid
       
   149     CSIPCRRequestItem* requestItem = NULL;
       
   150     for (TInt i=iRequestQueue.Count()-1; i >= 0; i--)
       
   151         {
       
   152         requestItem = iRequestQueue[i];
       
   153         if (requestItem->ChannelUid() == aUid)
       
   154             {
       
   155             TUint32 requestId = requestItem->RequestId();
       
   156             TUid nextHopUid(TUid::Null());
       
   157             if (iCRServer.RoutingTable().FindMatch(aUid,iClientUid,nextHopUid))
       
   158                 {
       
   159                 iReceiver->RequestCompletedL(requestId,nextHopUid);
       
   160                 }
       
   161             else
       
   162                 {
       
   163                 iReceiver->ErrorReceivedL(requestId,KErrNotFound);
       
   164                 }
       
   165             ProtectedRemoveFromRequestQueue( requestItem );
       
   166             delete requestItem;            
       
   167             }
       
   168         }
       
   169     
       
   170     CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex
       
   171         
       
   172     CSipCrWorkerAo* workerAo = CSipCrWorkerAo::NewLC(*this);
       
   173     CreateWorkerThreadL(workerAo,ConnectWorkerThreadFunction);
       
   174     CleanupStack::Pop(workerAo);
       
   175     }
       
   176     
       
   177 // ----------------------------------------------------------------------------
       
   178 // CSIPCRServerSession::DoServiceL
       
   179 // ----------------------------------------------------------------------------
       
   180 //
       
   181 void CSIPCRServerSession::DoServiceL (TInt aFunction,
       
   182                                       const RMessage2& aMessage)
       
   183     {
       
   184     switch (aFunction)
       
   185         {
       
   186 #ifndef	PLAT_SEC_TEST
       
   187         case ESIPCRIpcSetClientUid:
       
   188             SetUIDL(aMessage); break;
       
   189             
       
   190 	    case ESIPCRIpcRegister:
       
   191 	        RegisterL(iCRServer.ITCUtility().ReadUIDL(aMessage)); break;
       
   192 
       
   193 	    case ESIPCRIpcDeregister:
       
   194 	        DeregisterL(iCRServer.ITCUtility().ReadUIDL(aMessage)); break;
       
   195 
       
   196         case ESIPCRIpcClientReadyToReceive: // Async. Don't complete yet.
       
   197             ClientReadyToReceiveL(aMessage); return;
       
   198             
       
   199         case ESIPCRIpcClientCancelReceive:
       
   200             CancelClientReceiveL(); break;
       
   201             
       
   202         case ESIPCRIpcCancelRequest:
       
   203             CancelRequestL(aMessage); break;            
       
   204         
       
   205         case ESIPCRIpcCancelAllRequests:
       
   206             CancelAllRequests(); break;
       
   207             
       
   208         case ESIPCRIpcChannel:
       
   209             ChannelL(aMessage); break;
       
   210             
       
   211         case ESIPCRIpcChannelWithResolver:
       
   212             ChannelWithResolverL(aMessage); break;
       
   213             
       
   214         case ESIPCRIpcClientReceiveSipResponse:
       
   215             ClientReceiveSipResponseL(aMessage); break;
       
   216         
       
   217         default:
       
   218             break;
       
   219 #endif
       
   220 	    }
       
   221     iCRServer.ITCUtility().Complete(aMessage,KErrNone);
       
   222     }
       
   223 
       
   224 // ----------------------------------------------------------------------------
       
   225 // CSIPCRServerSession::ChannelWithResolverL
       
   226 // ----------------------------------------------------------------------------
       
   227 //
       
   228 void CSIPCRServerSession::ChannelWithResolverL(const RMessage2& aMessage)
       
   229     {
       
   230     CSIPRequest* request = CSIPRequest::NewLC();
       
   231     iCRServer.ITCUtility().ReadSIPRequestL(aMessage, *request);
       
   232     TUid resolverUid = iCRServer.ITCUtility().ReadResolverUidL(aMessage);
       
   233     TUint32 requestId = CreateRequestId();
       
   234     TSipClient clientUid(TUid::Null(),EFalse,EFalse);
       
   235     ChannelL(requestId,*request,clientUid,resolverUid);
       
   236     CleanupStack::PopAndDestroy(request);
       
   237     iCRServer.ITCUtility().WriteRequestIdL(aMessage,requestId);
       
   238     }
       
   239     
       
   240 // ----------------------------------------------------------------------------
       
   241 // CSIPCRServerSession::ChannelL
       
   242 // ----------------------------------------------------------------------------
       
   243 //
       
   244 void CSIPCRServerSession::ChannelL(const RMessage2& aMessage)
       
   245     {
       
   246     CSIPRequest* request = CSIPRequest::NewLC();
       
   247     iCRServer.ITCUtility().ReadSIPRequestL(aMessage, *request);
       
   248     
       
   249     TUint32 requestId = CreateRequestId();
       
   250     iCRServer.ITCUtility().WriteRequestIdL(aMessage,requestId);
       
   251     
       
   252     TSipClient clientUid(TUid::Null(),EFalse,EFalse);
       
   253     
       
   254     CSIPResponse* response = ResolveClientL(*request,clientUid);
       
   255     if (response)
       
   256         {
       
   257         CleanupStack::PushL(response);
       
   258         iReceiver->AddErrorResponseL(requestId,response);
       
   259         CleanupStack::PopAndDestroy(response);
       
   260         }
       
   261     else
       
   262         {
       
   263         ChannelL(requestId,*request,clientUid,TUid::Null());
       
   264         }
       
   265     CleanupStack::PopAndDestroy(request);
       
   266     }
       
   267     
       
   268 // ----------------------------------------------------------------------------
       
   269 // CSIPCRServerSession::RegisterL
       
   270 // ----------------------------------------------------------------------------
       
   271 //
       
   272 void CSIPCRServerSession::RegisterL(const TUid& aChannelUid)
       
   273     {
       
   274     iCRServer.RoutingTable().AssociateL(iClientUid, aChannelUid);
       
   275     iCRServer.RoutingEntryAddedL(aChannelUid);
       
   276     }
       
   277 
       
   278 // ----------------------------------------------------------------------------
       
   279 // CSIPCRServerSession::DeregisterL
       
   280 // ----------------------------------------------------------------------------
       
   281 //
       
   282 void CSIPCRServerSession::DeregisterL(const TUid& aChannelUid)
       
   283     {
       
   284     iCRServer.RoutingTable().Remove(aChannelUid);
       
   285     }
       
   286 
       
   287 // ----------------------------------------------------------------------------
       
   288 // CSIPCRServerSession::SetUIDL
       
   289 // ----------------------------------------------------------------------------
       
   290 //
       
   291 void CSIPCRServerSession::SetUIDL(const RMessage2& aMessage)
       
   292     {
       
   293     iClientUid = iCRServer.ITCUtility().ReadUIDL (aMessage);
       
   294     iCRServer.RoutingTable().AddL(iClientUid);
       
   295     iClientUidSet = ETrue;
       
   296     }
       
   297 
       
   298 // ----------------------------------------------------------------------------
       
   299 // CSIPCRServerSession::ClientReadyToReceiveL
       
   300 // ----------------------------------------------------------------------------
       
   301 //
       
   302 void CSIPCRServerSession::ClientReadyToReceiveL(const RMessage2& aMessage)
       
   303     {
       
   304     iReceiver->ClientReadyToReceiveL(aMessage);
       
   305     }
       
   306 
       
   307 // ----------------------------------------------------------------------------
       
   308 // CSIPCRServerSession::ClientReceiveSipResponseL
       
   309 // ----------------------------------------------------------------------------
       
   310 //
       
   311 void CSIPCRServerSession::ClientReceiveSipResponseL(const RMessage2& aMessage)
       
   312     {
       
   313     iReceiver->WriteSipResponseToClientL(aMessage);
       
   314     }
       
   315 
       
   316 // ----------------------------------------------------------------------------
       
   317 // CSIPCRServerSession::CancelRequestL
       
   318 // ----------------------------------------------------------------------------
       
   319 //
       
   320 void CSIPCRServerSession::CancelRequestL(const RMessage2& aMessage)
       
   321     {
       
   322     TUint32 requestId = iCRServer.ITCUtility().ReadRequestIdL(aMessage);
       
   323     TBool found = EFalse;
       
   324     
       
   325     CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex);    
       
   326     
       
   327     for (TInt i=iRequestQueue.Count()-1; i >=0 && !found; i--)
       
   328         {
       
   329         CSIPCRRequestItem* requestItem = iRequestQueue[i];
       
   330         if (requestItem->RequestId() == requestId)
       
   331             {
       
   332             CancelConnectL( requestItem );
       
   333             ProtectedRemoveFromRequestQueue( requestItem );
       
   334             delete requestItem;             
       
   335             found = ETrue;
       
   336             }
       
   337         }
       
   338         
       
   339     CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex   
       
   340           
       
   341     iReceiver->RemoveByRequestId(requestId);
       
   342     CSipCrWorkerAo* workerAo = CSipCrWorkerAo::NewLC(*this);
       
   343     CreateWorkerThreadL(workerAo,ConnectWorkerThreadFunction);
       
   344     CleanupStack::Pop(workerAo);
       
   345     }
       
   346     
       
   347 // ----------------------------------------------------------------------------
       
   348 // CSIPCRServerSession::CancelConnectL
       
   349 // ----------------------------------------------------------------------------
       
   350 //    
       
   351 void CSIPCRServerSession::CancelConnectL( CSIPCRRequestItem* aRequestItem )
       
   352     {
       
   353     if ( aRequestItem->Client().PluginType() == TSipClient::ESecondGeneration )
       
   354     	{
       
   355     	if ( aRequestItem->ConnectCalled() )
       
   356     		{
       
   357     		CSIPResolvedClient2* resolvedClient2 =
       
   358         		iCRServer.LoadPlugin2LC( 
       
   359         		    aRequestItem->Client().ImplementationUid() );
       
   360             resolvedClient2->CancelConnect( aRequestItem->Client().Uid() );
       
   361         	CleanupStack::PopAndDestroy( resolvedClient2 );
       
   362     		}
       
   363     	}
       
   364     }
       
   365     
       
   366 // ---------------------------------------------------------------------------
       
   367 // CSIPCRServerSession::AddToRequestQueueL
       
   368 // ---------------------------------------------------------------------------
       
   369 //
       
   370 template<class T> void CSIPCRServerSession::AddToRequestQueueL( 
       
   371     CSIPCRRequestItem* aRequestItem,
       
   372     T& aResolvedClient )
       
   373 	{
       
   374 	__ASSERT_ALWAYS ( aRequestItem, User::Leave( KErrArgument ) );
       
   375 
       
   376     // The request item needs to be in request queue 
       
   377     // in case the client connects immediately after calling ConnectL 
       
   378     // and the main thread examines the request queue 
       
   379     ProtectedAddToRequestQueueL( aRequestItem );
       
   380     TSipCrRequestQueueCleanupData cleanupData;
       
   381     cleanupData.iSession = this;
       
   382     cleanupData.iRequestItem = aRequestItem;
       
   383     TCleanupItem cleanupItem( RemoveFromRequestQueue, &cleanupData );
       
   384     CleanupStack::PushL(cleanupItem);
       
   385     TBool connectSucceeded = ConnectL( *aRequestItem, aResolvedClient );
       
   386     CleanupStack::Pop(); // cleanupItem, leave the item to queue
       
   387     if ( !connectSucceeded )
       
   388         {
       
   389         ProtectedRemoveFromRequestQueue( aRequestItem );
       
   390         delete aRequestItem;
       
   391         }  
       
   392 	}
       
   393 
       
   394 // ---------------------------------------------------------------------------
       
   395 // CSIPCRServerSession::ConnectL
       
   396 // ---------------------------------------------------------------------------
       
   397 //
       
   398 template<class T> TBool CSIPCRServerSession::ConnectL( 
       
   399     CSIPCRRequestItem& aRequestItem,
       
   400     T& aResolvedClient )
       
   401 	{
       
   402 	TBool success = ETrue;
       
   403     TRAPD (err, aResolvedClient.ConnectL(aRequestItem.ChannelUid()));
       
   404     if (err == KErrNoMemory)
       
   405         {
       
   406         User::Leave(err);
       
   407         }
       
   408     else if (err != KErrNone)
       
   409         {
       
   410         CSIPResponse* response = CSIPResponse::NewLC(K480ResponseCode,
       
   411             SIPStrings::StringF(SipStrConsts::EPhraseTemporarilyNotAvailable));
       
   412         iReceiver->AddErrorResponseL(aRequestItem.RequestId(),response);
       
   413         CleanupStack::Pop(response);
       
   414         success = EFalse;
       
   415         }
       
   416     else
       
   417         {
       
   418         aRequestItem.SetConnectCalled();    
       
   419         }        
       
   420     return success;
       
   421 	}
       
   422 
       
   423 // ----------------------------------------------------------------------------
       
   424 // CSIPCRServerSession::CancelAllRequests
       
   425 // ----------------------------------------------------------------------------
       
   426 //    
       
   427 void CSIPCRServerSession::CancelAllRequests()
       
   428     {
       
   429     iRequestQueueMutex.Wait(); // Protect iRequestQueue with a mutex
       
   430     iRequestQueue.ResetAndDestroy();
       
   431     iRequestQueueMutex.Signal();
       
   432     iReceiver->RemoveAll();
       
   433     }
       
   434     
       
   435 // ----------------------------------------------------------------------------
       
   436 // CSIPCRServerSession::CancelClientReceiveL
       
   437 // ----------------------------------------------------------------------------
       
   438 //
       
   439 void CSIPCRServerSession::CancelClientReceiveL ()
       
   440     {
       
   441     iReceiver->CancelClientReceiveL();
       
   442     }
       
   443 
       
   444 // ----------------------------------------------------------------------------
       
   445 // CSIPCRServerSession::ResolveClientL
       
   446 // ----------------------------------------------------------------------------
       
   447 //
       
   448 CSIPResponse* CSIPCRServerSession::ResolveClientL(
       
   449     CSIPRequest& aRequest,
       
   450     TSipClient& aUid)
       
   451     {
       
   452     RArray<TSipClient> uids;
       
   453     CleanupClosePushL(uids);
       
   454     // Always execute the client resolving code in the main thread
       
   455     // Multithreading the resolving code would be error prone and
       
   456     // there is no performance reason to create a new thread for resolving.
       
   457     CSIPResponse* response = 
       
   458         iCRServer.ClientResolver().FindUidL(aRequest,uids);
       
   459     if (!response)
       
   460         {
       
   461         __ASSERT_ALWAYS(uids.Count() > 0, User::Leave(KErrNotFound));
       
   462         if (!FindUid(uids,aUid,ETrue,ETrue) &&
       
   463             !FindUid(uids,aUid,ETrue,EFalse) &&
       
   464             !FindUid(uids,aUid,EFalse,ETrue) &&
       
   465             !FindUid(uids,aUid,EFalse,EFalse))
       
   466             {
       
   467             response = CSIPResponse::NewL(K503ResponseCode,
       
   468                 SIPStrings::StringF(SipStrConsts::EPhraseServiceUnavailable));
       
   469             }
       
   470         }
       
   471     CleanupStack::PopAndDestroy(1); // uids
       
   472     return response;
       
   473     }
       
   474     
       
   475 // ----------------------------------------------------------------------------
       
   476 // CSIPCRServerSession::ChannelL
       
   477 // ----------------------------------------------------------------------------
       
   478 //    
       
   479 void CSIPCRServerSession::ChannelL(
       
   480     TUint32 aRequestId,
       
   481     CSIPRequest& aRequest,
       
   482     const TSipClient& aClient,
       
   483     const TUid& aResolverUid)
       
   484     {
       
   485     // SIP request cannot be passed as such to the worker thread because 
       
   486     // the main and worker threads are using a different string pool.
       
   487     // Instead SIP request is externalized in the main thread and 
       
   488     // internalized in the worker thread.
       
   489     CBufBase* serializedRequest = SIPCRSerializer::ExternalizeL(aRequest);
       
   490     CleanupStack::PushL(serializedRequest);
       
   491     HBufC8* requestBody = aRequest.TakeContentOwnershipL();
       
   492     CleanupStack::PushL(requestBody);
       
   493     
       
   494     CSipCrWorkerAo* workerAo = 
       
   495         CSipCrWorkerAo::NewL(
       
   496             aRequestId,serializedRequest,requestBody,
       
   497             aClient,aResolverUid,*this);
       
   498             
       
   499     CleanupStack::Pop(requestBody);
       
   500     CleanupStack::Pop(serializedRequest);    
       
   501     
       
   502     CleanupStack::PushL(workerAo);
       
   503     CreateWorkerThreadL(workerAo,ChannelWorkerThreadFunction);
       
   504     CleanupStack::Pop(workerAo);
       
   505     }
       
   506 
       
   507 // ----------------------------------------------------------------------------
       
   508 // CSIPCRServerSession::ChannelImplementationL
       
   509 // ----------------------------------------------------------------------------
       
   510 //   
       
   511 void CSIPCRServerSession::ChannelImplementationL( CSipCrWorkerAo& aWorkerAo )
       
   512     {    
       
   513     CSIPRequest* request = CSIPRequest::NewLC(); 
       
   514     SIPCRSerializer::InternalizeL( 
       
   515         aWorkerAo.SerializedSipRequest().Ptr( 0 ), *request );
       
   516     request->SetContent( aWorkerAo.GetSipRequestBody() );
       
   517     
       
   518     CSIPResolvedClient2* resolvedClient2 = NULL;
       
   519     CSIPResolvedClient* resolvedClient = NULL;
       
   520     
       
   521     if ( aWorkerAo.SipClient().PluginType() == TSipClient::EFirstGeneration )
       
   522     	{
       
   523     	resolvedClient =
       
   524         	iCRServer.LoadPlugin1LC( aWorkerAo.SipClient().Uid(),
       
   525         							 aWorkerAo.ResolverUid() );
       
   526 	__ASSERT_ALWAYS ( resolvedClient , User::Leave( KErrNoMemory ) );
       
   527     	}
       
   528     else
       
   529     	{
       
   530     	resolvedClient2 = 
       
   531     	    iCRServer.LoadPlugin2LC( aWorkerAo.SipClient().ImplementationUid() );
       
   532 	__ASSERT_ALWAYS ( resolvedClient2 , User::Leave( KErrNoMemory ) );
       
   533     	}
       
   534     
       
   535     TUid channelUid;   
       
   536     ChannelUidL( aWorkerAo.SipClient(), channelUid, request, resolvedClient );
       
   537     
       
   538     TUid nextHopUid( TUid::Null() );
       
   539     
       
   540     if ( iCRServer.RoutingTable().FindMatch( channelUid,
       
   541                                              iClientUid,
       
   542                                              nextHopUid ) )
       
   543         {
       
   544         iReceiver->RequestCompletedL( aWorkerAo.RequestId(),nextHopUid );
       
   545         }
       
   546     else // Client not running
       
   547         {
       
   548         CSIPCRRequestItem* requestItem = 
       
   549             CSIPCRRequestItem::NewLC( aWorkerAo.RequestId(), 
       
   550             						  aWorkerAo.SipClient(),
       
   551                                       channelUid,
       
   552                                       aWorkerAo.ResolverUid() ); 
       
   553         if ( resolvedClient ) 
       
   554          	{
       
   555          	AddToRequestQueueL( requestItem, *resolvedClient );
       
   556          	}
       
   557         else
       
   558         	{
       
   559         	AddToRequestQueueL( requestItem, *resolvedClient2 );
       
   560         	}
       
   561         CleanupStack::Pop( requestItem );
       
   562         }
       
   563     if ( resolvedClient )
       
   564     	{
       
   565     	CleanupStack::PopAndDestroy( resolvedClient );
       
   566     	}
       
   567     if ( resolvedClient2 )
       
   568     	{
       
   569     	CleanupStack::PopAndDestroy( resolvedClient2 );
       
   570     	}
       
   571     
       
   572     CleanupStack::PopAndDestroy( request );
       
   573     }
       
   574     
       
   575 // ----------------------------------------------------------------------------
       
   576 // CSIPCRServerSession::ChannelUidL
       
   577 // ----------------------------------------------------------------------------
       
   578 //
       
   579 void CSIPCRServerSession::ChannelUidL(
       
   580     const TSipClient& aClient,
       
   581     TUid& aChannelUid, 
       
   582     CSIPRequest* aRequest,
       
   583     CSIPResolvedClient* aResolvedClient )
       
   584     {
       
   585     if ( aClient.PluginType() == TSipClient::EFirstGeneration )
       
   586     	{
       
   587     	HBufC8* uri = aRequest->RequestURI()->ToTextL();
       
   588     	CleanupStack::PushL(uri);
       
   589     
       
   590     	CSIPContentTypeHeader* contenTypeHeader = 
       
   591         	static_cast<CSIPContentTypeHeader*>(
       
   592             	aRequest->Header(
       
   593                 	SIPStrings::StringF(SipStrConsts::EContentTypeHeader),0));
       
   594     	                
       
   595     	if(aResolvedClient)
       
   596 	{
       
   597 		aChannelUid = aResolvedClient->ChannelL(aRequest->Method(), 
       
   598                                                *uri, 
       
   599                                                aRequest->AllHeadersL(),
       
   600                                                aRequest->Content(),
       
   601                                                contenTypeHeader);
       
   602 	}
       
   603     	CleanupStack::PopAndDestroy(uri);
       
   604     	}
       
   605   	else
       
   606   		{
       
   607   		aChannelUid = aClient.Uid();
       
   608   		}
       
   609     }
       
   610 
       
   611 // ----------------------------------------------------------------------------
       
   612 // CSIPCRServerSession::HandleNextPendingRequestL
       
   613 // ----------------------------------------------------------------------------
       
   614 //  
       
   615 void CSIPCRServerSession::HandleNextPendingRequestL(
       
   616     CSipCrWorkerAo& /*aWorkerAo*/)
       
   617     {
       
   618     CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex);
       
   619 
       
   620     if ( iRequestQueue.Count() > 0 && !( iRequestQueue[0]->ConnectCalled() ) )
       
   621         {
       
   622         CSIPCRRequestItem* requestItem = iRequestQueue[ 0 ];
       
   623     	if ( requestItem->Client().PluginType() == 
       
   624     	     TSipClient::EFirstGeneration )
       
   625     		{
       
   626     		CSIPResolvedClient* resolvedClient =
       
   627         	    iCRServer.LoadPlugin1LC( requestItem->Client().Uid(),
       
   628                                          requestItem->ResolverUid() );
       
   629             ConnectL( *requestItem, *resolvedClient );
       
   630         	CleanupStack::PopAndDestroy( resolvedClient );                    
       
   631     		}
       
   632         else
       
   633         	{
       
   634         	CSIPResolvedClient2* resolvedClient2 =
       
   635         	    iCRServer.LoadPlugin2LC( requestItem->Client().ImplementationUid() );
       
   636             ConnectL( *requestItem, *resolvedClient2 );
       
   637         	CleanupStack::PopAndDestroy( resolvedClient2 ); 
       
   638         	}
       
   639         }
       
   640     
       
   641     CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex  
       
   642     }
       
   643 
       
   644 // ----------------------------------------------------------------------------
       
   645 // CSIPCRServerSession::CreateRequestId
       
   646 // ----------------------------------------------------------------------------
       
   647 //
       
   648 TUint32 CSIPCRServerSession::CreateRequestId()
       
   649     {
       
   650    	if (iRequestIdCounter < KMaxTUint32)
       
   651 		{
       
   652 		iRequestIdCounter++;
       
   653 		}
       
   654 	else
       
   655 		{
       
   656 		iRequestIdCounter = 1;
       
   657 		}
       
   658 	return iRequestIdCounter;
       
   659     }
       
   660     
       
   661 // ----------------------------------------------------------------------------
       
   662 // CSIPCRServerSession::FindUid
       
   663 // ----------------------------------------------------------------------------
       
   664 //    
       
   665 TBool CSIPCRServerSession::FindUid(
       
   666     const RArray<TSipClient>& aUids,
       
   667     TSipClient& aUid,
       
   668     TBool aRomBased,
       
   669     TBool aConnected)
       
   670     {
       
   671     TInt found = EFalse;
       
   672     for (TInt i=0; i < aUids.Count() && !found; i++)
       
   673         {
       
   674         const TSipClient& client = aUids[i];
       
   675         TBool connected = iCRServer.RoutingTable().HasUid(client.Uid());
       
   676         if ( client.RomBased() == aRomBased && connected == aConnected )
       
   677             {
       
   678             if ( aConnected || client.AllowStarting() )
       
   679                 {
       
   680                 aUid.SetUid( client.Uid() );
       
   681                 aUid.SetAllowStarting( client.AllowStarting() );
       
   682                 aUid.SetPluginType( client.PluginType() );
       
   683                 aUid.SetRomBased( client.RomBased() );
       
   684                 aUid.SetImplementationUid( client.ImplementationUid() );
       
   685                 found = ETrue;
       
   686                 }
       
   687             }
       
   688         }
       
   689     return found;    
       
   690     }
       
   691    
       
   692 // ----------------------------------------------------------------------------
       
   693 // CSIPCRServerSession::CreateWorkerThreadL
       
   694 // ----------------------------------------------------------------------------
       
   695 //   
       
   696 void CSIPCRServerSession::CreateWorkerThreadL(
       
   697     CSipCrWorkerAo* aWorkerAo,
       
   698     ThreadFunctionPtr aThreadFunctionPtr)
       
   699     {
       
   700     TName threadName(KWorkerThreadName);
       
   701     threadName.AppendNum(static_cast<TUint64>(Math::Random()),EHex);
       
   702 	RThread thread;
       
   703     TInt err = thread.Create(threadName,
       
   704                              aThreadFunctionPtr,
       
   705                              KDefaultStackSize,
       
   706                              NULL, // Use the same heap as the main thread
       
   707                              aWorkerAo);
       
   708     User::LeaveIfError(err);
       
   709     CleanupClosePushL(thread);
       
   710     aWorkerAo->StartThreadL(thread);
       
   711     err = iWorkerAos.Append(aWorkerAo);
       
   712     if (err != KErrNone)
       
   713         {
       
   714         aWorkerAo->Cancel();
       
   715         User::Leave(err);
       
   716         }
       
   717     CleanupStack::PopAndDestroy(&thread);
       
   718     }
       
   719 
       
   720 // ----------------------------------------------------------------------------
       
   721 // CSIPCRServerSession::ChannelWorkerThreadFunction
       
   722 // ----------------------------------------------------------------------------
       
   723 //	
       
   724 TInt CSIPCRServerSession::ChannelWorkerThreadFunction(TAny* aPtr)
       
   725     {
       
   726     return WorkerThreadFunctionImpl(aPtr,
       
   727         &CSIPCRServerSession::ChannelImplementationL);
       
   728     }
       
   729 
       
   730 // ----------------------------------------------------------------------------
       
   731 // CSIPCRServerSession::ConnectWorkerThreadFunction
       
   732 // ----------------------------------------------------------------------------
       
   733 //  
       
   734 TInt CSIPCRServerSession::ConnectWorkerThreadFunction(TAny* aPtr)
       
   735     {
       
   736     return WorkerThreadFunctionImpl(aPtr,
       
   737         &CSIPCRServerSession::HandleNextPendingRequestL);
       
   738     }
       
   739 
       
   740 // ----------------------------------------------------------------------------
       
   741 // CSIPCRServerSession::WorkerThreadFunctionImpl
       
   742 // ----------------------------------------------------------------------------
       
   743 //    
       
   744 TInt CSIPCRServerSession::WorkerThreadFunctionImpl(
       
   745     TAny* aPtr,
       
   746     WorkerFunctionPtr aWorkerFunctionPtr)
       
   747     {
       
   748     CSipCrWorkerAo* workerAo = 
       
   749         reinterpret_cast<CSipCrWorkerAo*>(aPtr);
       
   750     TInt err = KErrNoMemory;
       
   751     CTrapCleanup* cleanupStack = CTrapCleanup::New();
       
   752     if (cleanupStack)
       
   753         {
       
   754         TRAP(err, SIPStrings::OpenL());
       
   755         if (!err)
       
   756             {
       
   757             TRAP(err, (workerAo->Session().*aWorkerFunctionPtr)(*workerAo));
       
   758             SIPStrings::Close();
       
   759             REComSession::FinalClose(); // For each thread separately
       
   760             }
       
   761         }
       
   762     delete cleanupStack;
       
   763     return err;
       
   764     }
       
   765 
       
   766 // ----------------------------------------------------------------------------
       
   767 // CSIPCRServerSession::ProtectedAddToRequestQueueL
       
   768 // ----------------------------------------------------------------------------
       
   769 //
       
   770 void CSIPCRServerSession::ProtectedAddToRequestQueueL(
       
   771     CSIPCRRequestItem* aRequestItem)
       
   772     {
       
   773     CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex);
       
   774     iRequestQueue.AppendL(aRequestItem);
       
   775     CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex
       
   776     }
       
   777 
       
   778 // ----------------------------------------------------------------------------
       
   779 // CSIPCRServerSession::ProtectedRemoveFromRequestQueue
       
   780 // ----------------------------------------------------------------------------
       
   781 //    
       
   782 void CSIPCRServerSession::ProtectedRemoveFromRequestQueue(
       
   783     CSIPCRRequestItem* aRequestItem)
       
   784     {
       
   785     iRequestQueueMutex.Wait();
       
   786     TInt index = iRequestQueue.Find(aRequestItem); 
       
   787     if (index >= 0)
       
   788         {
       
   789         iRequestQueue.Remove(index);
       
   790         }    
       
   791     iRequestQueueMutex.Signal();
       
   792     }
       
   793 
       
   794 // -----------------------------------------------------------------------------
       
   795 // CSIPCRServerSession::RemoveFromRequestQueue
       
   796 // -----------------------------------------------------------------------------
       
   797 //
       
   798 void CSIPCRServerSession::RemoveFromRequestQueue(TAny* aCleanupData)
       
   799 	{
       
   800     TSipCrRequestQueueCleanupData* cleanupData = 
       
   801         reinterpret_cast<TSipCrRequestQueueCleanupData*>(aCleanupData);
       
   802     cleanupData->iSession->ProtectedRemoveFromRequestQueue(
       
   803         cleanupData->iRequestItem);
       
   804 	}
       
   805 
       
   806 // End of File