diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/ClientResolver/Server/src/CSIPCRServerSession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/ClientResolver/Server/src/CSIPCRServerSession.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,806 @@ +// 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 : CSIPCRServerSession.cpp +// Part of : SIP Client Resolver +// Version : 1.0 +// + + + +// INCLUDES +#include +#include "CSipCRServerSession.h" +#include "CSIPCRRoutingTable.h" +#include "CSIPClientResolver.h" +#include "CSIPCRITCUtility.h" +#include "CSIPCRSessionReceiver.h" +#include "CSipCRServer.h" +#include "sipCRclientserver.h" +#include "CSIPCRRequestItem.h" +#include "siprequest.h" +#include "sipresponse.h" +#include "TSipClient.h" +#include "sipresolvedclient.h" +#include "sipcontenttypeheader.h" +#include "sipstrconsts.h" +#include "sipstrings.h" +#include "uricontainer.h" +#include "SIPCRSerializer.h" +#include "sipresolvedclient2.h" +#include "sipcrworkerao.h" +#include "sipcrrequestqueuecleanupdata.h" + +const TUint K480ResponseCode = 480; +const TUint K503ResponseCode = 503; + +_LIT(KWorkerThreadName, "SIPClientResolverSessionWorker"); + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::NewL +// ---------------------------------------------------------------------------- +// +CSIPCRServerSession* CSIPCRServerSession::NewL(CSIPCRServer& aCRServer) + { + CSIPCRServerSession* self = CSIPCRServerSession::NewLC(aCRServer); + CleanupStack::Pop (self); + return self; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::NewLC +// ---------------------------------------------------------------------------- +// +CSIPCRServerSession* CSIPCRServerSession::NewLC(CSIPCRServer& aCRServer) + { + CSIPCRServerSession* self = new(ELeave)CSIPCRServerSession(aCRServer); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::CSIPCRServerSession +// ---------------------------------------------------------------------------- +// +CSIPCRServerSession::CSIPCRServerSession(CSIPCRServer& aCRServer) + : iClientUid(TUid::Null()), + iClientUidSet(EFalse), + iCRServer(aCRServer) + { + iCRServer.IncrementSessions(); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ConstructL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ConstructL() + { + User::LeaveIfError(iRequestQueueMutex.CreateLocal()); + iReceiver = CSIPCRSessionReceiver::NewL(iCRServer.ITCUtility()); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::~CSIPCRServerSession +// ---------------------------------------------------------------------------- +// +CSIPCRServerSession::~CSIPCRServerSession () + { + iWorkerAos.ResetAndDestroy(); + delete iReceiver; + iRequestQueue.ResetAndDestroy(); + iCRServer.DecrementSessions(); + if (iClientUidSet) + { + iCRServer.RoutingTable().Remove(iClientUid); + } + iRequestQueueMutex.Close(); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ServiceL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ServiceL(const RMessage2& aMessage) + { + DoServiceL(aMessage.Function(),aMessage); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::WorkerAoRequestCompleted +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::WorkerAoRequestCompleted(CSipCrWorkerAo* aWorkerAo) + { + TInt err = aWorkerAo->CompletionCode(); + TUint32 requestId = aWorkerAo->RequestId(); + if (err != KErrNone && requestId > 0) + { + TRAP_IGNORE(iReceiver->ErrorReceivedL(requestId,err)) + } + TInt index = iWorkerAos.Find(aWorkerAo); + if (index >= 0) + { + iWorkerAos.Remove(index); + } + delete aWorkerAo; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::RoutingEntryAddedL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::RoutingEntryAddedL(const TUid& aUid) + { + CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex); + + // Complete pending requests for aUid + CSIPCRRequestItem* requestItem = NULL; + for (TInt i=iRequestQueue.Count()-1; i >= 0; i--) + { + requestItem = iRequestQueue[i]; + if (requestItem->ChannelUid() == aUid) + { + TUint32 requestId = requestItem->RequestId(); + TUid nextHopUid(TUid::Null()); + if (iCRServer.RoutingTable().FindMatch(aUid,iClientUid,nextHopUid)) + { + iReceiver->RequestCompletedL(requestId,nextHopUid); + } + else + { + iReceiver->ErrorReceivedL(requestId,KErrNotFound); + } + ProtectedRemoveFromRequestQueue( requestItem ); + delete requestItem; + } + } + + CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex + + CSipCrWorkerAo* workerAo = CSipCrWorkerAo::NewLC(*this); + CreateWorkerThreadL(workerAo,ConnectWorkerThreadFunction); + CleanupStack::Pop(workerAo); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::DoServiceL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::DoServiceL (TInt aFunction, + const RMessage2& aMessage) + { + switch (aFunction) + { +#ifndef PLAT_SEC_TEST + case ESIPCRIpcSetClientUid: + SetUIDL(aMessage); break; + + case ESIPCRIpcRegister: + RegisterL(iCRServer.ITCUtility().ReadUIDL(aMessage)); break; + + case ESIPCRIpcDeregister: + DeregisterL(iCRServer.ITCUtility().ReadUIDL(aMessage)); break; + + case ESIPCRIpcClientReadyToReceive: // Async. Don't complete yet. + ClientReadyToReceiveL(aMessage); return; + + case ESIPCRIpcClientCancelReceive: + CancelClientReceiveL(); break; + + case ESIPCRIpcCancelRequest: + CancelRequestL(aMessage); break; + + case ESIPCRIpcCancelAllRequests: + CancelAllRequests(); break; + + case ESIPCRIpcChannel: + ChannelL(aMessage); break; + + case ESIPCRIpcChannelWithResolver: + ChannelWithResolverL(aMessage); break; + + case ESIPCRIpcClientReceiveSipResponse: + ClientReceiveSipResponseL(aMessage); break; + + default: + break; +#endif + } + iCRServer.ITCUtility().Complete(aMessage,KErrNone); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ChannelWithResolverL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ChannelWithResolverL(const RMessage2& aMessage) + { + CSIPRequest* request = CSIPRequest::NewLC(); + iCRServer.ITCUtility().ReadSIPRequestL(aMessage, *request); + TUid resolverUid = iCRServer.ITCUtility().ReadResolverUidL(aMessage); + TUint32 requestId = CreateRequestId(); + TSipClient clientUid(TUid::Null(),EFalse,EFalse); + ChannelL(requestId,*request,clientUid,resolverUid); + CleanupStack::PopAndDestroy(request); + iCRServer.ITCUtility().WriteRequestIdL(aMessage,requestId); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ChannelL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ChannelL(const RMessage2& aMessage) + { + CSIPRequest* request = CSIPRequest::NewLC(); + iCRServer.ITCUtility().ReadSIPRequestL(aMessage, *request); + + TUint32 requestId = CreateRequestId(); + iCRServer.ITCUtility().WriteRequestIdL(aMessage,requestId); + + TSipClient clientUid(TUid::Null(),EFalse,EFalse); + + CSIPResponse* response = ResolveClientL(*request,clientUid); + if (response) + { + CleanupStack::PushL(response); + iReceiver->AddErrorResponseL(requestId,response); + CleanupStack::PopAndDestroy(response); + } + else + { + ChannelL(requestId,*request,clientUid,TUid::Null()); + } + CleanupStack::PopAndDestroy(request); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::RegisterL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::RegisterL(const TUid& aChannelUid) + { + iCRServer.RoutingTable().AssociateL(iClientUid, aChannelUid); + iCRServer.RoutingEntryAddedL(aChannelUid); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::DeregisterL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::DeregisterL(const TUid& aChannelUid) + { + iCRServer.RoutingTable().Remove(aChannelUid); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::SetUIDL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::SetUIDL(const RMessage2& aMessage) + { + iClientUid = iCRServer.ITCUtility().ReadUIDL (aMessage); + iCRServer.RoutingTable().AddL(iClientUid); + iClientUidSet = ETrue; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ClientReadyToReceiveL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ClientReadyToReceiveL(const RMessage2& aMessage) + { + iReceiver->ClientReadyToReceiveL(aMessage); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ClientReceiveSipResponseL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ClientReceiveSipResponseL(const RMessage2& aMessage) + { + iReceiver->WriteSipResponseToClientL(aMessage); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::CancelRequestL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::CancelRequestL(const RMessage2& aMessage) + { + TUint32 requestId = iCRServer.ITCUtility().ReadRequestIdL(aMessage); + TBool found = EFalse; + + CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex); + + for (TInt i=iRequestQueue.Count()-1; i >=0 && !found; i--) + { + CSIPCRRequestItem* requestItem = iRequestQueue[i]; + if (requestItem->RequestId() == requestId) + { + CancelConnectL( requestItem ); + ProtectedRemoveFromRequestQueue( requestItem ); + delete requestItem; + found = ETrue; + } + } + + CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex + + iReceiver->RemoveByRequestId(requestId); + CSipCrWorkerAo* workerAo = CSipCrWorkerAo::NewLC(*this); + CreateWorkerThreadL(workerAo,ConnectWorkerThreadFunction); + CleanupStack::Pop(workerAo); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::CancelConnectL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::CancelConnectL( CSIPCRRequestItem* aRequestItem ) + { + if ( aRequestItem->Client().PluginType() == TSipClient::ESecondGeneration ) + { + if ( aRequestItem->ConnectCalled() ) + { + CSIPResolvedClient2* resolvedClient2 = + iCRServer.LoadPlugin2LC( + aRequestItem->Client().ImplementationUid() ); + resolvedClient2->CancelConnect( aRequestItem->Client().Uid() ); + CleanupStack::PopAndDestroy( resolvedClient2 ); + } + } + } + +// --------------------------------------------------------------------------- +// CSIPCRServerSession::AddToRequestQueueL +// --------------------------------------------------------------------------- +// +template void CSIPCRServerSession::AddToRequestQueueL( + CSIPCRRequestItem* aRequestItem, + T& aResolvedClient ) + { + __ASSERT_ALWAYS ( aRequestItem, User::Leave( KErrArgument ) ); + + // The request item needs to be in request queue + // in case the client connects immediately after calling ConnectL + // and the main thread examines the request queue + ProtectedAddToRequestQueueL( aRequestItem ); + TSipCrRequestQueueCleanupData cleanupData; + cleanupData.iSession = this; + cleanupData.iRequestItem = aRequestItem; + TCleanupItem cleanupItem( RemoveFromRequestQueue, &cleanupData ); + CleanupStack::PushL(cleanupItem); + TBool connectSucceeded = ConnectL( *aRequestItem, aResolvedClient ); + CleanupStack::Pop(); // cleanupItem, leave the item to queue + if ( !connectSucceeded ) + { + ProtectedRemoveFromRequestQueue( aRequestItem ); + delete aRequestItem; + } + } + +// --------------------------------------------------------------------------- +// CSIPCRServerSession::ConnectL +// --------------------------------------------------------------------------- +// +template TBool CSIPCRServerSession::ConnectL( + CSIPCRRequestItem& aRequestItem, + T& aResolvedClient ) + { + TBool success = ETrue; + TRAPD (err, aResolvedClient.ConnectL(aRequestItem.ChannelUid())); + if (err == KErrNoMemory) + { + User::Leave(err); + } + else if (err != KErrNone) + { + CSIPResponse* response = CSIPResponse::NewLC(K480ResponseCode, + SIPStrings::StringF(SipStrConsts::EPhraseTemporarilyNotAvailable)); + iReceiver->AddErrorResponseL(aRequestItem.RequestId(),response); + CleanupStack::Pop(response); + success = EFalse; + } + else + { + aRequestItem.SetConnectCalled(); + } + return success; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::CancelAllRequests +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::CancelAllRequests() + { + iRequestQueueMutex.Wait(); // Protect iRequestQueue with a mutex + iRequestQueue.ResetAndDestroy(); + iRequestQueueMutex.Signal(); + iReceiver->RemoveAll(); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::CancelClientReceiveL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::CancelClientReceiveL () + { + iReceiver->CancelClientReceiveL(); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ResolveClientL +// ---------------------------------------------------------------------------- +// +CSIPResponse* CSIPCRServerSession::ResolveClientL( + CSIPRequest& aRequest, + TSipClient& aUid) + { + RArray uids; + CleanupClosePushL(uids); + // Always execute the client resolving code in the main thread + // Multithreading the resolving code would be error prone and + // there is no performance reason to create a new thread for resolving. + CSIPResponse* response = + iCRServer.ClientResolver().FindUidL(aRequest,uids); + if (!response) + { + __ASSERT_ALWAYS(uids.Count() > 0, User::Leave(KErrNotFound)); + if (!FindUid(uids,aUid,ETrue,ETrue) && + !FindUid(uids,aUid,ETrue,EFalse) && + !FindUid(uids,aUid,EFalse,ETrue) && + !FindUid(uids,aUid,EFalse,EFalse)) + { + response = CSIPResponse::NewL(K503ResponseCode, + SIPStrings::StringF(SipStrConsts::EPhraseServiceUnavailable)); + } + } + CleanupStack::PopAndDestroy(1); // uids + return response; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ChannelL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ChannelL( + TUint32 aRequestId, + CSIPRequest& aRequest, + const TSipClient& aClient, + const TUid& aResolverUid) + { + // SIP request cannot be passed as such to the worker thread because + // the main and worker threads are using a different string pool. + // Instead SIP request is externalized in the main thread and + // internalized in the worker thread. + CBufBase* serializedRequest = SIPCRSerializer::ExternalizeL(aRequest); + CleanupStack::PushL(serializedRequest); + HBufC8* requestBody = aRequest.TakeContentOwnershipL(); + CleanupStack::PushL(requestBody); + + CSipCrWorkerAo* workerAo = + CSipCrWorkerAo::NewL( + aRequestId,serializedRequest,requestBody, + aClient,aResolverUid,*this); + + CleanupStack::Pop(requestBody); + CleanupStack::Pop(serializedRequest); + + CleanupStack::PushL(workerAo); + CreateWorkerThreadL(workerAo,ChannelWorkerThreadFunction); + CleanupStack::Pop(workerAo); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ChannelImplementationL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ChannelImplementationL( CSipCrWorkerAo& aWorkerAo ) + { + CSIPRequest* request = CSIPRequest::NewLC(); + SIPCRSerializer::InternalizeL( + aWorkerAo.SerializedSipRequest().Ptr( 0 ), *request ); + request->SetContent( aWorkerAo.GetSipRequestBody() ); + + CSIPResolvedClient2* resolvedClient2 = NULL; + CSIPResolvedClient* resolvedClient = NULL; + + if ( aWorkerAo.SipClient().PluginType() == TSipClient::EFirstGeneration ) + { + resolvedClient = + iCRServer.LoadPlugin1LC( aWorkerAo.SipClient().Uid(), + aWorkerAo.ResolverUid() ); + __ASSERT_ALWAYS ( resolvedClient , User::Leave( KErrNoMemory ) ); + } + else + { + resolvedClient2 = + iCRServer.LoadPlugin2LC( aWorkerAo.SipClient().ImplementationUid() ); + __ASSERT_ALWAYS ( resolvedClient2 , User::Leave( KErrNoMemory ) ); + } + + TUid channelUid; + ChannelUidL( aWorkerAo.SipClient(), channelUid, request, resolvedClient ); + + TUid nextHopUid( TUid::Null() ); + + if ( iCRServer.RoutingTable().FindMatch( channelUid, + iClientUid, + nextHopUid ) ) + { + iReceiver->RequestCompletedL( aWorkerAo.RequestId(),nextHopUid ); + } + else // Client not running + { + CSIPCRRequestItem* requestItem = + CSIPCRRequestItem::NewLC( aWorkerAo.RequestId(), + aWorkerAo.SipClient(), + channelUid, + aWorkerAo.ResolverUid() ); + if ( resolvedClient ) + { + AddToRequestQueueL( requestItem, *resolvedClient ); + } + else + { + AddToRequestQueueL( requestItem, *resolvedClient2 ); + } + CleanupStack::Pop( requestItem ); + } + if ( resolvedClient ) + { + CleanupStack::PopAndDestroy( resolvedClient ); + } + if ( resolvedClient2 ) + { + CleanupStack::PopAndDestroy( resolvedClient2 ); + } + + CleanupStack::PopAndDestroy( request ); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ChannelUidL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ChannelUidL( + const TSipClient& aClient, + TUid& aChannelUid, + CSIPRequest* aRequest, + CSIPResolvedClient* aResolvedClient ) + { + if ( aClient.PluginType() == TSipClient::EFirstGeneration ) + { + HBufC8* uri = aRequest->RequestURI()->ToTextL(); + CleanupStack::PushL(uri); + + CSIPContentTypeHeader* contenTypeHeader = + static_cast( + aRequest->Header( + SIPStrings::StringF(SipStrConsts::EContentTypeHeader),0)); + + if(aResolvedClient) + { + aChannelUid = aResolvedClient->ChannelL(aRequest->Method(), + *uri, + aRequest->AllHeadersL(), + aRequest->Content(), + contenTypeHeader); + } + CleanupStack::PopAndDestroy(uri); + } + else + { + aChannelUid = aClient.Uid(); + } + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::HandleNextPendingRequestL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::HandleNextPendingRequestL( + CSipCrWorkerAo& /*aWorkerAo*/) + { + CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex); + + if ( iRequestQueue.Count() > 0 && !( iRequestQueue[0]->ConnectCalled() ) ) + { + CSIPCRRequestItem* requestItem = iRequestQueue[ 0 ]; + if ( requestItem->Client().PluginType() == + TSipClient::EFirstGeneration ) + { + CSIPResolvedClient* resolvedClient = + iCRServer.LoadPlugin1LC( requestItem->Client().Uid(), + requestItem->ResolverUid() ); + ConnectL( *requestItem, *resolvedClient ); + CleanupStack::PopAndDestroy( resolvedClient ); + } + else + { + CSIPResolvedClient2* resolvedClient2 = + iCRServer.LoadPlugin2LC( requestItem->Client().ImplementationUid() ); + ConnectL( *requestItem, *resolvedClient2 ); + CleanupStack::PopAndDestroy( resolvedClient2 ); + } + } + + CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::CreateRequestId +// ---------------------------------------------------------------------------- +// +TUint32 CSIPCRServerSession::CreateRequestId() + { + if (iRequestIdCounter < KMaxTUint32) + { + iRequestIdCounter++; + } + else + { + iRequestIdCounter = 1; + } + return iRequestIdCounter; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::FindUid +// ---------------------------------------------------------------------------- +// +TBool CSIPCRServerSession::FindUid( + const RArray& aUids, + TSipClient& aUid, + TBool aRomBased, + TBool aConnected) + { + TInt found = EFalse; + for (TInt i=0; i < aUids.Count() && !found; i++) + { + const TSipClient& client = aUids[i]; + TBool connected = iCRServer.RoutingTable().HasUid(client.Uid()); + if ( client.RomBased() == aRomBased && connected == aConnected ) + { + if ( aConnected || client.AllowStarting() ) + { + aUid.SetUid( client.Uid() ); + aUid.SetAllowStarting( client.AllowStarting() ); + aUid.SetPluginType( client.PluginType() ); + aUid.SetRomBased( client.RomBased() ); + aUid.SetImplementationUid( client.ImplementationUid() ); + found = ETrue; + } + } + } + return found; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::CreateWorkerThreadL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::CreateWorkerThreadL( + CSipCrWorkerAo* aWorkerAo, + ThreadFunctionPtr aThreadFunctionPtr) + { + TName threadName(KWorkerThreadName); + threadName.AppendNum(static_cast(Math::Random()),EHex); + RThread thread; + TInt err = thread.Create(threadName, + aThreadFunctionPtr, + KDefaultStackSize, + NULL, // Use the same heap as the main thread + aWorkerAo); + User::LeaveIfError(err); + CleanupClosePushL(thread); + aWorkerAo->StartThreadL(thread); + err = iWorkerAos.Append(aWorkerAo); + if (err != KErrNone) + { + aWorkerAo->Cancel(); + User::Leave(err); + } + CleanupStack::PopAndDestroy(&thread); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ChannelWorkerThreadFunction +// ---------------------------------------------------------------------------- +// +TInt CSIPCRServerSession::ChannelWorkerThreadFunction(TAny* aPtr) + { + return WorkerThreadFunctionImpl(aPtr, + &CSIPCRServerSession::ChannelImplementationL); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ConnectWorkerThreadFunction +// ---------------------------------------------------------------------------- +// +TInt CSIPCRServerSession::ConnectWorkerThreadFunction(TAny* aPtr) + { + return WorkerThreadFunctionImpl(aPtr, + &CSIPCRServerSession::HandleNextPendingRequestL); + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::WorkerThreadFunctionImpl +// ---------------------------------------------------------------------------- +// +TInt CSIPCRServerSession::WorkerThreadFunctionImpl( + TAny* aPtr, + WorkerFunctionPtr aWorkerFunctionPtr) + { + CSipCrWorkerAo* workerAo = + reinterpret_cast(aPtr); + TInt err = KErrNoMemory; + CTrapCleanup* cleanupStack = CTrapCleanup::New(); + if (cleanupStack) + { + TRAP(err, SIPStrings::OpenL()); + if (!err) + { + TRAP(err, (workerAo->Session().*aWorkerFunctionPtr)(*workerAo)); + SIPStrings::Close(); + REComSession::FinalClose(); // For each thread separately + } + } + delete cleanupStack; + return err; + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ProtectedAddToRequestQueueL +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ProtectedAddToRequestQueueL( + CSIPCRRequestItem* aRequestItem) + { + CSIPCRITCUtility::WaitForMutexLC(iRequestQueueMutex); + iRequestQueue.AppendL(aRequestItem); + CleanupStack::PopAndDestroy(); // signals iRequestQueueMutex + } + +// ---------------------------------------------------------------------------- +// CSIPCRServerSession::ProtectedRemoveFromRequestQueue +// ---------------------------------------------------------------------------- +// +void CSIPCRServerSession::ProtectedRemoveFromRequestQueue( + CSIPCRRequestItem* aRequestItem) + { + iRequestQueueMutex.Wait(); + TInt index = iRequestQueue.Find(aRequestItem); + if (index >= 0) + { + iRequestQueue.Remove(index); + } + iRequestQueueMutex.Signal(); + } + +// ----------------------------------------------------------------------------- +// CSIPCRServerSession::RemoveFromRequestQueue +// ----------------------------------------------------------------------------- +// +void CSIPCRServerSession::RemoveFromRequestQueue(TAny* aCleanupData) + { + TSipCrRequestQueueCleanupData* cleanupData = + reinterpret_cast(aCleanupData); + cleanupData->iSession->ProtectedRemoveFromRequestQueue( + cleanupData->iRequestItem); + } + +// End of File