accessoryservices/remotecontrolfw/server/src/controllersession.cpp
changeset 74 9d35fd98f273
equal deleted inserted replaced
69:dc67b94625c5 74:9d35fd98f273
       
     1 // Copyright (c) 2010 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 the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <bluetooth/logger.h>
       
    17 #include "activehelper.h"
       
    18 #include "bearermanager.h"
       
    19 #include "controllersession.h"
       
    20 #include "messagequeue.h"
       
    21 #include "remconmessage.h"
       
    22 #include "remconserver.h"
       
    23 #include "server.h"
       
    24 #include "utils.h"
       
    25 
       
    26 #ifdef __FLOG_ACTIVE
       
    27 _LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER);
       
    28 #endif
       
    29 
       
    30 #ifdef _DEBUG
       
    31 PANICCATEGORY("ctsession");
       
    32 #endif
       
    33 
       
    34 
       
    35 CRemConControllerSession* CRemConControllerSession::NewL(CRemConServer& aServer,
       
    36 	CBearerManager& aBearerManager,
       
    37 	const TClientInfo& aClientInfo,
       
    38 	TUint aId)
       
    39 	{
       
    40 	LOG_STATIC_FUNC;
       
    41 	CRemConControllerSession* self = new(ELeave) CRemConControllerSession(aServer, aBearerManager, aId);
       
    42 	CleanupStack::PushL(self);
       
    43 	self->ConstructL(aClientInfo);
       
    44 	CLEANUPSTACK_POP1(self);
       
    45 	return self;
       
    46 	}
       
    47 
       
    48 CRemConControllerSession::~CRemConControllerSession()
       
    49 	{
       
    50 	LOG_FUNC;
       
    51 
       
    52 	delete iPendingMsgProcessor;
       
    53 
       
    54 	// we will need to tell the server which bearer this used to be connected to
       
    55 	// this enables the server to not inform a bearer that is already connected
       
    56 	// that its been connected
       
    57 	// Tell the server we've gone away- it may start its shutdown timer.
       
    58 	iServer.ControllerClientClosed(*this, iRemoteAddress.BearerUid());
       
    59 	iPlayerName.Close();
       
    60 	}
       
    61 
       
    62 CRemConControllerSession::CRemConControllerSession(CRemConServer& aServer, 
       
    63 	CBearerManager& aBearerManager,
       
    64 	TUint aId)
       
    65 	: CRemConSession(aServer, aBearerManager, aId)
       
    66 	{
       
    67 	LOG_FUNC;
       
    68 	}
       
    69 
       
    70 void CRemConControllerSession::ConstructL(const TClientInfo& aClientInfo)
       
    71 	{
       
    72 	LOG_FUNC;
       
    73 	
       
    74 	BaseConstructL(aClientInfo);
       
    75 
       
    76 	iPendingMsgProcessor = new (ELeave) CActiveHelper(*this);
       
    77 	
       
    78 	LEAVEIFERRORL(iServer.ControllerClientOpened(*this));
       
    79 
       
    80 	// Set our pointer into the connection history at the current/'Last' item.
       
    81 	// Can't do this til we've told the server we exist
       
    82 	iServer.SetConnectionHistoryPointer(Id());
       
    83 	}
       
    84 
       
    85 TBool CRemConControllerSession::SupportedMessage(const CRemConMessage& aMsg) const
       
    86 	{
       
    87 	LOG_FUNC;
       
    88 	LOG1(_L("\taMsg.InterfaceUid() = 0x%08x"), aMsg.InterfaceUid());
       
    89 
       
    90 	// Return true unless this is a command for an unsupported interface
       
    91 	TBool result = !(aMsg.MsgType() == ERemConCommand && !FindInterfaceByUid(aMsg.InterfaceUid()));
       
    92 
       
    93 	LOG1(_L("result = %d"), result);
       
    94 	return result;
       
    95 	}
       
    96 
       
    97 void CRemConControllerSession::SetPlayerType(const RMessage2& aMessage)
       
    98 	{
       
    99 	LOG_FUNC;
       
   100 
       
   101 	// Controller clients don't provide the additional parameters are optional,
       
   102 	// so we just complete the message with KErrNone.
       
   103 	CompleteClient(aMessage, KErrNone);
       
   104 	}
       
   105 
       
   106 void CRemConControllerSession::CompleteConnect(const TRemConAddress& aAddr, TInt aError)
       
   107 	{
       
   108 	LOG_FUNC;
       
   109 	LOG2(_L("\taError = %d, aAddr.BearerUid = 0x%08x"), aError, aAddr.BearerUid());
       
   110 
       
   111 	LOG1(_L("\tiRemoteAddress.BearerUid = 0x%08x"), iRemoteAddress.BearerUid());
       
   112 	LOG1(_L("\tiConnectBearerMsg.Handle = %d"), iConnectBearerMsg.Handle());
       
   113 
       
   114 	if ( iRemoteAddress == aAddr )
       
   115 		{
       
   116 		if ( iConnectBearerMsg.Handle() )
       
   117 			{
       
   118 			// We are a session that has an outstanding request on this specific 
       
   119 			// connection address.
       
   120 			CompleteClient(iConnectBearerMsg, aError);
       
   121 			}
       
   122 		else 
       
   123 			{
       
   124 			// Connect bearer message is not valid. 
       
   125 			// Check for pending messages.
       
   126 			CheckForPendingMsg();
       
   127 			}
       
   128 		}
       
   129 	}
       
   130 
       
   131 void CRemConControllerSession::CompleteDisconnect(const TRemConAddress& aAddr, TInt aError)
       
   132 	{
       
   133 	LOG_FUNC;
       
   134 	LOG2(_L("\taError = %d, aAddr.BearerUid = 0x%08x"), aError, aAddr.BearerUid());
       
   135 
       
   136 	LOG1(_L("\tiRemoteAddress.BearerUid = 0x%08x"), iRemoteAddress.BearerUid());
       
   137 	LOG1(_L("\tiDisconnectBearerMsg.Handle = %d"), iDisconnectBearerMsg.Handle());
       
   138 
       
   139 	if ( iRemoteAddress == aAddr )
       
   140 		{
       
   141 		if ( iDisconnectBearerMsg.Handle() )
       
   142 			{
       
   143 			// We are a session that has an outstanding request on this specific 
       
   144 			// connection address.
       
   145 			CompleteClient(iDisconnectBearerMsg, aError);
       
   146 			}
       
   147 		else 
       
   148 			{
       
   149 			// Diconnect bearer message is not valid. 
       
   150 			// Check for pending messages.
       
   151 			CheckForPendingMsg();
       
   152 			}
       
   153 
       
   154 		}
       
   155 	}
       
   156 
       
   157 void CRemConControllerSession::ProcessPendingMsgL()
       
   158 	{
       
   159 	LOG_FUNC;
       
   160 	if (!iPendingMsg.Handle())
       
   161 		{
       
   162 		// This means that the pending connect or disconnect message,
       
   163 		// has been cancelled by the time we got here.
       
   164 		// (It was cancelled between two following calls:
       
   165 		// iPendingMsgProcessor::Complete and iPendingMsgProcessor::RunL
       
   166 		return;
       
   167 		}
       
   168 
       
   169 	ServiceL(iPendingMsg);
       
   170 	if (iPendingMsg.Handle())
       
   171 		{
       
   172 		// This means that the pending msg has not been completed in ServiceL call.
       
   173 		// It was stored either in iConnectBearerMsg or iDisconnectBearerMsg member.
       
   174 		// This also means that this message is not "pending" any more 
       
   175 		// (as processing of its copy has been started). 
       
   176 		// However because the copy will get completed we need to 
       
   177 		// clean iPendingMsg.iHandle here
       
   178 		// To supress coverity error for uninitialized use of 'emptyMsg' coverity annotations
       
   179 		// are used as the in-line default constructor of RMessage2 doesn't initialize all member variables.
       
   180 		// coverity[var_decl]
       
   181 		RMessage2 emptyMsg;
       
   182 		iPendingMsg = emptyMsg;
       
   183 		}
       
   184 	}
       
   185 
       
   186 void CRemConControllerSession::CheckForPendingMsg() const
       
   187 	{
       
   188 	LOG_FUNC;
       
   189 	if (iPendingMsg.Handle())
       
   190 		{
       
   191 		ASSERT_DEBUG(iPendingMsgProcessor);
       
   192 		iPendingMsgProcessor->Complete();
       
   193 		}
       
   194 	}
       
   195 
       
   196 CRemConMessage* CRemConControllerSession::DoPrepareSendMessageL(const RMessage2& aMessage)
       
   197 	{
       
   198 	LOG_FUNC;
       
   199 
       
   200 	// Check we don't have a disconnect outstanding- this makes no sense from 
       
   201 	// a client viewpoint (they should cancel the disconnect first).
       
   202 	// [The client is allowed to have a connect request outstanding- the 
       
   203 	// bearer manager makes sure a bearer-level connect is not posted on the 
       
   204 	// same address twice.]
       
   205 	if ( iDisconnectBearerMsg.Handle() )
       
   206 		{
       
   207 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   208 		return NULL;
       
   209 		}
       
   210 
       
   211 	// Get the data the client wants to send.
       
   212 	TUid interfaceUid;
       
   213 	TUint operationId;
       
   214 
       
   215 	TRemConMessageSubType messageSubType;
       
   216 	RBuf8 sendDes;
       
   217 	if (!DoGetSendInfoLC(aMessage, interfaceUid, operationId, messageSubType, sendDes))
       
   218 		{
       
   219 		// DoGetSendInfoLC() panicked the message
       
   220 		return NULL;
       
   221 		}
       
   222 
       
   223 	CRemConMessage* msg = NULL;
       
   224 	LOG(_L("\tCONTROLLER send"));
       
   225 	if (  (messageSubType == ERemConNotifyCommandAwaitingInterim)
       
   226 	   || (messageSubType == ERemConNotifyCommandAwaitingChanged)
       
   227 		)
       
   228 		{
       
   229 		LOG(_L("\terror, not allowed to use Send() to send notify command"));
       
   230 		CleanupStack::PopAndDestroy(&sendDes);
       
   231 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc);
       
   232 		}
       
   233 	else
       
   234 		{
       
   235 		msg = CRemConMessage::NewL(
       
   236 				iRemoteAddress, // either specified (if we're connection-oriented) or null (we're connectionless- this field will be filled in by the TSP)
       
   237 				ERemConCommand, 
       
   238 				messageSubType,
       
   239 				interfaceUid,
       
   240 				operationId,
       
   241 				sendDes, // msg takes ownership
       
   242 				Id(), // session id for when the response comes back
       
   243 				0, // we let the bearer manager invent a new transaction id when the message gets to it
       
   244 				ETrue);
       
   245 		CLEANUPSTACK_POP1(&sendDes); // now owned by msg
       
   246 		}		
       
   247 
       
   248 	return msg;
       
   249 	}
       
   250 
       
   251 void CRemConControllerSession::SendUnreliable(const RMessage2& aMessage)
       
   252 	{
       
   253 	LOG_FUNC;
       
   254 
       
   255 	// Check we've had our features set...
       
   256 	if (!ClientAvailable())
       
   257 		{
       
   258 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   259 		return;
       
   260 		}
       
   261 
       
   262 	// Check we don't have a disconnect outstanding- this makes no sense from 
       
   263 	// a client viewpoint (they should cancel the disconnect first).
       
   264 	// [The client is allowed to have a connect request outstanding- the 
       
   265 	// bearer manager makes sure a bearer-level connect is not posted on the 
       
   266 	// same address twice.]
       
   267 	if ( iDisconnectBearerMsg.Handle() )
       
   268 		{
       
   269 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   270 		return;
       
   271 		}
       
   272 
       
   273 	CRemConMessage* msg = NULL;
       
   274 	TRAPD(err, msg = DoCreateUnreliableMessageL(aMessage));
       
   275 	CompleteClient(aMessage, err);
       
   276 	if (err == KErrNone)
       
   277 		{
       
   278 		ASSERT_DEBUG(iSendQueue);
       
   279 		if (iSending || !iSendQueue->IsEmpty())
       
   280 			{
       
   281 			iSendQueue->Append(*msg);
       
   282 			}
       
   283 		else
       
   284 			{
       
   285 			SendToServer(*msg);
       
   286 			}
       
   287 		}
       
   288 	}
       
   289 
       
   290 CRemConMessage* CRemConControllerSession::DoCreateUnreliableMessageL(const RMessage2& aMessage)
       
   291 	{
       
   292 	LOG_FUNC;
       
   293 
       
   294 	// Get the data the client wants to send.
       
   295 	TUid interfaceUid;
       
   296 	TUint operationId;
       
   297 	TRemConMessageSubType messageSubType;
       
   298 	RBuf8 sendDes;
       
   299 	DoGetSendInfoLC(aMessage, interfaceUid, operationId, messageSubType, sendDes);
       
   300 
       
   301 	// Before we ask the server to send, we must set our ClientInfo 
       
   302 	// correctly so the TSP can get information about the client. 
       
   303 	iClientInfo.Message() = aMessage;
       
   304 
       
   305 	CRemConMessage* msg = NULL;
       
   306 	
       
   307 	LOG(_L("\tCONTROLLER send"));
       
   308 	
       
   309 	// A client is not allowed to send an unreliable notify command.
       
   310 	if	(	(messageSubType == ERemConNotifyCommandAwaitingInterim)
       
   311 		||	(messageSubType == ERemConNotifyCommandAwaitingChanged)
       
   312 		)
       
   313 		{
       
   314 		LOG(_L8("\tNot allowed to send unreliable notify command"));
       
   315 		CleanupStack::PopAndDestroy(&sendDes);
       
   316 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc);
       
   317 		LEAVEL(KErrBadDescriptor);
       
   318 		}
       
   319 	
       
   320 	msg = CRemConMessage::NewL(
       
   321 		iRemoteAddress, // either specified (if we're connection-oriented) or null (we're connectionless- this field will be filled in by the TSP)
       
   322 		ERemConCommand, // controllers can only send commands
       
   323 		messageSubType,
       
   324 		interfaceUid,
       
   325 		operationId,
       
   326 		sendDes, // msg takes ownership
       
   327 		Id(), // session id for when the response comes back
       
   328 		0, // we let the bearer manager invent a new transaction id when the message gets to it
       
   329 		EFalse);
       
   330 	CLEANUPSTACK_POP1(&sendDes); // now owned by msg
       
   331 
       
   332 	return msg;
       
   333 	}
       
   334 
       
   335 void CRemConControllerSession::RegisterInterestedAPIs(const RMessage2& aMessage)
       
   336 	{
       
   337 	LOG_FUNC;
       
   338 	// No interfaces should have been registered yet!
       
   339 	ASSERT_DEBUG(iInterestedAPIs == NULL);
       
   340 	
       
   341 	TRAPD(err, iInterestedAPIs = ExtractInterestedAPIsL(aMessage));
       
   342 	
       
   343 	iServer.ControllerClientAvailable();
       
   344 
       
   345 	CompleteClient(aMessage, err);
       
   346 	}
       
   347 
       
   348 void CRemConControllerSession::GoConnectionOriented(const RMessage2& aMessage)
       
   349 	{
       
   350 	LOG_FUNC;
       
   351 
       
   352 	// Check we've had our features set...
       
   353 	if (!ClientAvailable())
       
   354 		{
       
   355 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   356 		return;
       
   357 		}
       
   358 
       
   359 	if ( !iRemoteAddress.IsNull() )
       
   360 		{
       
   361 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicAlreadyConnectionOriented);
       
   362 		return;
       
   363 		}
       
   364 
       
   365 	if ( iConnectBearerMsg.Handle() || iDisconnectBearerMsg.Handle() || iSendMsg.Handle())
       
   366 		{
       
   367 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   368 		return;
       
   369 		}
       
   370 	if (iSending != ENotSending)
       
   371 		{
       
   372 		DoSendCancel();
       
   373 		}
       
   374 	EmptySendQueue();
       
   375 	
       
   376 	// Get the desired address from the message and check it.
       
   377 	const TUid uid = TUid::Uid(aMessage.Int0());
       
   378 	LOG1(_L("\tuid = 0x%08x"), uid);
       
   379 	// Check the requested bearer exists.
       
   380 	TBool bearerExists = iBearerManager.BearerExists(uid);
       
   381 	if ( !bearerExists)
       
   382 		{
       
   383 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerPluginIncorrectInterface);
       
   384 		return;
       
   385 		}
       
   386 	// Check the bearer-specific part of the address.
       
   387 	TBuf8<TRemConAddress::KMaxAddrSize> buf;
       
   388 	TInt err = aMessage.Read(1, buf);
       
   389 	if ( err != KErrNone )
       
   390 		{
       
   391 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor);
       
   392 		return;
       
   393 		}
       
   394 
       
   395 	// Do security check- if this client won't be allowed to use the bearer 
       
   396 	// then fail the request. 
       
   397 	// NB This security check (repeated in debug at ConnectBearer and 
       
   398 	// DisconnectBearer time) is all that stands between a connection-oriented 
       
   399 	// client and the bearer, and is all the caps checking that RemCon does!
       
   400 	err = KErrPermissionDenied;
       
   401 	if ( iBearerManager.CheckPolicy(uid, aMessage) )
       
   402 		{
       
   403 		err = KErrNone;
       
   404 		}
       
   405 		
       
   406 		
       
   407 	// if alls well and we're connection oriented then set up as such
       
   408 	if (KErrNone == err)
       
   409 		{
       
   410 		// The client has passed all our checks- set our data member.
       
   411 		iRemoteAddress.BearerUid() = uid;
       
   412 		iRemoteAddress.Addr() = buf;
       
   413 		// tell the server
       
   414 		iServer.ClientGoConnectionOriented(*this,uid);
       
   415 		}
       
   416 				
       
   417 	CompleteClient(aMessage, err);
       
   418 	}
       
   419 
       
   420 void CRemConControllerSession::GoConnectionless(const RMessage2& aMessage)
       
   421 	{
       
   422 	LOG_FUNC;
       
   423 
       
   424 	// Check we've had our features set...
       
   425 	if (!ClientAvailable())
       
   426 		{
       
   427 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   428 		return;
       
   429 		}
       
   430 
       
   431 	if ( iRemoteAddress.IsNull() )
       
   432 		{
       
   433 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicNotConnectionOriented);
       
   434 		return;
       
   435 		}
       
   436 
       
   437 	if ( iConnectBearerMsg.Handle() || iDisconnectBearerMsg.Handle() || iSendMsg.Handle())
       
   438 		{
       
   439 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   440 		return;
       
   441 		}
       
   442 	
       
   443 	if (iSending != ENotSending)
       
   444 		{
       
   445 		DoSendCancel();
       
   446 		}
       
   447 	EmptySendQueue();
       
   448 	
       
   449 	// we will need to tell the server which bearer this used to be connected to
       
   450 	// this enables the server to not inform a bearer that is already connected
       
   451 	// that its been connected
       
   452 	TUid oldUid = iRemoteAddress.BearerUid();
       
   453 	
       
   454 	iRemoteAddress.BearerUid() = KNullUid;	
       
   455 
       
   456 	// tell the server
       
   457 	iServer.ClientGoConnectionless(*this, oldUid);
       
   458 
       
   459 	CompleteClient(aMessage, KErrNone);
       
   460 	}
       
   461 
       
   462 void CRemConControllerSession::ConnectBearer(const RMessage2& aMessage)
       
   463 	{
       
   464 	LOG_FUNC;
       
   465 
       
   466 	// Check we've had our features set...
       
   467 	if (!ClientAvailable())
       
   468 		{
       
   469 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   470 		return;
       
   471 		}
       
   472 
       
   473 	if ( iConnectBearerMsg.Handle() || iDisconnectBearerMsg.Handle() )
       
   474 		{
       
   475 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   476 		return;
       
   477 		}
       
   478 
       
   479 	if ( iRemoteAddress.IsNull() )
       
   480 		{
       
   481 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicNotConnectionOriented);
       
   482 		return;
       
   483 		}
       
   484 
       
   485 	// Check the requested bearer exists.
       
   486 	TBool bearerExists = iBearerManager.BearerExists(iRemoteAddress.BearerUid());
       
   487 	// This check was done at GoConnectionOriented time.
       
   488 	ASSERT_DEBUG(bearerExists);
       
   489 	// So was this one.
       
   490 	ASSERT_DEBUG(iBearerManager.CheckPolicy(iRemoteAddress.BearerUid(), aMessage));
       
   491 
       
   492 	// Check the state of our given connection at the bearer level. If it is: 
       
   493 	// -) disconnected request the connection to come up,
       
   494 	// -) connecting or disconnecting, add message to the queue of pending 
       
   495 	//		messages, and process it once connecting/disconnecting has been completed
       
   496 	// -) connected, complete the client's message,
       
   497 
       
   498 	TConnectionState conState;
       
   499 	conState = iServer.ConnectionState(iRemoteAddress);
       
   500 
       
   501 	if ( conState == EDisconnected )
       
   502 		{
       
   503 		// The bearer may indicate connection synchronously, so set this 
       
   504 		// message _before_ we ask them
       
   505 		iConnectBearerMsg = aMessage;
       
   506 		TInt err = iBearerManager.Connect(iRemoteAddress);
       
   507 		if ( err != KErrNone )
       
   508 			{
       
   509 			CompleteClient(iConnectBearerMsg, err);
       
   510 			}
       
   511 		}
       
   512 	else if ( conState == EDisconnecting ||  conState == EConnecting )
       
   513 		{
       
   514 		if ( iPendingMsg.Handle() )
       
   515 			{
       
   516 			PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   517 			return;
       
   518 			}
       
   519 		// Store the message, it will get processed later.
       
   520 		iPendingMsg = aMessage;
       
   521 		}
       
   522 	else // EConnected
       
   523 		{
       
   524 		CompleteClient(aMessage, KErrNone);
       
   525 		}
       
   526 		
       
   527 	}
       
   528 
       
   529 void CRemConControllerSession::ConnectBearerCancel(const RMessage2& aMessage)
       
   530 	{
       
   531 	LOG_FUNC;
       
   532 
       
   533 	// Check we've had our features set...
       
   534 	if (!ClientAvailable())
       
   535 		{
       
   536 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   537 		return;
       
   538 		}
       
   539 
       
   540 	if ( iConnectBearerMsg.Handle() )
       
   541 		{
       
   542 		CompleteClient(iConnectBearerMsg, KErrCancel);
       
   543 		}
       
   544 	else if ( iPendingMsg.Handle() && ( iPendingMsg.Function() == ERemConConnectBearer ))
       
   545 		{
       
   546 		CompleteClient(iPendingMsg, KErrCancel);
       
   547 		}
       
   548 		
       
   549 	CompleteClient(aMessage, KErrNone);
       
   550 	// At no point do we make any change to the processes going on underneath
       
   551 	// us- 'Cancel' APIs are just for cancelling interest in an async
       
   552 	// operation.
       
   553 	}
       
   554 
       
   555 void CRemConControllerSession::DisconnectBearer(const RMessage2& aMessage)
       
   556 	{
       
   557 	LOG_FUNC;
       
   558 
       
   559 	// Check we've had our features set...
       
   560 	if (!ClientAvailable())
       
   561 		{
       
   562 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   563 		return;
       
   564 		}
       
   565 
       
   566 	if ( iDisconnectBearerMsg.Handle() || iConnectBearerMsg.Handle() || iSendMsg.Handle())
       
   567 		{
       
   568 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   569 		return;
       
   570 		}
       
   571 
       
   572 	if ( iRemoteAddress.IsNull() )
       
   573 		{
       
   574 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicNotConnectionOriented);
       
   575 		return;
       
   576 		}
       
   577 
       
   578 	if (iSending != ENotSending)
       
   579 		{
       
   580 		DoSendCancel();
       
   581 		}
       
   582 	EmptySendQueue();
       
   583 	
       
   584 	// Check the requested bearer exists.
       
   585 	TBool bearerExists = iBearerManager.BearerExists(iRemoteAddress.BearerUid());
       
   586 	// This check was done at GoConnectionOriented time.
       
   587 	ASSERT_DEBUG(bearerExists);
       
   588 	// So was this one.
       
   589 	ASSERT_DEBUG(iBearerManager.CheckPolicy(iRemoteAddress.BearerUid(), aMessage));
       
   590 
       
   591 	// Check the state of the given connection. If it is:
       
   592 	// -) connected, request connection to go away,
       
   593 	// -) disconnected, compete the client's message,
       
   594 	// -) connecting or disconnecting, add message to the queue of pending 
       
   595 	//		messages, and process it once connecting/disconnecting has been completed
       
   596 
       
   597 	TInt err;
       
   598 	TConnectionState conState;
       
   599 	conState = iServer.ConnectionState(iRemoteAddress);
       
   600 
       
   601 	if ( conState == EConnected )
       
   602 		{
       
   603 		// The bearer may indicate disconnection synchronously, so set this 
       
   604 		// message _before_ we ask them
       
   605 		iDisconnectBearerMsg = aMessage;
       
   606 		err = iBearerManager.Disconnect(iRemoteAddress);
       
   607 		if ( err != KErrNone )
       
   608 			{
       
   609 			CompleteClient(iDisconnectBearerMsg, err);
       
   610 			}
       
   611 		}
       
   612 	else if ( conState == EDisconnecting ||  conState == EConnecting )
       
   613 		{
       
   614 		if ( iPendingMsg.Handle() )
       
   615 			{
       
   616 			PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   617 			return;
       
   618 			}
       
   619 		// Store the message, it will get processed later.
       
   620 		iPendingMsg = aMessage;
       
   621 		}
       
   622 	else //disconnected
       
   623 		{
       
   624 		CompleteClient(aMessage, KErrNone);	
       
   625 		}
       
   626 	}
       
   627 
       
   628 void CRemConControllerSession::DisconnectBearerCancel(const RMessage2& aMessage)
       
   629 	{
       
   630 	LOG_FUNC;
       
   631 
       
   632 	// Check we've had our features set...
       
   633 	if (!ClientAvailable())
       
   634 		{
       
   635 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   636 		return;
       
   637 		}
       
   638 
       
   639 	if ( iDisconnectBearerMsg.Handle() )
       
   640 		{
       
   641 		CompleteClient(iDisconnectBearerMsg, KErrCancel);
       
   642 		}
       
   643 	else if ( iPendingMsg.Handle() && (iPendingMsg.Function() == ERemConDisconnectBearer ))
       
   644 		{
       
   645 		CompleteClient(iPendingMsg, KErrCancel);
       
   646 		}
       
   647 		
       
   648 	CompleteClient(aMessage, KErrNone);
       
   649 	}
       
   650 
       
   651 /**
       
   652 Sends a notify message to the remote device.
       
   653 
       
   654 This function is intended for the RemCon controller client to send a notify
       
   655 command to the remote device.
       
   656 */
       
   657 void CRemConControllerSession::SendNotify(const RMessage2& aMessage)
       
   658 	{
       
   659 	LOG_FUNC;
       
   660 
       
   661 	// Check we're not already sending...
       
   662 	if ( iSendMsg.Handle())
       
   663 		{
       
   664 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicSendAlreadyOutstanding);
       
   665 		return;
       
   666 		}
       
   667 	
       
   668 	iSendMsg = aMessage;
       
   669 	
       
   670 	// Check we've had our features set...
       
   671 	if (!ClientAvailable())
       
   672 		{
       
   673 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
       
   674 		return;
       
   675 		}
       
   676 
       
   677 	// Check we don't have a disconnect outstanding- this makes no sense from 
       
   678 	// a client viewpoint (they should cancel the disconnect first).
       
   679 	// [The client is allowed to have a connect request outstanding- the 
       
   680 	// bearer manager makes sure a bearer-level connect is not posted on the 
       
   681 	// same address twice.]
       
   682 	if ( iDisconnectBearerMsg.Handle() )
       
   683 		{
       
   684 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding);
       
   685 		return;
       
   686 		}
       
   687 
       
   688 	TRAPD(err, DoSendNotifyL(aMessage));
       
   689 	if ( err != KErrNone )
       
   690 		{
       
   691 		CompleteClient(aMessage, err);
       
   692 		}
       
   693 	}
       
   694 
       
   695 /**
       
   696 @see CRemConControllerSession::SendNotify
       
   697 */
       
   698 void CRemConControllerSession::DoSendNotifyL(const RMessage2& aMessage)
       
   699 	{
       
   700 	LOG_FUNC;
       
   701 
       
   702 	// Get the data the client wants to send.
       
   703 	const TUid interfaceUid = TUid::Uid(aMessage.Int0());
       
   704 	LOG1(_L("\tinterfaceUid = 0x%08x"), interfaceUid);
       
   705 
       
   706 	if (aMessage.GetDesLengthL(1) != sizeof(TOperationInformation))
       
   707 		{
       
   708 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor);
       
   709 		return;
       
   710 		}
       
   711 
       
   712 	TPckgBuf<TOperationInformation> opInfoPckg;	
       
   713 	TInt err= aMessage.Read(
       
   714 			1, // location of the descriptor in the client's message (as we expect them to have set it up)
       
   715 			opInfoPckg, // descriptor to write to from client memory space
       
   716 			0 // offset into our descriptor to put the client's data
       
   717 			);
       
   718 	
       
   719 	if ( err != KErrNone )
       
   720 		{
       
   721 		LOG1(_L("\taMessage.Read = %d"), err);
       
   722 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor);
       
   723 		return;
       
   724 		}	
       
   725 	
       
   726 	const TUint operationId = opInfoPckg().iOperationId;
       
   727 	LOG1(_L("\toperationId = 0x%02x"), operationId);
       
   728 	
       
   729 	const TRemConMessageSubType messageSubType = opInfoPckg().iMessageSubType;
       
   730 	LOG1(_L("\tmessageSubType = 0x%02x"), messageSubType);
       
   731 	
       
   732 	const TUint dataLength = (TUint)aMessage.GetDesLengthL(2);
       
   733 	LOG1(_L("\tdataLength = %d"), dataLength);
       
   734 	
       
   735 	// If the client wanted to send some operation-associated data, read it 
       
   736 	// from them.
       
   737 	RBuf8 sendDes;
       
   738 	if ( dataLength != 0 )
       
   739 		{
       
   740 		sendDes.CreateL(dataLength);
       
   741 		TInt err = aMessage.Read(
       
   742 			2, // location of the descriptor in the client's message (as we expect them to have set it up)
       
   743 			sendDes, // descriptor to write to from client memory space
       
   744 			0 // offset into our descriptor to put the client's data
       
   745 			);
       
   746 		// NB We don't do LEAVEIFERRORL(aMessage.Read) because a bad client 
       
   747 		// descriptor is a panicking offence for them, not an 'error the 
       
   748 		// request' offence.
       
   749 		if ( err != KErrNone )
       
   750 			{
       
   751 			LOG1(_L("\taMessage.Read = %d"), err);
       
   752 			sendDes.Close();
       
   753 			PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor);
       
   754 			return;
       
   755 			}
       
   756 		}
       
   757 
       
   758 	// Before we ask the server to send, we must set our ClientInfo 
       
   759 	// correctly so the TSP can get information about the client. 
       
   760 	iClientInfo.Message() = aMessage;
       
   761 
       
   762 	CRemConMessage* msg = NULL;
       
   763 	
       
   764 	if (messageSubType != ERemConNotifyCommandAwaitingInterim)
       
   765 		{
       
   766 		sendDes.Close();
       
   767 		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc);
       
   768 		return;
       
   769 		}
       
   770 	
       
   771 	CleanupClosePushL(sendDes);
       
   772 	msg = CRemConMessage::NewL(
       
   773 			iRemoteAddress, // either specified (if we're connection-oriented) or null (we're connectionless- this field will be filled in by the TSP)
       
   774 			ERemConNotifyCommand, 
       
   775 			messageSubType,
       
   776 			interfaceUid,
       
   777 			operationId,
       
   778 			sendDes, // msg takes ownership
       
   779 			Id(), // session id for when the response comes back
       
   780 			0, // we let the bearer manager invent a new transaction id when the message gets to it
       
   781 			ETrue);	
       
   782 	CLEANUPSTACK_POP1(&sendDes); // now owned by msg
       
   783 	
       
   784 	LOG(_L("\tCONTROLLER send"));
       
   785 	ASSERT_DEBUG(iSendQueue);
       
   786 	if (iSending != ENotSending || !iSendQueue->IsEmpty())
       
   787 		{
       
   788 		iSendQueue->Append(*msg);
       
   789 		}
       
   790 	else
       
   791 		{
       
   792 		SendToServer(*msg);
       
   793 		}
       
   794 	}
       
   795 
       
   796 void CRemConControllerSession::SendToServer(CRemConMessage& aMsg)
       
   797 	{
       
   798 	LOG_FUNC;
       
   799 	
       
   800 	// Set our completion members.
       
   801 	NumRemotes() = 0;
       
   802 	NumRemotesToTry() = 0;
       
   803 	SendError() = KErrNone;
       
   804 
       
   805 	
       
   806 	iSending = (aMsg.IsReliableSend()) ? ESendingReliable: ESendingUnreliable;
       
   807 	
       
   808 	iServer.SendCommand(aMsg);
       
   809 	}
       
   810 
       
   811 void CRemConControllerSession::EmptySendQueue()
       
   812 	{
       
   813 	LOG_FUNC;
       
   814 
       
   815 	ASSERT_DEBUG(!iSendMsg.Handle())
       
   816 	ASSERT_DEBUG(iSendNextCallBack);
       
   817 	iSendNextCallBack->Cancel();
       
   818 	CRemConMessage* msg;
       
   819 	ASSERT_DEBUG(iSendQueue);
       
   820 	TSglQueIter<CRemConMessage>& iter = iSendQueue->SetToFirst();
       
   821 	while ((msg = iter++) != NULL)
       
   822 		{
       
   823 		iSendQueue->RemoveAndDestroy(*msg);
       
   824 		}
       
   825 	}
       
   826 
       
   827 void CRemConControllerSession::DoSendCancel()
       
   828 	{
       
   829 	LOG_FUNC;
       
   830 	// We must tell the server, and pull the CRemConMessage from the 
       
   831 	// 'outgoing pending TSP' queue if it's on it. If the TSP is currently 
       
   832 	// processing the CRemConMessage, we must tell it to stop before we 
       
   833 	// can complete the RMessage2 iSendMsg- the TSP might still be 
       
   834 	// dereferencing bits of it. (The TSP is given iSendMsg so it can 
       
   835 	// access the client's secure ID and do a capability check.)
       
   836 	// NB This only matters for commands- responses don't go through the 
       
   837 	// TSP.
       
   838 	// Not also that this processing *stops* this 
       
   839 	// CRemConSession::SendCancel method from being the very simple 'I'm 
       
   840 	// no longer interested in the completion of the asynchronous request' 
       
   841 	// type of API it (and all cancels) should be. It actually does work 
       
   842 	// as well. As long as this work is implemented _synchronously_, we 
       
   843 	// should be OK.
       
   844 	iServer.SendCancel(*this);
       
   845 
       
   846 	NumRemotesToTry() = 0;
       
   847 	iSendError = KErrCancel;
       
   848 	CompleteSend();
       
   849 	}
       
   850 
       
   851 void CRemConControllerSession::CompleteMessage(const CRemConMessage& aMessage)
       
   852 	{
       
   853 	LOG_FUNC;
       
   854 
       
   855 	switch (aMessage.MsgType())
       
   856 		{
       
   857 	case ERemConCommand:
       
   858 	case ERemConResponse:
       
   859 	case ERemConReject:
       
   860 		{
       
   861 		CompleteSend();
       
   862 		break;
       
   863 		}
       
   864 	case ERemConNotifyCommand:
       
   865 		{
       
   866 		CompleteSendNotify();
       
   867 		break;
       
   868 		}
       
   869 	default:
       
   870 		ASSERT_DEBUG(EFalse);
       
   871 		break;
       
   872 		}
       
   873 
       
   874 	}
       
   875 
       
   876 void CRemConControllerSession::DoReceive()
       
   877 	{
       
   878 	// Request messages from the server for this controller session.
       
   879 	// If there's anything waiting to be given to us, ReceiveRequest will call 
       
   880 	// back to us with it.
       
   881 	iServer.ReceiveRequest(*this);	
       
   882 	}
       
   883 
       
   884 void CRemConControllerSession::MrcmsoMessageSendResult(const CRemConMessage& aMessage, TInt aError)
       
   885 	{
       
   886 	LOG_FUNC;
       
   887 
       
   888 	// We should not already be sending a message to n remotes
       
   889 	ASSERT_DEBUG(NumRemotesToTry() == 0);
       
   890 
       
   891 	SendError() = aError;
       
   892 	CompleteMessage(aMessage);
       
   893 	}
       
   894 
       
   895 void CRemConControllerSession::MrcmsoMessageSendOneOrMoreAttempt(const CRemConMessage& /*aMessage*/, TUint aNumRemotes)
       
   896 	{
       
   897 	LOG_FUNC;
       
   898 
       
   899 	// We should not already be sending a message
       
   900 	ASSERT_DEBUG(NumRemotesToTry() == 0);
       
   901 
       
   902 	NumRemotes() = 0;
       
   903 	NumRemotesToTry() = aNumRemotes;
       
   904 	SendError() = KErrNone;
       
   905 	}
       
   906 
       
   907 void CRemConControllerSession::MrcmsoMessageSendOneOrMoreIncremental(const CRemConMessage& /*aMessage*/, TUint /*aNumRemotes*/)
       
   908 	{
       
   909 	LOG_FUNC;
       
   910 
       
   911 	// This method should never be called, as it is not required to support controller sessions.
       
   912 	ASSERT_DEBUG(EFalse);
       
   913 	}
       
   914 
       
   915 void CRemConControllerSession::MrcmsoMessageSendOneOrMoreAttemptFailed(const CRemConMessage& aMessage, TInt aError)
       
   916 	{
       
   917 	LOG_FUNC;
       
   918 
       
   919 	// We should not already be sending a message
       
   920 	ASSERT_DEBUG(NumRemotesToTry() == 0);
       
   921 
       
   922 	NumRemotes() = 0;
       
   923 	SendError() = aError;
       
   924 	CompleteMessage(aMessage);
       
   925 	}
       
   926 
       
   927 void CRemConControllerSession::MrcmsoMessageSendOneOrMoreResult(const CRemConMessage& aMessage, TInt aError)
       
   928 	{
       
   929 	LOG_FUNC;
       
   930 
       
   931 	// Ignore notification if client has been completed
       
   932 	if (NumRemotesToTry() > 0)
       
   933 		{
       
   934 		// Only set error if different from KErrNone
       
   935 		if (aError == KErrNone)
       
   936 			{
       
   937 			++NumRemotes();
       
   938 			}
       
   939 		else
       
   940 			{
       
   941 			SendError() = aError;
       
   942 			}
       
   943 
       
   944 		--NumRemotesToTry();
       
   945 		if (NumRemotesToTry() == 0)
       
   946 			{
       
   947 			CompleteMessage(aMessage);
       
   948 			}
       
   949 		}
       
   950 	}
       
   951 
       
   952 void CRemConControllerSession::MrcmsoMessageSendOneOrMoreAbandoned(const CRemConMessage& /*aMessage*/)
       
   953 	{
       
   954 	LOG_FUNC;
       
   955 
       
   956 	// This method should never be called, as it is not required to support controller sessions.
       
   957 	ASSERT_DEBUG(EFalse);
       
   958 	}