datacommsserver/esockserver/csock/cs_connectionservimpl.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2006-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 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @released since 399
       
    19 */
       
    20 
       
    21 #include <es_sock.h>
       
    22 #include <comms-infras/es_connectionserv.h>
       
    23 #include <comms-infras/es_availability.h>
       
    24 #include <comms-infras/es_connectionservermessages.h>
       
    25 #include "cs_connectionservimpl.h"
       
    26 #include <connpref.h>
       
    27 #include <comms-infras/ss_log.h>
       
    28 #include <rsshared.h>
       
    29 #include <es_ver.h>
       
    30 
       
    31 
       
    32 using namespace ConnectionServ;
       
    33 
       
    34 CConnectionServImpl::CConnectionServImpl(RConnectionServ& aCS) :
       
    35 	iConnectionServ(aCS)
       
    36 /** 
       
    37  Empty ctor
       
    38  */	
       
    39 	{
       
    40 	LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: CConnectionServImpl() tid %d"), this, (TUint)RThread().Id()); );
       
    41 	}
       
    42 
       
    43 
       
    44 CConnectionServImpl* CConnectionServImpl::NewL(RConnectionServ& aCS)
       
    45 	{
       
    46 	LOG( ESockLog::Printf(_L8("CConnectionServImpl : NewL() tid %d"), (TUint)RThread().Id()); );
       
    47 	CConnectionServImpl* inst = new(ELeave) CConnectionServImpl(aCS);
       
    48 	return inst;
       
    49 	}
       
    50 
       
    51 
       
    52 CConnectionServImpl::~CConnectionServImpl()
       
    53 /** 
       
    54  Closes the comms manager sub-session 
       
    55 
       
    56  Clean up resources then drop to base class
       
    57  */
       
    58 	{
       
    59 	LOG( ESockLog::Printf(_L8("CConnectionServImpl%08x: ~CConnectionServImpl() tid %d"), this, (TUint)RThread().Id()); );
       
    60 
       
    61 	// Stop any active queries and remove them from the active scheduler.
       
    62 
       
    63 	// This is a lot cheaper on ROM than implementing server-side code to handle shutdown
       
    64 
       
    65 	CancelAccessPointStatusQuery();
       
    66 	delete iAccessPointStatusRequest;
       
    67 
       
    68 	CancelAccessPointNotification();
       
    69 	delete iAccessPointNotificationRequest;
       
    70 	}
       
    71 
       
    72 
       
    73 //
       
    74 // Access Point Status
       
    75 //
       
    76 
       
    77 void CConnectionServImpl::AccessPointStatusQuery(const CConnectionServParameterBundle& aQuery, CConnectionServParameterBundle& aResult, TRequestStatus& aStatus)
       
    78 /**
       
    79 Retrieve information from the Tier(s) specified in the Connect function about the availability of one or more services.  
       
    80 aQuery is an in parameter.  A client adds a query parameter set to specify the Access Point or group of Access Points
       
    81 	it wishes to enquire about and adds one or more parameter sets to carry the information they are interested to retrieve
       
    82 	for each Access Points
       
    83 aResult is an out parameter. The Connection Server populates this bundle with information about the access points that
       
    84 	matched the query.
       
    85 The time taken to perform this action depends on the implementation in the stack plug-in that serves the request
       
    86 */
       
    87 	{
       
    88 	LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: AccessPointStatusQuery() tid %d"), this, (TUint)RThread().Id()); );
       
    89 
       
    90 	if(iAccessPointStatusRequest && iAccessPointStatusRequest->IsActive())
       
    91 		{
       
    92 		// complete the request with failure
       
    93 		TRequestStatus* status = &aStatus;
       
    94     	User::RequestComplete(status, KErrInUse);
       
    95 		return;
       
    96 		}
       
    97 
       
    98 	if(!iAccessPointStatusRequest)
       
    99 		{
       
   100 		// Delegate the call to the active object.. NewL creates and sets up the object..
       
   101 		// We give it a pointer to this so it can call SendReceive.
       
   102 		// We only hold onto the pointer to it so we can send a cancel to it.
       
   103 		TRAPD(result, iAccessPointStatusRequest = CAccessPointStatusRequest::NewL(*this) );
       
   104 		if(result)
       
   105 			{
       
   106 			// complete the request with failure
       
   107 			TRequestStatus* status = &aStatus;
       
   108 	    	User::RequestComplete(status, KErrArgument);
       
   109 	    	return;
       
   110 			}
       
   111 		}
       
   112 
       
   113 	// Delegate the call to the active object.. NewL creates and sets up the object and
       
   114 	//    adds it to the active scheduler.
       
   115 	// 		Once it's finished it'll take itself off and delete itself.
       
   116 	// We only hold onto the pointer to it so we can send a cancel to it.
       
   117 	iAccessPointStatusRequest->Start(aQuery,aResult,aStatus);
       
   118 	}
       
   119 
       
   120 
       
   121 void CConnectionServImpl::CancelAccessPointStatusQuery()
       
   122 /**
       
   123 Tell the Connection Server we are cancelling our status query request. If no query is active, does nothing.
       
   124 */
       
   125 	{
       
   126 	LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: CancelAccessPointStatusQuery() tid %d"), this, (TUint)RThread().Id()); );
       
   127 	if(iAccessPointStatusRequest)
       
   128 		{
       
   129 		// this will cause it to clean itself up (i.e. forward the cancel to the server then remove itself from the scheduler)
       
   130 		iAccessPointStatusRequest->Cancel();
       
   131 		}
       
   132 	else
       
   133 		{
       
   134 		LOG( ESockLog::Printf(_L8("Tried to cancel inactive query. Ignoring.")); );
       
   135 		}
       
   136 	}
       
   137 
       
   138 
       
   139 //
       
   140 // Access Point Notification
       
   141 //
       
   142 
       
   143 void CConnectionServImpl::AccessPointNotification(const CConnectionServParameterBundle& aQuery, MAccessPointNotificationObserver& aObserver)
       
   144 /**
       
   145 As for GetAvailability, but will notify regularly of changes to availability of requested Access Point(s).
       
   146 The aQuery defines a view of the access points, as soon as this view is established all its contents are reported
       
   147  (i.e. we get initial status), after that, Access Points entering or leaving the view get reported to the observer.
       
   148 Queueing of multiple events happens automatically server side
       
   149 MAccessPointNotificationObserver contains a Notify(CConnectionServParameterBundle aResult) method and an Error() method to catch
       
   150 	errors from this function
       
   151 */
       
   152 	{
       
   153 	LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: AccessPointNotification() tid %d"), this, (TUint)RThread().Id()); );
       
   154 
       
   155 	if(iAccessPointNotificationRequest && iAccessPointNotificationRequest->IsActive())
       
   156 		{
       
   157 		// complete the request with failure
       
   158 		aObserver.AccessPointNotificationError(KErrInUse);
       
   159 		return;
       
   160 		}
       
   161 
       
   162 	if(!iAccessPointNotificationRequest)
       
   163 		{
       
   164 		// Delegate the call to the active object.. NewL creates and sets up the object..
       
   165 		// We give it a pointer to this so it can call SendReceive.
       
   166 		// We only hold onto the pointer to it so we can send a cancel to it.
       
   167 		TRAPD(result, iAccessPointNotificationRequest = CAccessPointNotificationRequest::NewL(*this) );
       
   168 		if(result)
       
   169 			{
       
   170 			// complete the request with failure
       
   171 			aObserver.AccessPointNotificationError(KErrArgument);
       
   172 			return;
       
   173 			}
       
   174 		}
       
   175 
       
   176 	// Delegate the call to the active object.. NewL creates and sets up the object and
       
   177 	//    adds it to the active scheduler.
       
   178 	// 		Once it's finished it'll take itself off the scheduler.
       
   179 	// We only hold onto the pointer to it so we can send a cancel to it.
       
   180 	iAccessPointNotificationRequest->Start(aQuery,aObserver);
       
   181 	}
       
   182 
       
   183 
       
   184 void CConnectionServImpl::CancelAccessPointNotification()
       
   185 /**
       
   186 Tell the Connection Server we are cancelling our notification session. If no notification session is active, does nothing.
       
   187 */
       
   188 	{	
       
   189 	LOG( ESockLog::Printf(_L8("CConnectionServImpl %08x: CancelAccessPointNotification() tid %d"), this, (TUint)RThread().Id()); );
       
   190 	if(iAccessPointNotificationRequest && iAccessPointNotificationRequest->IsActive())
       
   191 		{
       
   192 		// this will cause it to clean itself up (i.e. forward the cancel to the server then remove itself from the scheduler)
       
   193 		iAccessPointNotificationRequest->Cancel();
       
   194 		}
       
   195 	else
       
   196 		{
       
   197 		LOG( ESockLog::Printf(_L8("Tried to cancel inactive query. Ignoring.")); );
       
   198 		}
       
   199 
       
   200 	}
       
   201 
       
   202 
       
   203 
       
   204 
       
   205 
       
   206 
       
   207 
       
   208 CAccessPointStatusRequest::CAccessPointStatusRequest(CConnectionServImpl& aImpl):
       
   209 	CActive(CActive::EPriorityStandard), iConnectionServImpl(aImpl)
       
   210 	{
       
   211 	}
       
   212 
       
   213 CAccessPointStatusRequest::~CAccessPointStatusRequest()
       
   214 	{
       
   215 	iQueryBuffer.Close();
       
   216 	iResultBuffer.Close();
       
   217 	}
       
   218 
       
   219 void CAccessPointStatusRequest::ConstructL()
       
   220 	{
       
   221 	User::LeaveIfError(iQueryBuffer.Create(KInitialBufferSize));
       
   222 	User::LeaveIfError(iResultBuffer.Create(KInitialBufferSize));
       
   223 	}
       
   224 
       
   225 /* static*/
       
   226 CAccessPointStatusRequest* CAccessPointStatusRequest::NewL(CConnectionServImpl& aImpl)
       
   227 	{
       
   228 	CAccessPointStatusRequest *inst = new(ELeave) CAccessPointStatusRequest(aImpl);
       
   229 	inst->ConstructL();
       
   230 	return inst;
       
   231 	}
       
   232 
       
   233 void CAccessPointStatusRequest::Start(const CConnectionServParameterBundle& aQuery, CConnectionServParameterBundle& aResult, TRequestStatus& aStatus)
       
   234 /**
       
   235  *
       
   236  *
       
   237  */
       
   238 	{
       
   239 	CActiveScheduler::Add(this);
       
   240 
       
   241 	iResult = &aResult;
       
   242 	iClientRequest = &aStatus;
       
   243 
       
   244 	TInt ret = CConnectionServImpl::EnsureBufferIsBigEnough(iQueryBuffer,aQuery.Length());
       
   245 
       
   246 	if(ret == KErrNone)
       
   247 		{
       
   248 		iQueryBuffer.SetLength(0);
       
   249 		ret = aQuery.Store(iQueryBuffer);
       
   250 		}
       
   251 
       
   252 	if (ret != KErrNone)
       
   253 		{
       
   254 		LOG( ESockLog::Printf(_L8("CAccessPointStatusRequest %08x: Start() tid %d failed when storing parameter bundle in serialization buffer: %d"), this, (TUint)RThread().Id(), ret); );
       
   255 		CompleteClientRequest(ret);
       
   256 		return;
       
   257 		}
       
   258 
       
   259 	iSentRequest = ECMAccessPointStatusQuery_DoThenGetResultOrSize;
       
   260 	iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(&iQueryBuffer,  &iResultBuffer),iStatus);
       
   261 	SetActive();
       
   262 	}
       
   263 
       
   264 void CAccessPointStatusRequest::RunL()
       
   265 	{
       
   266 	TInt result = iStatus.Int();
       
   267 	if(result == KErrNone)
       
   268 		{
       
   269 		// all is well. let's deserialise result buffer into result bundle..
       
   270 		result = iResult->Load(iResultBuffer);
       
   271 		}
       
   272 	else
       
   273 	if(result > KErrNone &&  // result held error or required buffer length
       
   274        iSentRequest == ECMAccessPointStatusQuery_DoThenGetResultOrSize )
       
   275 		{
       
   276 		// ok so it finished but buffer isn't big enough.. so (re)allocate and re-call
       
   277 		result = CConnectionServImpl::EnsureBufferIsBigEnough(iResultBuffer,result);
       
   278 
       
   279 		if(result == KErrNone)
       
   280 			{
       
   281 			iSentRequest = ECMAccessPointStatusQuery_GetResult;
       
   282 			iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(&iResultBuffer),iStatus);
       
   283 			SetActive();
       
   284 			return;
       
   285 			}
       
   286 		}
       
   287 
       
   288 	CompleteClientRequest(result);
       
   289 	}
       
   290 
       
   291 TInt CConnectionServImpl::EnsureBufferIsBigEnough(RBuf8& aBufToCheck, TUint aSize)
       
   292 	{
       
   293 	return (aBufToCheck.MaxSize() < aSize) ? aBufToCheck.ReAlloc(aSize) : KErrNone ;
       
   294 	}
       
   295 
       
   296 
       
   297 void CAccessPointStatusRequest::CompleteClientRequest(TInt aError)
       
   298 	{
       
   299 	User::RequestComplete(iClientRequest, aError);
       
   300 //	CActiveScheduler::Remove(this); 
       
   301 	}
       
   302 
       
   303 void CAccessPointStatusRequest::DoCancel()
       
   304 	{
       
   305 	iSentRequest = ECMAccessPointStatusQuery_Cancel;
       
   306 	iConnectionServImpl.SendReceive(iSentRequest);
       
   307 	CompleteClientRequest(KErrCancel);
       
   308 	}
       
   309 
       
   310 TInt CAccessPointStatusRequest::RunError(TInt aError)
       
   311 	{
       
   312 	CompleteClientRequest(aError);
       
   313 	
       
   314 	// Error has gone to client.. No need to error the ActiveScheduler
       
   315 	return KErrNone;
       
   316 	}
       
   317 
       
   318 
       
   319 
       
   320 
       
   321 
       
   322 CAccessPointNotificationRequest::CAccessPointNotificationRequest(CConnectionServImpl& aImpl):
       
   323 	CActive(CActive::EPriorityStandard), iConnectionServImpl(aImpl)
       
   324 	{
       
   325 	}
       
   326 
       
   327 void CAccessPointNotificationRequest::ConstructL()
       
   328 	{
       
   329 	User::LeaveIfError(iResultBuffer.Create(KInitialBufferSize));
       
   330 	}
       
   331 
       
   332 /* static*/
       
   333 CAccessPointNotificationRequest* CAccessPointNotificationRequest::NewL(CConnectionServImpl& aImpl)
       
   334 	{
       
   335 	CAccessPointNotificationRequest *inst = new(ELeave) CAccessPointNotificationRequest(aImpl);
       
   336 	inst->ConstructL();
       
   337 	return inst;
       
   338 	}
       
   339 
       
   340 void CAccessPointNotificationRequest::Start(const CConnectionServParameterBundle& aQuery, MAccessPointNotificationObserver& aObserver)
       
   341 	{
       
   342 	CActiveScheduler::Add(this);
       
   343 
       
   344 	iObserver = &aObserver;
       
   345 
       
   346 	TInt ret = CConnectionServImpl::EnsureBufferIsBigEnough(iQueryBuffer,aQuery.Length());
       
   347 
       
   348 	if(ret == KErrNone)
       
   349 		{
       
   350 		iQueryBuffer.SetLength(0);
       
   351 		ret = aQuery.Store(iQueryBuffer);
       
   352 		}
       
   353 
       
   354 	if (ret != KErrNone)
       
   355 		{
       
   356 		LOG( ESockLog::Printf(_L8("CAccessPointNotificationRequest %08x: Start() tid %d failed when storing parameter bundle in serialization buffer: %d"), this, (TUint)RThread().Id(), ret); );
       
   357 		iObserver->AccessPointNotificationError(KErrNoMemory);
       
   358 		return;
       
   359 		}
       
   360 
       
   361 	iSentRequest = ECMAccessPointNotification_SetupThenAwaitThenGetResultOrSize;
       
   362 	iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(&iQueryBuffer,  &iResultBuffer),iStatus);
       
   363 	SetActive();
       
   364 	}
       
   365 
       
   366 
       
   367 void CAccessPointNotificationRequest::DoCancel()
       
   368 	{
       
   369 	iSentRequest = ECMAccessPointNotification_Cancel;
       
   370 	iConnectionServImpl.SendReceive(iSentRequest);
       
   371 	iObserver->AccessPointNotificationError(KErrCancel);
       
   372 	}
       
   373 
       
   374 void CAccessPointNotificationRequest::RunL()
       
   375 	{
       
   376 	TInt result = iStatus.Int();
       
   377 	if(result == KErrNone)
       
   378 		{
       
   379 		// all is well. let's deserialise result buffer into result bundle..
       
   380 		CConnectionServParameterBundle *bundle = CConnectionServParameterBundle::LoadL(iResultBuffer);
       
   381 
       
   382 		// issue next request immediately
       
   383 		iSentRequest = ECMAccessPointNotification_AwaitThenGetResultOrSize;
       
   384 		iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(0,&iResultBuffer),iStatus);
       
   385 		SetActive();
       
   386 
       
   387 		// report notification to observer
       
   388 		iObserver->AccessPointNotification(bundle);
       
   389 		return;
       
   390 		}
       
   391 	else
       
   392 	if(result > KErrNone &&  // result held error or required buffer length
       
   393        iSentRequest == ECMAccessPointNotification_SetupThenAwaitThenGetResultOrSize ||
       
   394 	   iSentRequest == ECMAccessPointNotification_AwaitThenGetResultOrSize)
       
   395 		{
       
   396 		// ok so it finished but buffer isn't big enough.. so (re)allocate and re-call
       
   397 		result = CConnectionServImpl::EnsureBufferIsBigEnough(iResultBuffer,result);
       
   398 
       
   399 		if(result == KErrNone)
       
   400 			{
       
   401 			iSentRequest = ECMAccessPointNotification_GetResult;
       
   402 			iConnectionServImpl.SendReceive(iSentRequest, TIpcArgs(0,&iResultBuffer),iStatus);
       
   403 			SetActive();
       
   404 			return;
       
   405 			}
       
   406 		}
       
   407 
       
   408 	iObserver->AccessPointNotificationError(result);
       
   409 	}
       
   410 
       
   411 TInt CAccessPointNotificationRequest::RunError(TInt aError)
       
   412 	{
       
   413 	iObserver->AccessPointNotificationError(aError);
       
   414 	
       
   415 	// Error has gone to client.. No need to error the ActiveScheduler
       
   416 	return KErrNone;
       
   417 	}
       
   418 
       
   419