diff -r dc67b94625c5 -r 9d35fd98f273 accessoryservices/remotecontrolfw/server/src/targetclientprocess.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accessoryservices/remotecontrolfw/server/src/targetclientprocess.cpp Mon Oct 04 02:28:24 2010 +0300 @@ -0,0 +1,459 @@ +// 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 "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: +// Server-side representation of a target client, which may have multiple +// sessions associated with it. +// + + +#include +#include + +#include "server.h" +#include "bearermanager.h" +#include "remconmessage.h" +#include "targetsession.h" + +#include "targetclientprocess.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER); +#endif + +#ifdef _DEBUG +PANICCATEGORY("tgclient"); +#endif + +TBool TargetSessionCompareUsingSupportedInterface(const TUid* aInterfaceUid, const CRemConTargetSession& aSession) + { + return aSession.InterfaceSupported(*aInterfaceUid); + } + +TBool TargetSessionCompareUsingSupportedMessage(const CRemConMessage* aMessage, const CRemConTargetSession& aSession) + { + return aSession.SupportedMessage(*aMessage); + } + +CRemConTargetClientProcess* CRemConTargetClientProcess::NewLC(TClientInfo& aClientInfo, TRemConClientId aClientId, CRemConServer& aServer, CBearerManager& aBearerManager) + { + LOG_STATIC_FUNC + + CRemConTargetClientProcess* result = new (ELeave) CRemConTargetClientProcess(aClientInfo, aClientId, aServer, aBearerManager); + CleanupStack::PushL(result); + return result; + } + +CRemConTargetClientProcess::CRemConTargetClientProcess(TClientInfo& aClientInfo, TRemConClientId aClientId, CRemConServer& aServer, CBearerManager& aBearerManager) + : iClientInfo(aClientInfo), + iClientId(aClientId), + iServer(aServer), + iBearerManager(aBearerManager), + iPlayerInfoSet(EFalse), + iTargetSessions(KMaxNumberTargetSessions) + { + LOG_FUNC + } + +CRemConTargetClientProcess::~CRemConTargetClientProcess() + { + LOG_FUNC + + iPlayerName.Close(); + iTargetSessions.Close(); + iServer.TargetClientClosed(*this); + } + +CRemConTargetSession* CRemConTargetClientProcess::NewSessionL(TUint aSessionId) + { + LOG_FUNC + CRemConTargetSession* sess = NULL; + + // Only create a session if we havent reached our maximum. + if (TargetSessionCount() < KMaxNumberTargetSessions) + { + sess = CRemConTargetSession::NewL(*this, iServer, iBearerManager, aSessionId); + } + else + { + LEAVEIFERRORL(KErrOverflow); + } + + return sess; + } + + +TInt CRemConTargetClientProcess::TargetSessionOpened(CRemConTargetSession& aSession) + { + LOG_FUNC + LOG1(_L("\t&aSession = 0x%08x"), &aSession) + + // Register the session by appending it to our array and asking the server to + // make an item for it in the record of which points in the connection history + // sessions are interested in. + ASSERT(iTargetSessions.Count() < KMaxNumberTargetSessions); // Should have been caught by now. + + // The append should never fail because the RPointerArray was constructed with a granularity of + // KMaxNumberTargetSessions items. +#ifdef _DEBUG + TInt err = iTargetSessions.Append(&aSession); + ASSERT(err == KErrNone); +#else + static_cast(iTargetSessions.Append(&aSession)); +#endif + + TInt ret = iServer.RegisterTargetSessionPointerToConnHistory(aSession); + + if ( ret != KErrNone ) + { + iTargetSessions.Remove(iTargetSessions.Count() - 1); + } + else + { + // Session successfully registered. + iServer.CancelShutdownTimer(); + } + + LOG1(_L("\tret = %d"), ret) + return ret; + } + +void CRemConTargetClientProcess::TargetSessionClosed(CRemConTargetSession& aSession) + { + LOG_FUNC + LOG1(_L("\t&aSession = 0x%08x"), &aSession) + + // Remove session from our list + TInt sessionIndex = iTargetSessions.Find(&aSession); + + if (sessionIndex > KErrNotFound) + { + iTargetSessions.Remove(sessionIndex); + + // Inform server that session has dropped. + iServer.TargetSessionClosed(*this, aSession); + + if (iTargetSessions.Count() > 0) + { + iServer.TargetFeaturesUpdated(*this); + } + + } + } + +void CRemConTargetClientProcess::SetPlayerInformationL(const TPlayerTypeInformation& aPlayerType, const TDesC8& aPlayerName) + { + LOG_FUNC + ASSERT_DEBUG(!HasPlayerInformation()); + + if (!HasPlayerInformation()) + { + iPlayerName.CreateL(aPlayerName); + iPlayerType = aPlayerType; + iPlayerInfoSet = ETrue; + } + } + +void CRemConTargetClientProcess::InterfacesRegistered() + { + LOG_FUNC + + // If this client has not been made available yet, do so now. + // Otherwise, notify the server that new interfaces have been registered. + if (!iClientAvailable) + { + iServer.TargetClientAvailable(*this); + iClientAvailable = ETrue; + } + else + { + iServer.TargetFeaturesUpdated(*this); + } + + } + +TBool CRemConTargetClientProcess::IsInterfaceTypeRegisteredByAnotherSession(CRemConTargetSession& aSession, TUid aInterfaceUid) const + { + LOG_FUNC + + TUint sessionCount = iTargetSessions.Count(); + for (TUint i=0; i < sessionCount; ++i) + { + if (aSession.Id() != iTargetSessions[i]->Id()) + { + if (iTargetSessions[i]->InterfaceSupported(aInterfaceUid)) + { + return ETrue; + } + } + } + + return EFalse; + } + +TInt CRemConTargetClientProcess::ReceiveMessage(CRemConMessage& aMessage) + { + LOG_FUNC + + // Find the session supporting this message + CRemConTargetSession* sess = FindSessionForMessage(aMessage); + + if (sess) + { + // Session found. Check session is able to handle this message. + if (sess->CurrentReceiveMessage().Handle()) + { + // Pass message to session and return the error code obtained. + return sess->WriteMessageToClient(aMessage); + } + else + { + // Session not able to handle message at this time. + return KErrNotReady; + } + } + else + { + // No session supports this message + return KErrArgument; + } + } + +void CRemConTargetClientProcess::ConnectionsChanged() + { + LOG_FUNC + + // Notify each session + TUint sessionCount = iTargetSessions.Count(); + for (TUint i = 0; i < sessionCount; ++i) + { + iTargetSessions[i]->ConnectionsChanged(); + } + } + +TInt CRemConTargetClientProcess::SupportedInterfaces(RArray& aUids) + { + LOG_FUNC + + TInt err = KErrNone; + aUids.Reset(); + + // Gather the list of supported interfaces from each session. + TUint sessionCount = iTargetSessions.Count(); + for (TUint i = 0 ; i < sessionCount && err == KErrNone; ++i) + { + err = iTargetSessions[i]->AppendSupportedInterfaces(aUids); + } + + return err; + } + +TInt CRemConTargetClientProcess::SupportedBulkInterfaces(RArray& aUids) + { + LOG_FUNC + + TInt err = KErrNone; + aUids.Reset(); + + // Gather the list of supported bulk interfaces from each session. + TUint sessionCount = iTargetSessions.Count(); + for (TUint i = 0 ; i < sessionCount && err == KErrNone; ++i) + { + err = iTargetSessions[i]->AppendSupportedBulkInterfaces(aUids); + } + + return err; + } + +TInt CRemConTargetClientProcess::SupportedOperations(TUid aInterfaceUid, RArray& aOperations) + { + LOG_FUNC + + // Find the session supporting this interface. + TInt sessIndex = FindSessionForInterface(aInterfaceUid); + + if (sessIndex >= KErrNone) + { + return iTargetSessions[sessIndex]->SupportedOperations(aInterfaceUid, aOperations); + } + else + { + // Interface not found, so operation not supported. + return KErrNotSupported; + } + } + +CRemConTargetSession* CRemConTargetClientProcess::FindSessionForMessage(const CRemConMessage& aMessage) + { + LOG_FUNC + + TInt result = iTargetSessions.Find(aMessage, TargetSessionCompareUsingSupportedMessage); + if (result >= KErrNone) + { + return iTargetSessions[result]; + } + else + { + return NULL; + } + + } + +TInt CRemConTargetClientProcess::FindSessionForInterface(TUid aInterfaceUid) const + { + LOG_FUNC + + return iTargetSessions.Find(aInterfaceUid, TargetSessionCompareUsingSupportedInterface); + } + +void CRemConTargetClientProcess::CompleteMessageForSession(const CRemConMessage& aMessage, CRemConTargetSession& aSession) + { + LOG_FUNC + + // Targets can only send responses or rejects. + switch (aMessage.MsgType()) + { + case ERemConResponse: + case ERemConReject: + aSession.CompleteSend(); + break; + default: + ASSERT_DEBUG(EFalse); + break; + } + + } + +void CRemConTargetClientProcess::MrcmsoMessageSendResult(const CRemConMessage& /*aMessage*/, TInt /*aError*/) + { + LOG_FUNC + + // This method should never be called, as it is not required to support target client processes. + ASSERT_DEBUG(EFalse); + } + +void CRemConTargetClientProcess::MrcmsoMessageSendOneOrMoreAttempt(const CRemConMessage& aMessage, TUint aNumRemotes) + { + LOG_FUNC + + // Notifications should not be received for reject messages, as the client did not request these be sent. + ASSERT_DEBUG(aMessage.MsgType() != ERemConReject); + + // Find session and notify + CRemConTargetSession* sess = FindSessionForMessage(aMessage); + ASSERT_DEBUG(sess); + + // Session should not already be sending a message to n remotes + ASSERT_DEBUG(sess->NumRemotesToTry() == 0); + + sess->NumRemotes() = 0; + sess->NumRemotesToTry() = aNumRemotes; + sess->SendError() = KErrNone; + } + +void CRemConTargetClientProcess::MrcmsoMessageSendOneOrMoreIncremental(const CRemConMessage& aMessage, TUint aNumRemotes) + { + LOG_FUNC + + // Notifications should not be received for reject messages, as the client did not request these be sent. + ASSERT_DEBUG(aMessage.MsgType() != ERemConReject); + + // Find session and notify + CRemConTargetSession* sess = FindSessionForMessage(aMessage); + ASSERT_DEBUG(sess); + + if (sess->NumRemotesToTry() == 0) + { + MrcmsoMessageSendOneOrMoreAttempt(aMessage,aNumRemotes); + } + else + { + // No send should have yet been attempted + ASSERT_DEBUG(sess->NumRemotes() == 0); + + sess->NumRemotesToTry() += aNumRemotes; + } + } + +void CRemConTargetClientProcess::MrcmsoMessageSendOneOrMoreAttemptFailed(const CRemConMessage& aMessage, TInt aError) + { + LOG_FUNC + + // Notifications should not be received for reject messages, as the client did not request these be sent. + ASSERT_DEBUG(aMessage.MsgType() != ERemConReject); + + // Find session and notify + CRemConTargetSession* sess = FindSessionForMessage(aMessage); + ASSERT_DEBUG(sess); + + // Session should not already be sending a message to n remotes + ASSERT_DEBUG(sess->NumRemotesToTry() == 0); + + sess->NumRemotes() = 0; + sess->SendError() = aError; + CompleteMessageForSession(aMessage, *sess); + } + +void CRemConTargetClientProcess::MrcmsoMessageSendOneOrMoreResult(const CRemConMessage& aMessage, TInt aError) + { + LOG_FUNC + + // Notifications should not be received for reject messages, as the client did not request these be sent. + ASSERT_DEBUG(aMessage.MsgType() != ERemConReject); + + // Find session and notify + CRemConTargetSession* sess = FindSessionForMessage(aMessage); + ASSERT_DEBUG(sess); + + // Ignore notification if client has been completed + if (sess->NumRemotesToTry() > 0) + { + // Only set error if different from KErrNone + if (aError == KErrNone) + { + ++sess->NumRemotes(); + } + else + { + sess->SendError() = aError; + } + + --sess->NumRemotesToTry(); + if (sess->NumRemotesToTry() == 0) + { + CompleteMessageForSession(aMessage, *sess); + } + } + } + +void CRemConTargetClientProcess::MrcmsoMessageSendOneOrMoreAbandoned(const CRemConMessage& aMessage) + { + LOG_FUNC + + // Notifications should not be received for reject messages, as the client did not request these be sent. + ASSERT_DEBUG(aMessage.MsgType() != ERemConReject); + + // Find session and notify + CRemConTargetSession* sess = FindSessionForMessage(aMessage); + ASSERT_DEBUG(sess); + + // Ignore notification if client has been completed + if (sess->NumRemotesToTry() > 0) + { + // Do not adjust NumRemotes() as the message was not sent (but we still don't error the client!) + --sess->NumRemotesToTry(); + if (sess->NumRemotesToTry() == 0) + { + CompleteMessageForSession(aMessage, *sess); + } + } + }