--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/csock/cs_connectionservimpl.cpp Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,419 @@
+// 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:
+//
+
+/**
+ @file
+ @released since 399
+*/
+
+#include <es_sock.h>
+#include <comms-infras/es_connectionserv.h>
+#include <comms-infras/es_availability.h>
+#include <comms-infras/es_connectionservermessages.h>
+#include "cs_connectionservimpl.h"
+#include <connpref.h>
+#include <comms-infras/ss_log.h>
+#include <rsshared.h>
+#include <es_ver.h>
+
+
+using namespace ConnectionServ;
+
+CConnectionServImpl::CConnectionServImpl(RConnectionServ& aCS) :
+ iConnectionServ(aCS)
+/**
+ Empty ctor
+ */
+ {
+ LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: CConnectionServImpl() tid %d"), this, (TUint)RThread().Id()); );
+ }
+
+
+CConnectionServImpl* CConnectionServImpl::NewL(RConnectionServ& aCS)
+ {
+ LOG( ESockLog::Printf(_L8("CConnectionServImpl : NewL() tid %d"), (TUint)RThread().Id()); );
+ CConnectionServImpl* inst = new(ELeave) CConnectionServImpl(aCS);
+ return inst;
+ }
+
+
+CConnectionServImpl::~CConnectionServImpl()
+/**
+ Closes the comms manager sub-session
+
+ Clean up resources then drop to base class
+ */
+ {
+ LOG( ESockLog::Printf(_L8("CConnectionServImpl%08x: ~CConnectionServImpl() tid %d"), this, (TUint)RThread().Id()); );
+
+ // Stop any active queries and remove them from the active scheduler.
+
+ // This is a lot cheaper on ROM than implementing server-side code to handle shutdown
+
+ CancelAccessPointStatusQuery();
+ delete iAccessPointStatusRequest;
+
+ CancelAccessPointNotification();
+ delete iAccessPointNotificationRequest;
+ }
+
+
+//
+// Access Point Status
+//
+
+void CConnectionServImpl::AccessPointStatusQuery(const CConnectionServParameterBundle& aQuery, CConnectionServParameterBundle& aResult, TRequestStatus& aStatus)
+/**
+Retrieve information from the Tier(s) specified in the Connect function about the availability of one or more services.
+aQuery is an in parameter. A client adds a query parameter set to specify the Access Point or group of Access Points
+ it wishes to enquire about and adds one or more parameter sets to carry the information they are interested to retrieve
+ for each Access Points
+aResult is an out parameter. The Connection Server populates this bundle with information about the access points that
+ matched the query.
+The time taken to perform this action depends on the implementation in the stack plug-in that serves the request
+*/
+ {
+ LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: AccessPointStatusQuery() tid %d"), this, (TUint)RThread().Id()); );
+
+ if(iAccessPointStatusRequest && iAccessPointStatusRequest->IsActive())
+ {
+ // complete the request with failure
+ TRequestStatus* status = &aStatus;
+ User::RequestComplete(status, KErrInUse);
+ return;
+ }
+
+ if(!iAccessPointStatusRequest)
+ {
+ // Delegate the call to the active object.. NewL creates and sets up the object..
+ // We give it a pointer to this so it can call SendReceive.
+ // We only hold onto the pointer to it so we can send a cancel to it.
+ TRAPD(result, iAccessPointStatusRequest = CAccessPointStatusRequest::NewL(*this) );
+ if(result)
+ {
+ // complete the request with failure
+ TRequestStatus* status = &aStatus;
+ User::RequestComplete(status, KErrArgument);
+ return;
+ }
+ }
+
+ // Delegate the call to the active object.. NewL creates and sets up the object and
+ // adds it to the active scheduler.
+ // Once it's finished it'll take itself off and delete itself.
+ // We only hold onto the pointer to it so we can send a cancel to it.
+ iAccessPointStatusRequest->Start(aQuery,aResult,aStatus);
+ }
+
+
+void CConnectionServImpl::CancelAccessPointStatusQuery()
+/**
+Tell the Connection Server we are cancelling our status query request. If no query is active, does nothing.
+*/
+ {
+ LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: CancelAccessPointStatusQuery() tid %d"), this, (TUint)RThread().Id()); );
+ if(iAccessPointStatusRequest)
+ {
+ // this will cause it to clean itself up (i.e. forward the cancel to the server then remove itself from the scheduler)
+ iAccessPointStatusRequest->Cancel();
+ }
+ else
+ {
+ LOG( ESockLog::Printf(_L8("Tried to cancel inactive query. Ignoring.")); );
+ }
+ }
+
+
+//
+// Access Point Notification
+//
+
+void CConnectionServImpl::AccessPointNotification(const CConnectionServParameterBundle& aQuery, MAccessPointNotificationObserver& aObserver)
+/**
+As for GetAvailability, but will notify regularly of changes to availability of requested Access Point(s).
+The aQuery defines a view of the access points, as soon as this view is established all its contents are reported
+ (i.e. we get initial status), after that, Access Points entering or leaving the view get reported to the observer.
+Queueing of multiple events happens automatically server side
+MAccessPointNotificationObserver contains a Notify(CConnectionServParameterBundle aResult) method and an Error() method to catch
+ errors from this function
+*/
+ {
+ LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: AccessPointNotification() tid %d"), this, (TUint)RThread().Id()); );
+
+ if(iAccessPointNotificationRequest && iAccessPointNotificationRequest->IsActive())
+ {
+ // complete the request with failure
+ aObserver.AccessPointNotificationError(KErrInUse);
+ return;
+ }
+
+ if(!iAccessPointNotificationRequest)
+ {
+ // Delegate the call to the active object.. NewL creates and sets up the object..
+ // We give it a pointer to this so it can call SendReceive.
+ // We only hold onto the pointer to it so we can send a cancel to it.
+ TRAPD(result, iAccessPointNotificationRequest = CAccessPointNotificationRequest::NewL(*this) );
+ if(result)
+ {
+ // complete the request with failure
+ aObserver.AccessPointNotificationError(KErrArgument);
+ return;
+ }
+ }
+
+ // Delegate the call to the active object.. NewL creates and sets up the object and
+ // adds it to the active scheduler.
+ // Once it's finished it'll take itself off the scheduler.
+ // We only hold onto the pointer to it so we can send a cancel to it.
+ iAccessPointNotificationRequest->Start(aQuery,aObserver);
+ }
+
+
+void CConnectionServImpl::CancelAccessPointNotification()
+/**
+Tell the Connection Server we are cancelling our notification session. If no notification session is active, does nothing.
+*/
+ {
+ LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: CancelAccessPointNotification() tid %d"), this, (TUint)RThread().Id()); );
+ if(iAccessPointNotificationRequest && iAccessPointNotificationRequest->IsActive())
+ {
+ // this will cause it to clean itself up (i.e. forward the cancel to the server then remove itself from the scheduler)
+ iAccessPointNotificationRequest->Cancel();
+ }
+ else
+ {
+ LOG( ESockLog::Printf(_L8("Tried to cancel inactive query. Ignoring.")); );
+ }
+
+ }
+
+
+
+
+
+
+
+CAccessPointStatusRequest::CAccessPointStatusRequest(CConnectionServImpl& aImpl):
+ CActive(CActive::EPriorityStandard), iConnectionServImpl(aImpl)
+ {
+ }
+
+CAccessPointStatusRequest::~CAccessPointStatusRequest()
+ {
+ iQueryBuffer.Close();
+ iResultBuffer.Close();
+ }
+
+void CAccessPointStatusRequest::ConstructL()
+ {
+ User::LeaveIfError(iQueryBuffer.Create(KInitialBufferSize));
+ User::LeaveIfError(iResultBuffer.Create(KInitialBufferSize));
+ }
+
+/* static*/
+CAccessPointStatusRequest* CAccessPointStatusRequest::NewL(CConnectionServImpl& aImpl)
+ {
+ CAccessPointStatusRequest *inst = new(ELeave) CAccessPointStatusRequest(aImpl);
+ inst->ConstructL();
+ return inst;
+ }
+
+void CAccessPointStatusRequest::Start(const CConnectionServParameterBundle& aQuery, CConnectionServParameterBundle& aResult, TRequestStatus& aStatus)
+/**
+ *
+ *
+ */
+ {
+ CActiveScheduler::Add(this);
+
+ iResult = &aResult;
+ iClientRequest = &aStatus;
+
+ TInt ret = CConnectionServImpl::EnsureBufferIsBigEnough(iQueryBuffer,aQuery.Length());
+
+ if(ret == KErrNone)
+ {
+ iQueryBuffer.SetLength(0);
+ ret = aQuery.Store(iQueryBuffer);
+ }
+
+ if (ret != KErrNone)
+ {
+ LOG( ESockLog::Printf(_L8("CAccessPointStatusRequest %08x: Start() tid %d failed when storing parameter bundle in serialization buffer: %d"), this, (TUint)RThread().Id(), ret); );
+ CompleteClientRequest(ret);
+ return;
+ }
+
+ iSentRequest = ECMAccessPointStatusQuery_DoThenGetResultOrSize;
+ iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(&iQueryBuffer, &iResultBuffer),iStatus);
+ SetActive();
+ }
+
+void CAccessPointStatusRequest::RunL()
+ {
+ TInt result = iStatus.Int();
+ if(result == KErrNone)
+ {
+ // all is well. let's deserialise result buffer into result bundle..
+ result = iResult->Load(iResultBuffer);
+ }
+ else
+ if(result > KErrNone && // result held error or required buffer length
+ iSentRequest == ECMAccessPointStatusQuery_DoThenGetResultOrSize )
+ {
+ // ok so it finished but buffer isn't big enough.. so (re)allocate and re-call
+ result = CConnectionServImpl::EnsureBufferIsBigEnough(iResultBuffer,result);
+
+ if(result == KErrNone)
+ {
+ iSentRequest = ECMAccessPointStatusQuery_GetResult;
+ iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(&iResultBuffer),iStatus);
+ SetActive();
+ return;
+ }
+ }
+
+ CompleteClientRequest(result);
+ }
+
+TInt CConnectionServImpl::EnsureBufferIsBigEnough(RBuf8& aBufToCheck, TUint aSize)
+ {
+ return (aBufToCheck.MaxSize() < aSize) ? aBufToCheck.ReAlloc(aSize) : KErrNone ;
+ }
+
+
+void CAccessPointStatusRequest::CompleteClientRequest(TInt aError)
+ {
+ User::RequestComplete(iClientRequest, aError);
+// CActiveScheduler::Remove(this);
+ }
+
+void CAccessPointStatusRequest::DoCancel()
+ {
+ iSentRequest = ECMAccessPointStatusQuery_Cancel;
+ iConnectionServImpl.SendReceive(iSentRequest);
+ CompleteClientRequest(KErrCancel);
+ }
+
+TInt CAccessPointStatusRequest::RunError(TInt aError)
+ {
+ CompleteClientRequest(aError);
+
+ // Error has gone to client.. No need to error the ActiveScheduler
+ return KErrNone;
+ }
+
+
+
+
+
+CAccessPointNotificationRequest::CAccessPointNotificationRequest(CConnectionServImpl& aImpl):
+ CActive(CActive::EPriorityStandard), iConnectionServImpl(aImpl)
+ {
+ }
+
+void CAccessPointNotificationRequest::ConstructL()
+ {
+ User::LeaveIfError(iResultBuffer.Create(KInitialBufferSize));
+ }
+
+/* static*/
+CAccessPointNotificationRequest* CAccessPointNotificationRequest::NewL(CConnectionServImpl& aImpl)
+ {
+ CAccessPointNotificationRequest *inst = new(ELeave) CAccessPointNotificationRequest(aImpl);
+ inst->ConstructL();
+ return inst;
+ }
+
+void CAccessPointNotificationRequest::Start(const CConnectionServParameterBundle& aQuery, MAccessPointNotificationObserver& aObserver)
+ {
+ CActiveScheduler::Add(this);
+
+ iObserver = &aObserver;
+
+ TInt ret = CConnectionServImpl::EnsureBufferIsBigEnough(iQueryBuffer,aQuery.Length());
+
+ if(ret == KErrNone)
+ {
+ iQueryBuffer.SetLength(0);
+ ret = aQuery.Store(iQueryBuffer);
+ }
+
+ if (ret != KErrNone)
+ {
+ LOG( ESockLog::Printf(_L8("CAccessPointNotificationRequest %08x: Start() tid %d failed when storing parameter bundle in serialization buffer: %d"), this, (TUint)RThread().Id(), ret); );
+ iObserver->AccessPointNotificationError(KErrNoMemory);
+ return;
+ }
+
+ iSentRequest = ECMAccessPointNotification_SetupThenAwaitThenGetResultOrSize;
+ iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(&iQueryBuffer, &iResultBuffer),iStatus);
+ SetActive();
+ }
+
+
+void CAccessPointNotificationRequest::DoCancel()
+ {
+ iSentRequest = ECMAccessPointNotification_Cancel;
+ iConnectionServImpl.SendReceive(iSentRequest);
+ iObserver->AccessPointNotificationError(KErrCancel);
+ }
+
+void CAccessPointNotificationRequest::RunL()
+ {
+ TInt result = iStatus.Int();
+ if(result == KErrNone)
+ {
+ // all is well. let's deserialise result buffer into result bundle..
+ CConnectionServParameterBundle *bundle = CConnectionServParameterBundle::LoadL(iResultBuffer);
+
+ // issue next request immediately
+ iSentRequest = ECMAccessPointNotification_AwaitThenGetResultOrSize;
+ iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(0,&iResultBuffer),iStatus);
+ SetActive();
+
+ // report notification to observer
+ iObserver->AccessPointNotification(bundle);
+ return;
+ }
+ else
+ if(result > KErrNone && // result held error or required buffer length
+ iSentRequest == ECMAccessPointNotification_SetupThenAwaitThenGetResultOrSize ||
+ iSentRequest == ECMAccessPointNotification_AwaitThenGetResultOrSize)
+ {
+ // ok so it finished but buffer isn't big enough.. so (re)allocate and re-call
+ result = CConnectionServImpl::EnsureBufferIsBigEnough(iResultBuffer,result);
+
+ if(result == KErrNone)
+ {
+ iSentRequest = ECMAccessPointNotification_GetResult;
+ iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(0,&iResultBuffer),iStatus);
+ SetActive();
+ return;
+ }
+ }
+
+ iObserver->AccessPointNotificationError(result);
+ }
+
+TInt CAccessPointNotificationRequest::RunError(TInt aError)
+ {
+ iObserver->AccessPointNotificationError(aError);
+
+ // Error has gone to client.. No need to error the ActiveScheduler
+ return KErrNone;
+ }
+
+