diff -r dc67b94625c5 -r 9d35fd98f273 accessoryservices/remotecontrolfw/server/src/targetsession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accessoryservices/remotecontrolfw/server/src/targetsession.cpp Mon Oct 04 02:28:24 2010 +0300 @@ -0,0 +1,331 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include "messagequeue.h" +#include "remconmessage.h" +#include "remconserver.h" +#include "server.h" +#include "targetsession.h" +#include "utils.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER); +#endif + +#ifdef _DEBUG +PANICCATEGORY("tgsession"); +#endif + +CRemConTargetSession* CRemConTargetSession::NewL(CRemConTargetClientProcess& aClientProcess, + CRemConServer& aServer, + CBearerManager& aBearerManager, + TUint aId) + { + LOG_STATIC_FUNC; + CRemConTargetSession* self = new(ELeave) CRemConTargetSession(aClientProcess, aServer, aBearerManager, aId); + CleanupStack::PushL(self); + self->ConstructL(); + CLEANUPSTACK_POP1(self); + return self; + } + +CRemConTargetSession::~CRemConTargetSession() + { + LOG_FUNC; + + // Tell the client process representation we've gone away- it may start its shutdown timer. + iClientProcess.TargetSessionClosed(*this); + } + +CRemConTargetSession::CRemConTargetSession(CRemConTargetClientProcess& aClientProcess, + CRemConServer& aServer, + CBearerManager& aBearerManager, + TUint aId) + : CRemConSession(aServer, aBearerManager, aId), + iClientProcess(aClientProcess) + { + LOG_FUNC; + } + +void CRemConTargetSession::ConstructL() + { + LOG_FUNC; + + BaseConstructL(iClientProcess.ClientInfo()); + + // Tell the client process representation about us (this will in turn inform the server). + LEAVEIFERRORL(iClientProcess.TargetSessionOpened(*this)); + + // Set our pointer into the connection history at the current/'Last' item. + // Can't do this til we've told the server we exist + iServer.SetConnectionHistoryPointer(Id()); + } + +TBool CRemConTargetSession::SupportedMessage(const CRemConMessage& aMsg) const + { + LOG_FUNC; + + // Return true if the message is for an interface supported by this session + return InterfaceSupported(aMsg.InterfaceUid()); + } + +TBool CRemConTargetSession::InterfaceSupported(TUid aInterfaceUid) const + { + LOG_FUNC; + LOG2(_L("\taInterfaceUid = 0x%08x, iInterestedAPIs = %d"), aInterfaceUid, iInterestedAPIs); + + TBool result = iInterestedAPIs ? (FindInterfaceByUid(aInterfaceUid) != NULL) : EFalse; + + LOG1(_L("result = %d"), result); + return result; + } + +void CRemConTargetSession::SetPlayerType(const RMessage2& aMessage) + { + LOG_FUNC; + + TInt err = aMessage.GetDesLength(1); + if (err >= 0) + { + TPlayerTypeInformation playerType; + RBuf8 playerName; + + TRAP(err, GetPlayerTypeAndNameL(aMessage, playerType, playerName)); + + if (err == KErrBadDescriptor) + { + PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); + playerName.Close(); + return; + } + else if (err == KErrArgument) + { + PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc); + playerName.Close(); + return; + } + else if (err == KErrNone) + { + // If player type is not set, then update iClientProcess with information. + // If player type is already set, then dont allow this to be changed for the client (panic the client if the information is different). + if (!iClientProcess.HasPlayerInformation()) + { + TRAP(err, iClientProcess.SetPlayerInformationL(playerType, playerName)); + } + else if (!iClientProcess.PlayerInformationMatches(playerType, playerName)) + { + PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicPlayerInfoAlreadySet); + playerName.Close(); + return; + } + } + + playerName.Close(); + } + else if (err == KErrBadDescriptor) + { + // The additional parameters are optional (i.e. old target clients won't provide them). + err = KErrNone; + } + + CompleteClient(aMessage, err); + } + +CRemConMessage* CRemConTargetSession::DoPrepareSendMessageL(const RMessage2& aMessage) + { + LOG_FUNC; + + // Get the data the client wants to send. + TUid interfaceUid; + TUint operationId; + + TRemConMessageSubType messageSubType; + RBuf8 sendDes; + if (!DoGetSendInfoLC(aMessage, interfaceUid, operationId, messageSubType, sendDes)) + { + // DoGetSendInfoLC() panicked the message + return NULL; + } + + CRemConMessage* msg = NULL; + + LOG(_L("\tTARGET send")); + + msg = CRemConMessage::NewL( + TRemConAddress(), // we don't know which remotes it's going to yet + ERemConResponse, // targets can only send responses + messageSubType, + interfaceUid, + operationId, + sendDes, // msg takes ownership + iClientProcess.Id(), // session id to match this response against the originating command + 0, // transaction id not yet known + ETrue); + CLEANUPSTACK_POP1(&sendDes); // now owned by msg + + return msg; + } + +void CRemConTargetSession::SendUnreliable(const RMessage2& aMessage) + { + LOG_FUNC; + + // Check we've had our features set... + if (!ClientAvailable()) + { + PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); + return; + } + + CRemConMessage* msg = NULL; + TRAPD(err, msg = DoCreateUnreliableMessageL(aMessage)); + CompleteClient(aMessage, err); + if (err == KErrNone) + { + ASSERT_DEBUG(iSendQueue); + if (iSending || !iSendQueue->IsEmpty()) + { + iSendQueue->Append(*msg); + } + else + { + SendToServer(*msg); + } + } + } + +CRemConMessage* CRemConTargetSession::DoCreateUnreliableMessageL(const RMessage2& aMessage) + { + LOG_FUNC; + + // Get the data the client wants to send. + TUid interfaceUid; + TUint operationId; + TRemConMessageSubType messageSubType; + RBuf8 sendDes; + DoGetSendInfoLC(aMessage, interfaceUid, operationId, messageSubType, sendDes); + + // Before we ask the server to send, we must set our ClientInfo + // correctly so the TSP can get information about the client. + iClientInfo.Message() = aMessage; + + CRemConMessage* msg = NULL; + + LOG(_L("\tTARGET send")); + + msg = CRemConMessage::NewL( + TRemConAddress(), // we don't know which remotes it's going to yet + ERemConResponse, // targets can only send responses + messageSubType, + interfaceUid, + operationId, + sendDes, // msg takes ownership + iClientProcess.Id(), // session id to match this response against the originating command + 0, // transaction id not yet known + EFalse); + CLEANUPSTACK_POP1(&sendDes); // now owned by msg + + return msg; + } + +void CRemConTargetSession::DoSendCancel() + { + LOG_FUNC; + + // We do not cancel any pending response messages, so don't need + // to notify the server here. + + NumRemotesToTry() = 0; + iSendError = KErrCancel; + CompleteSend(); + } + +void CRemConTargetSession::RegisterInterestedAPIs(const RMessage2& aMessage) + { + LOG_FUNC; + + // Check we haven't had our features set yet + if (ClientAvailable()) + { + PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); + return; + } + + CRemConInterfaceDetailsArray* interfaces = NULL; + TRAPD(err, interfaces = ExtractInterestedAPIsL(aMessage)); + + if(err == KErrNone) + { + // Ensure that none of these interfaces have already been registered by the client. + // Also note if bulk server is required. + TInt count = interfaces->Array().Count(); + TBool bulkServerRequired = EFalse; + for (TInt ix=0; ix < count; ++ix) + { + CRemConInterfaceDetails* details = interfaces->Array()[ix]; + ASSERT_DEBUG(details); + if (iClientProcess.IsInterfaceTypeRegisteredByAnotherSession(*this, details->Uid())) + { + // Destroy new interfaces and panic client. + delete interfaces; + PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientInterfaceAlreadyRegistered); + return; + } + else if (details->IsBulk()) + { + bulkServerRequired = ETrue; + } + } + + // Interfaces are OK, notify server if bulk server is required. + iInterestedAPIs = interfaces; + iClientProcess.InterfacesRegistered(); + if (bulkServerRequired) + { + iServer.BulkServerRequired(); + } + } + else + { + ASSERT_DEBUG(interfaces == NULL); + } + + CompleteClient(aMessage, err); + } + +void CRemConTargetSession::SendToServer(CRemConMessage& aMsg) + { + LOG_FUNC; + + // Set our completion members. + NumRemotes() = 0; + NumRemotesToTry() = 0; + SendError() = KErrNone; + + + iSending = (aMsg.IsReliableSend()) ? ESendingReliable: ESendingUnreliable; + + iServer.SendResponse(aMsg, iClientProcess); + } + +void CRemConTargetSession::DoReceive() + { + // Request messages from the server on behalf of the client. + // If there's anything waiting to be given to us, iClientProcess will call + // back to us with it. + iServer.ReceiveRequest(iClientProcess); + }