--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/eventmediator/src/eventmediator.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,1354 @@
+/*
+* Copyright (c) 2003-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: This module contains eventmediator and the services of it.
+*
+*/
+
+
+
+/**
+ * @file eventmediator.cpp
+ *
+ * This module contains eventmediator and the services of it.
+ *
+ */
+#include <es_sock.h>
+#include "eventmediator.h"
+#include "eventlogger.h"
+#include "eventmediatordefs.h"
+#include "sit.h"
+#include "log_em.h"
+
+#define FIRST_ARGUMENT 0
+#define SECOND_ARGUMENT 1
+#define THIRD_ARGUMENT 2
+#define FOURTH_ARGUMENT 3
+
+// ============================= CEventMediatorServer =============================
+
+const TUint CEventMediatorServer::iRangeCount = 2;
+
+const TInt CEventMediatorServer::iRanges[iRangeCount] =
+ {
+ CEventMediatorSession::KEventMediatorListen,
+ CEventMediatorSession::KEventMediatorClearEventLog+1
+ };
+
+const TUint8 CEventMediatorServer::iElementIndex[iRangeCount] =
+ {
+ 0,
+ CPolicyServer::ENotSupported
+ };
+
+const CPolicyServer::TPolicyElement CEventMediatorServer::iElements[] =
+ {
+ {_INIT_SECURITY_POLICY_C1(ECapabilityNetworkControl), CPolicyServer::EFailClient},
+ };
+
+const CPolicyServer::TPolicy CEventMediatorServer::iPolicy =
+ {
+ 0, // All connect attempts are checked
+ iRangeCount, // Count of ranges
+ iRanges, // 0...9, 9...
+ iElementIndex, // Only range 1000-1008 are checked
+ iElements // The list of policy elements
+ };
+
+
+CEventMediatorServer::CEventMediatorServer(void)
+ : CPolicyServer(EPriorityNormal,iPolicy), iStoredEvents(1)
+ {
+ }
+
+CEventMediatorServer* CEventMediatorServer::NewL()
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::NewL - begin\n")));
+ CEventMediatorServer* server = CEventMediatorServer::NewLC();
+ CleanupStack::Pop(); // server
+ LOG(Log::Printf(_L("CEventMediatorServer::NewL - end\n")));
+ return server;
+ }
+
+CEventMediatorServer* CEventMediatorServer::NewLC()
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::NewLC - begin\n")));
+ CEventMediatorServer* server = new (ELeave) CEventMediatorServer();
+ CleanupStack::PushL(server);
+ server->ConstructL(server);
+ LOG(Log::Printf(_L("CEventMediatorServer::NewLC - end\n")));
+ return server;
+ }
+
+void CEventMediatorServer::ConstructL(CEventMediatorServer* aServer)
+ {
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ fs.CreatePrivatePath(EDriveC);
+
+ TPath privateDir;
+ User::LeaveIfError(fs.PrivatePath(privateDir));
+ iEventLogFileName.Copy(privateDir);
+ iEventLogFileName.Append(KEventLogFile);
+
+ CleanupStack::PopAndDestroy(); // fs
+
+ aServer->iLogger = CEventLogger::NewL(this);
+ iSit = new (ELeave) CSit(this);
+ StartL(KEventMediatorServer);
+ }
+
+CEventMediatorServer::~CEventMediatorServer(void)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::~CEventMediatorServer\n")));
+ // Delete stored events
+ TInt nEvents = this->iStoredEvents.Count();
+ for (TInt i = 0; i < nEvents; i++)
+ {
+ delete iStoredEvents.At(i)->iData;
+ delete iStoredEvents.At(i);
+ }
+ iStoredEvents.Delete(0, iStoredEvents.Count());
+
+ // Delete log writer
+ delete iLogger;
+
+ delete iSit;
+ }
+
+// ----------------------------------------------------------------------------
+// CEventMediatorServer::StopEventMediator
+// Stops Event Mediator service if there are no sessions left.
+// ----------------------------------------------------------------------------
+//
+void CEventMediatorServer::StopEventMediator(void)
+ {
+ if (iSessionCount == 0)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::StopEventMediator - session count 0, stopping scheduler and thus the server\n")));
+ CActiveScheduler::Stop();
+ }
+ }
+
+TInt CEventMediatorServer::RunError(TInt aError)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::RunError - error = %d\n"), aError));
+ Message().Complete(aError);
+
+ // The leave will result in an early return from CServer::RunL(),
+ // skipping the call to request another message. So we issue the
+ // request here in order to keep the server running.
+ ReStart();
+
+ // Handled the error fully
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------------------------
+// CEventMediatorServer::NewSessionL
+// Creates a new session and returns the handle to the session.
+// ----------------------------------------------------------------------------
+//
+CSession2* CEventMediatorServer::NewSessionL(
+ const TVersion& /*aVersion*/,
+ const RMessage2& aMessage) const
+ {
+ // New sessions are not accepted if the server is shutting down
+ // (it's just waiting for the last session (from SIT) to die)
+ if (iShuttingDown)
+ {
+ User::Leave(KErrServerTerminated);
+ }
+
+ CSession2* session = CEventMediatorSession::NewL(CONST_CAST(CEventMediatorServer*, this), aMessage);
+ return session;
+ }
+
+void CEventMediatorServer::ReportEventL(const TEventType aType, TDesC8* aSpec,
+ TDesC8* aData, TInt aStatus)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::ReportEventL - event type = %d\n"), aType));
+ TInt listenerCount = 0;
+ CEventMediatorSession* session;
+ iSessionIter.SetToFirst();
+ session = (CEventMediatorSession*) iSessionIter++;
+
+ while (session != NULL)
+ {
+ // Some listeners listen this event with specification
+ listenerCount += session->CheckEventL(aType, aSpec, aData, aStatus);
+ // Some without specification, all events are good for them
+ if (aSpec != NULL)
+ {
+ listenerCount += session->CheckEventL(aType, NULL, aData, aStatus);
+ }
+ session = (CEventMediatorSession*) iSessionIter++;
+ }
+ if (listenerCount)
+ {
+ // Need to save the event data as it may/will be fetched later
+ TEventContainer* container = new (ELeave) TEventContainer(listenerCount, aData);
+ CleanupStack::PushL(container);
+ iStoredEvents.AppendL(container);
+ CleanupStack::Pop();
+ }
+ // Write event to log
+ if (aType == ELogEvent && iLogger)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::ReportEventL - calling iLogger->LogEvent\n")));
+ iLogger->LogEvent(*aData);
+ }
+
+ // If there are no listeners, delete data
+ if (listenerCount == 0)
+ {
+ delete aData;
+ }
+ }
+
+TInt CEventMediatorServer::CopyEventDataL(const RMessage2& aMessage)
+ {
+ TBool found = EFalse;
+ TInt i = 0;
+ TInt err = KErrNone;
+ while (!found && i < iStoredEvents.Count())
+ {
+ if (iStoredEvents.At(i)->iData == aMessage.Ptr0())
+ {
+ found = ETrue;
+ }
+ else
+ {
+ i++;
+ }
+ }
+ if (found)
+ {
+ aMessage.WriteL(SECOND_ARGUMENT, *(iStoredEvents.At(i)->iData));
+ MarkStoredEventListened(i);
+ }
+ else
+ {
+ err = KErrNotFound;
+ }
+ return err;
+ }
+
+void CEventMediatorServer::MarkStoredEventListened(TInt aIndex)
+ {
+ iStoredEvents.At(aIndex)->iListenerCount--;
+ if (iStoredEvents.At(aIndex)->iListenerCount == 0)
+ {
+ delete iStoredEvents.At(aIndex)->iData;
+ delete iStoredEvents.At(aIndex);
+ iStoredEvents.Delete(aIndex);
+ }
+ }
+
+TBool CEventMediatorServer::IsClientTheSitL(const RMessage2& aMessage)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::IsClientTheSitL\n")));
+ TBool isClientTheSit = EFalse;
+
+ RThread clientThread;
+ User::LeaveIfError(aMessage.Client(clientThread));
+
+ if (clientThread.Id() == iSit->ThreadId())
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::IsClientTheSitL - YES\n")));
+ isClientTheSit = ETrue;
+ }
+
+ clientThread.Close();
+
+ return isClientTheSit;
+ }
+
+void CEventMediatorServer::MakeSureSitIsRunningL()
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::MakeSureSitIsRunningL\n")));
+ // If the SIT has not yet been started
+ // or has died, try to start it
+ iSit->StartL();
+ }
+
+void CEventMediatorServer::SetTaskArrivalListenerL(CListenerContainer* aListener)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::SetTaskArrivalListenerL\n")));
+ if (aListener)
+ {
+ // Task arrival observation requests must
+ // come from the SIT
+ if (!IsClientTheSitL(aListener->Message()))
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ // Only one task arrival observation request
+ // is allowed to be present at the same time
+ if (iTaskArrivalListener && (aListener != iTaskArrivalListener))
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ iTaskArrivalListener = aListener;
+ }
+
+void CEventMediatorServer::ClearTaskArrivalListener()
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::ClearTaskArrivalListener\n")));
+ iTaskArrivalListener = NULL;
+ }
+
+CListenerContainer* CEventMediatorServer::TaskArrivalListener()
+ {
+ return iTaskArrivalListener;
+ }
+
+void CEventMediatorServer::TaskRequestArrivedL(CListenerContainer* aTaskRequest)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::TaskRequestArrivedL\n")));
+ CompleteTaskArrivalObservationRequestL(aTaskRequest->Type(), aTaskRequest->Specification());
+ }
+
+void CEventMediatorServer::TaskArrivalObservationRequestArrivedL()
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::TaskArrivalObservationRequestArrivedL\n")));
+ // Go through all pending event listening requests to see if any
+ // one of those should be passed to the SIT (i.e. if the task
+ // arrival observation request should be completed immediately)
+
+ CListenerContainer* taskRequest = FindWaitingTaskRequest();
+
+ if (taskRequest)
+ {
+ CompleteTaskArrivalObservationRequestL(taskRequest->Type(), taskRequest->Specification());
+ }
+ }
+
+void CEventMediatorServer::TaskRequestEventSpecFetchingRequestArrivedL(CListenerContainer* aFetchingRequest)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::TaskRequestEventSpecFetchingRequestArrivedL\n")));
+ TFetchTaskInfoEventSpec taskRequestInfo;
+ TPckg<TFetchTaskInfoEventSpec> taskRequestInfoDes(taskRequestInfo);
+ taskRequestInfoDes.Copy(*(aFetchingRequest->Specification()));
+
+ // Find the task request whose event specification
+ // we should return to the SIT TH
+ CListenerContainer* taskRequest = FindListener(taskRequestInfo.iEventType, taskRequestInfo.iEventSpecId);
+
+ if (taskRequest && !taskRequest->BeingFulfilled())
+ {
+ CompleteTaskRequestEventSpecFetchingRequestL(KErrNone, aFetchingRequest->Specification(),
+ taskRequest->Specification());
+ taskRequest->MarkAsBeingFulfilled();
+ }
+ else
+ {
+ CompleteTaskRequestEventSpecFetchingRequestL(KErrNotFound, aFetchingRequest->Specification(), NULL);
+ }
+ }
+
+void CEventMediatorServer::TaskCancellationObservationRequestArrivedL(CListenerContainer* aRequest)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::TaskCancellationObservationRequestArrivedL\n")));
+ // Try to find a task request event type that corresponds to the received
+ // event type. This will only succeed if the received event type is
+ // one that is used to listen to the cancellation of a task request.
+ TEventType taskRequestEventType = CSit::FindTaskRequestEventType(aRequest->Type());
+
+ // If a corresponding task request type was found...
+ if (taskRequestEventType != EUnfoundEvent)
+ {
+ // Try to find the listener container of the task request
+ CListenerContainer* taskRequest = FindListener(taskRequestEventType, aRequest->Specification());
+
+ // The listener container for the task request was not found
+ // (i.e. the task request has been cancelled or the
+ // corresponding client session has been closed), so we
+ // complete the cancellation observation request right away
+ if (taskRequest == NULL)
+ {
+ ReportEventL(aRequest->Type(), aRequest->Specification(), NULL);
+ }
+ }
+ }
+
+void CEventMediatorServer::CompleteTaskArrivalObservationRequestL(TEventType aEventType, TDesC8* aSpec)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::CompleteTaskArrivalObservationRequestL\n")));
+ if (iTaskArrivalListener)
+ {
+ // In SIT events, the event specification
+ // begins with the event specification ID
+ TEventSpec* sitEventSpec = (TEventSpec*)(aSpec->Ptr());
+
+ TTaskArrivedEventData eventData;
+ eventData.iEventType = aEventType;
+ eventData.iEventSpecId = sitEventSpec->iId;
+ TPckg<TTaskArrivedEventData> eventDataDes(eventData);
+
+ HBufC8* eventDataCopy = eventDataDes.AllocL();
+ CleanupStack::PushL(eventDataCopy);
+
+ ReportEventL(ETaskArrivedEvent, NULL, eventDataCopy);
+
+ CleanupStack::Pop(); // eventDataCopy, freed elsewhere
+ }
+ }
+
+void CEventMediatorServer::CompleteTaskRequestEventSpecFetchingRequestL(TInt aStatus, TDesC8* aEventSpec,
+ TDesC8* aTaskRequestEventSpec)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::CompleteTaskRequestEventSpecFetchingRequestL\n")));
+ // The event specification of the task request
+ // is returned to the SIT TH as event data
+ if (aTaskRequestEventSpec)
+ {
+ HBufC8* eventData = aTaskRequestEventSpec->AllocL();
+ CleanupStack::PushL(eventData);
+
+ ReportEventL(EFetchTaskInfoEvent, aEventSpec, eventData, aStatus);
+
+ CleanupStack::Pop(); // eventData, freed elsewhere
+ }
+ else
+ {
+ ReportEventL(EFetchTaskInfoEvent, aEventSpec, NULL, aStatus);
+ }
+ }
+
+CListenerContainer* CEventMediatorServer::FindWaitingTaskRequest()
+ {
+ CEventMediatorSession* session;
+ iSessionIter.SetToFirst();
+ session = (CEventMediatorSession*) iSessionIter++;
+
+ CListenerContainer* listener = NULL;
+
+ while (session != NULL)
+ {
+ listener = session->FindWaitingTaskRequest();
+ if (listener != NULL)
+ {
+ break;
+ }
+ session = (CEventMediatorSession*) iSessionIter++;
+ }
+
+ return listener;
+ }
+
+CListenerContainer* CEventMediatorServer::FindListener(TEventType aEventType,
+ TInt aEventSpecId)
+ {
+ CEventMediatorSession* session;
+ iSessionIter.SetToFirst();
+ session = (CEventMediatorSession*) iSessionIter++;
+
+ CListenerContainer* listener = NULL;
+
+ while (session != NULL)
+ {
+ listener = session->FindListener(aEventType, aEventSpecId);
+ if (listener != NULL)
+ {
+ break;
+ }
+ session = (CEventMediatorSession*) iSessionIter++;
+ }
+
+ return listener;
+ }
+
+CListenerContainer* CEventMediatorServer::FindListener(TEventType aEventType,
+ const TDesC8* aEventSpec)
+ {
+ CEventMediatorSession* session;
+ iSessionIter.SetToFirst();
+ session = (CEventMediatorSession*) iSessionIter++;
+
+ CListenerContainer* listener = NULL;
+
+ while (session != NULL)
+ {
+ listener = session->FindListener(aEventType, aEventSpec);
+ if (listener != NULL)
+ {
+ break;
+ }
+ session = (CEventMediatorSession*) iSessionIter++;
+ }
+
+ return listener;
+ }
+
+void CEventMediatorServer::CompleteListener(TEventType aEventType, const TDesC8* aEventSpec, TInt aStatus)
+ {
+ CEventMediatorSession* session;
+ iSessionIter.SetToFirst();
+ session = (CEventMediatorSession*) iSessionIter++;
+
+ while (session != NULL)
+ {
+ session->CompleteListener(aEventType, aEventSpec, aStatus);
+ session = (CEventMediatorSession*) iSessionIter++;
+ }
+ }
+
+TInt CEventMediatorServer::NormalSessionCount()
+ {
+ TInt normalSessionCount = 0;
+
+ CEventMediatorSession* session;
+ iSessionIter.SetToFirst();
+ session = (CEventMediatorSession*) iSessionIter++;
+
+ while (session != NULL)
+ {
+ if (!(session->IsASitSession()))
+ {
+ normalSessionCount++;
+ }
+ session = (CEventMediatorSession*) iSessionIter++;
+ }
+
+ return normalSessionCount;
+ }
+
+TInt CEventMediatorServer::NewEventSpecId()
+ {
+ return ++iNextEventSpecId;
+ }
+
+TPtrC CEventMediatorServer::EventLogFileName(void)
+ {
+ TPtrC name(iEventLogFileName);
+ return name;
+ }
+
+void CEventMediatorServer::SitDied()
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::SitDied\n")));
+ CompleteTaskRequests(KErrDied);
+ }
+
+void CEventMediatorServer::CompleteTaskRequests(TInt aStatus)
+ {
+ LOG(Log::Printf(_L("CEventMediatorServer::CompleteTaskRequests\n")));
+ CEventMediatorSession* session;
+ iSessionIter.SetToFirst();
+ session = (CEventMediatorSession*) iSessionIter++;
+
+ while (session != NULL)
+ {
+ session->CompleteTaskRequests(aStatus);
+ session = (CEventMediatorSession*) iSessionIter++;
+ }
+ }
+
+void CEventMediatorServer::SetShuttingDown(TBool aShuttingDown)
+ {
+ iShuttingDown = aShuttingDown;
+ }
+
+// ============================= CEventMediatorSession =============================
+
+CEventMediatorSession* CEventMediatorSession::NewL(CEventMediatorServer* aServer, const RMessage2& aMessage)
+ {
+ LOG(Log::Printf(_L("CEventMediatorSession::NewL - begin\n")));
+ CEventMediatorSession* self;
+ self = new (ELeave) CEventMediatorSession(aServer);
+ CleanupStack::PushL(self);
+
+ // Marks the session as a "SIT session"
+ // if the client is the SIT thread
+ self->iIsSitSession = aServer->IsClientTheSitL(aMessage);
+
+ aServer->iSessionCount++;
+
+ if ( !self->IsASitSession() )
+ {
+ User::LeaveIfError(self->iFs.Connect()); // For EventLog
+ self->iEventLogFileOpen = EFalse;
+ }
+
+ CleanupStack::Pop(); // self
+
+ LOG(Log::Printf(_L("CEventMediatorSession::NewL - end\n")));
+ return self;
+ }
+
+CEventMediatorSession::CEventMediatorSession(CEventMediatorServer* aServer)
+ : iListenedEvents(2), iServer(aServer)
+ {
+ }
+
+CEventMediatorSession::~CEventMediatorSession(void)
+ {
+ LOG(Log::Printf(_L("CEventMediatorSession::~CEventMediatorSession\n")));
+ CancelAll();
+ if (iServer)
+ {
+ TInt normalSessionCount = iServer->NormalSessionCount();
+
+ // If this too is a normal session and is dying,
+ // decrement the normal session count by one
+ if (!IsASitSession())
+ {
+ normalSessionCount--;
+
+ if (iEventLogFileOpen)
+ {
+ iEventLogFile.Close();
+ iEventLogFileOpen = EFalse;
+ }
+ iFs.Close(); // For EventLog
+
+ }
+
+ if (normalSessionCount == 0)
+ {
+ // If "normal" (non-sit) sessions are no longer present,
+ // we complete the task arrival observation request, thus
+ // causing the SIT to terminate and close its connection
+ // to this server. This should be the last connection whose
+ // closing will cause this server to terminate.
+ // NOTE. KErrCancel cannot be used here as the Event Mediator
+ // does not report it to the caller
+ LOG(Log::Printf(_L("CEventMediatorSession::~CEventMediatorSession - normal session count = 0\n")));
+ iServer->CompleteListener(ETaskArrivedEvent, NULL, KErrAbort);
+
+ // Set the server state to "shutting down". This will
+ // cause the server to discard any new connect requests
+ // with KErrServerTerminated.
+ iServer->SetShuttingDown(ETrue);
+ }
+
+ if (iServer->iSessionCount)
+ {
+ iServer->iSessionCount--;
+ }
+
+ iServer->StopEventMediator();
+ }
+ }
+
+void CEventMediatorSession::ServiceL(const RMessage2& aMessage)
+ {
+ TInt status = 0;
+
+ switch (aMessage.Function())
+ {
+ case KEventMediatorListen:
+ ListenToEventL(aMessage);
+ break;
+
+ case KEventMediatorListenWithSpec:
+ ListenToEventWithSpecL(aMessage);
+ break;
+
+ case KEventMediatorCancel:
+ CancelListening(aMessage);
+ aMessage.Complete(KErrNone);
+ break;
+
+ case KEventMediatorCancelWithSpec:
+ CancelListeningWithSpecL(aMessage);
+ aMessage.Complete(KErrNone);
+ break;
+
+ case KEventMediatorCancelAll:
+ CancelAll();
+ aMessage.Complete(KErrNone);
+ break;
+
+ case KEventMediatorReportEvent:
+ ReportEventL(aMessage);
+ aMessage.Complete(KErrNone);
+ break;
+
+ case KEventMediatorReportEventWithSpec:
+ ReportEventWithSpecL(aMessage);
+ aMessage.Complete(KErrNone);
+ break;
+
+ case KEventMediatorFetchData:
+ status = FetchDataL(aMessage);
+ aMessage.Complete(status);
+ break;
+
+ case KEventMediatorReportLogEvent:
+ ReportLogEventL(aMessage);
+ aMessage.Complete(KErrNone);
+ break;
+
+ case KEventMediatorNewEventSpecId:
+ NewEventSpecIdL(aMessage);
+ aMessage.Complete(KErrNone);
+ break;
+ case KEventMediatorDeletePrivateFiles:
+ status = DeletePrivateFiles();
+ aMessage.Complete(status);
+ break;
+
+ case KEventMediatorGetEventLogSize:
+ status = GetEventLogSize(aMessage);
+ aMessage.Complete(status);
+ break;
+
+ case KEventMediatorGetEventLogHeader:
+ status = GetEventLogHeader(aMessage);
+ aMessage.Complete(status);
+ break;
+ case KEventMediatorGetEventLogData:
+ status = GetEventLogData(aMessage);
+ aMessage.Complete(status);
+ break;
+ case KEventMediatorClearEventLog:
+ status = ClearEventLog();
+ aMessage.Complete(status);
+ break;
+ default:
+ aMessage.Complete(KErrGeneral);
+ break;
+ }
+ }
+
+TInt CEventMediatorSession::ListenToEventL(const RMessage2& aMessage)
+ {
+ CListenerContainer* listener = new (ELeave) CListenerContainer(aMessage, NULL, iServer);
+ CleanupStack::PushL(listener);
+
+ iListenedEvents.AppendL(listener);
+ CleanupStack::Pop(); // listener
+
+ listener->AnalyzeRequestL();
+
+ return KErrNone;
+ }
+
+TInt CEventMediatorSession::ListenToEventWithSpecL(const RMessage2& aMessage)
+ {
+ HBufC8* specBuf = NULL;
+
+ // Read specification
+ specBuf = ReadSpecificationFromClientL(aMessage);
+ CleanupStack::PushL(specBuf);
+
+ // Ownership of specBuf is given to listener
+ CListenerContainer* listener = new (ELeave) CListenerContainer(aMessage, specBuf, iServer);
+ CleanupStack::Pop(); // specBuf
+ CleanupStack::PushL(listener);
+
+ iListenedEvents.AppendL(listener);
+ CleanupStack::Pop(); // listener
+
+ listener->AnalyzeRequestL();
+
+ return KErrNone;
+ }
+
+void CEventMediatorSession::CancelListening(const RMessage2& aMessage)
+ {
+ TInt index;
+
+ while (FindListenerMsg((TEventType)aMessage.Int0(), index))
+ {
+ CompleteListener(index, KErrCancel);
+ }
+ }
+
+void CEventMediatorSession::CancelListeningWithSpecL(const RMessage2& aMessage)
+ {
+ HBufC8* specBuf = NULL;
+ TInt index;
+
+ // Read specification
+ specBuf = ReadSpecificationFromClientL(aMessage);
+ CleanupStack::PushL(specBuf);
+
+ // Cancel listeners
+ while (FindListenerMsg((TEventType)aMessage.Int0(), specBuf, index))
+ {
+ CompleteListener(index, KErrCancel);
+ }
+ CleanupStack::PopAndDestroy(); // specBuf
+ }
+
+void CEventMediatorSession::CancelAll()
+ {
+ TInt nEvents = iListenedEvents.Count();
+ for (TInt i = 0; i < nEvents; i++)
+ {
+ iListenedEvents.At(i)->Complete(KErrCancel);
+ delete iListenedEvents.At(i);
+ iListenedEvents.At(i) = NULL;
+ }
+ iListenedEvents.Reset();
+ }
+
+void CEventMediatorSession::ReportEventL(const RMessage2& aMessage)
+ {
+ TEventType eventType = (TEventType)aMessage.Int0();
+ LOG(Log::Printf(_L("CEventMediatorSession::ReportEventL - event type = %d\n"), eventType));
+ // Read data
+ HBufC8* dataBuf = ReadEventDataFromClientL(aMessage);
+ CleanupStack::PushL(dataBuf);
+ // Report event to server
+ iServer->ReportEventL(eventType, NULL, dataBuf);
+ CleanupStack::Pop();
+ }
+
+void CEventMediatorSession::ReportEventWithSpecL(const RMessage2& aMessage)
+ {
+ TEventType eventType=(TEventType) aMessage.Int0();
+ LOG(Log::Printf(_L("CEventMediatorSession::ReportEventWithSpecL - event type = %d\n"), eventType));
+ // Read data
+ HBufC8* dataBuf = ReadEventDataFromClientL(aMessage);
+ CleanupStack::PushL(dataBuf);
+ // Read specification
+ HBufC8* specBuf = ReadSpecificationFromClientL(aMessage);
+ CleanupStack::PushL(specBuf);
+ // Report event to server
+ iServer->ReportEventL(eventType, specBuf, dataBuf);
+ CleanupStack::PopAndDestroy(); // specBuf
+ CleanupStack::Pop(); // dataBuf
+ }
+
+void CEventMediatorSession::ReportLogEventL(const RMessage2& aMessage)
+ {
+ LOG(Log::Printf(_L("CEventMediatorSession::ReportLogEventL\n")));
+ // Read event
+ TLogEvent event;
+ TPckg<TLogEvent> eventPckg(event);
+ aMessage.ReadL(FIRST_ARGUMENT, eventPckg);
+
+ // Create one buffer to contain put everything in a normal buffer and
+ TInt lengthsDesLth = event.iDesCount * sizeof(TInt);
+ TInt position = eventPckg.Length();
+ TInt dataLength = position + lengthsDesLth + aMessage.Int2();
+ HBufC8* dataBuf = HBufC8::NewLC(dataLength);
+ TPtr8 dataPtr = dataBuf->Des();
+
+ // Copy event to buffer
+ dataPtr.Append(eventPckg);
+ // Read lengths to buffer
+ TPtr8 tmpPtr(&dataPtr[position], 0, dataLength - position);
+ aMessage.ReadL(SECOND_ARGUMENT, tmpPtr);
+ // Read descriptors to the buffer
+ position= dataPtr.Length();
+ tmpPtr.Set(&dataPtr[position], 0, dataLength - position);
+ aMessage.ReadL(THIRD_ARGUMENT, tmpPtr);
+
+ // Report event to server
+ iServer->ReportEventL(ELogEvent, NULL, dataBuf);
+ CleanupStack::Pop();
+ }
+
+TInt CEventMediatorSession::FetchDataL(const RMessage2& aMessage)
+ {
+ LOG(Log::Printf(_L("CEventMediatorSession::FetchDataL\n")));
+ return iServer->CopyEventDataL(aMessage);
+ }
+
+TInt CEventMediatorSession::CheckEventL(const TEventType aType, const TDesC8* aSpec,
+ const TDesC8* aData, TInt aStatus)
+ {
+ TInt index;
+ TInt listenerCount = 0;
+ TInt dataLth = 0;
+ // Some events don't not have data
+ if (aData)
+ {
+ dataLth = aData->Length();
+ }
+ TPckg<TInt> lengthpckg(dataLth);
+ TPckgC<const TAny*> ptrpckg(aData);
+
+ while (FindListenerMsg(aType, aSpec, index))
+ {
+ RMessage2& listener = iListenedEvents.At(index)->Message();
+
+ if (aStatus == KErrNone)
+ {
+ // Write info about data
+ listener.WriteL(SECOND_ARGUMENT, lengthpckg);
+ listener.WriteL(THIRD_ARGUMENT, ptrpckg);
+
+ // Complete listener
+ listener.Complete(KErrNone);
+ }
+ else
+ {
+ listener.Complete(aStatus);
+ }
+
+ delete iListenedEvents.At(index);
+ iListenedEvents.Delete(index);
+ listenerCount++;
+ }
+
+ return listenerCount;
+ }
+
+TBool CEventMediatorSession::FindListenerMsg(const TEventType aType, TInt& index)
+ {
+ for (TInt i = 0; i < iListenedEvents.Count(); i++)
+ {
+ if (iListenedEvents.At(i)->Type() == aType)
+ {
+ index=i;
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+TBool CEventMediatorSession::FindListenerMsg(const TEventType aType, const TDesC8* aSpec, TInt& index)
+ {
+ for (TInt i = 0; i < iListenedEvents.Count(); i++)
+ {
+ if (iListenedEvents.At(i)->HandlesEvent(aType, aSpec))
+ {
+ index = i;
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+TBool CEventMediatorSession::FindTaskRequestListenerMsg(TInt& index)
+ {
+ for (TInt i = 0; i < iListenedEvents.Count(); i++)
+ {
+ if (CSit::EventRequiresSit(iListenedEvents.At(i)->Type()))
+ {
+ index = i;
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+HBufC8* CEventMediatorSession::ReadSpecificationFromClientL(const RMessage2& aMessage)
+ {
+ HBufC8* specBuf;
+ // Read specification descriptor length from client, create specification buffer
+ const TAny* desPtr = aMessage.Ptr3();
+ if (desPtr == NULL)
+ {
+ return NULL;
+ }
+ TInt specLength = aMessage.GetDesLength(FOURTH_ARGUMENT);
+ // Create spcification buffer
+ specBuf = HBufC8::NewLC(specLength);
+ TPtr8 ptr = specBuf->Des();
+ // Read specification
+ aMessage.ReadL(FOURTH_ARGUMENT, ptr);
+ CleanupStack::Pop(); // specBuf
+ return specBuf;
+ }
+
+HBufC8* CEventMediatorSession::ReadEventDataFromClientL(const RMessage2& aMessage)
+ {
+ HBufC8* dataBuf = NULL;
+ TInt desLength = aMessage.Int1();
+
+ if (desLength != 0) // Some events have no data
+ {
+ dataBuf = HBufC8::NewLC(desLength);
+ TPtr8 ptr = dataBuf->Des();
+ aMessage.ReadL(THIRD_ARGUMENT, ptr);
+ CleanupStack::Pop(); // dataBuf
+ }
+ return dataBuf;
+ }
+
+CListenerContainer* CEventMediatorSession::FindWaitingTaskRequest()
+ {
+ CListenerContainer* listener = NULL;
+
+ for (TInt i = 0; i < iListenedEvents.Count(); i++)
+ {
+ if (iListenedEvents.At(i)->WaitingForFulfilling())
+ {
+ listener = iListenedEvents.At(i);
+ break;
+ }
+ }
+
+ return listener;
+ }
+
+CListenerContainer* CEventMediatorSession::FindListener(TEventType aEventType,
+ TInt aEventSpecId)
+ {
+ CListenerContainer* listener = NULL;
+
+ for (TInt i = 0; i < iListenedEvents.Count(); i++)
+ {
+ if (iListenedEvents.At(i)->Type() == aEventType)
+ {
+ TEventSpec* eventSpec = (TEventSpec*)(iListenedEvents.At(i)->Specification()->Ptr());
+
+ if (eventSpec->iId == aEventSpecId)
+ {
+ listener = iListenedEvents.At(i);
+ break;
+ }
+ }
+ }
+
+ return listener;
+ }
+
+CListenerContainer* CEventMediatorSession::FindListener(TEventType aEventType,
+ const TDesC8* aEventSpec)
+ {
+ CListenerContainer* listener = NULL;
+
+ for (TInt i = 0; i < iListenedEvents.Count(); i++)
+ {
+ if (iListenedEvents.At(i)->HandlesEvent(aEventType, aEventSpec))
+ {
+ listener = iListenedEvents.At(i);
+ break;
+ }
+ }
+
+ return listener;
+ }
+
+void CEventMediatorSession::CompleteListener(TEventType aEventType,
+ const TDesC8* aEventSpec,
+ TInt aStatus)
+ {
+ TInt index;
+ while (FindListenerMsg(aEventType, aEventSpec, index))
+ {
+ CompleteListener(index, aStatus);
+ }
+ }
+
+void CEventMediatorSession::CompleteListener(TInt aIndex, TInt aStatus)
+ {
+ iListenedEvents.At(aIndex)->Complete(aStatus);
+ delete iListenedEvents.At(aIndex);
+ iListenedEvents.Delete(aIndex);
+ }
+
+void CEventMediatorSession::CompleteTaskRequests(TInt aStatus)
+ {
+ LOG(Log::Printf(_L("CEventMediatorSession::CompleteTaskRequests\n")));
+ TInt index;
+ while (FindTaskRequestListenerMsg(index))
+ {
+ CompleteListener(index, aStatus);
+ }
+ }
+
+TBool CEventMediatorSession::IsASitSession()
+ {
+ return iIsSitSession;
+ }
+
+void CEventMediatorSession::NewEventSpecIdL(const RMessage2& aMessage)
+ {
+ TInt newEventSpecId = iServer->NewEventSpecId();
+ TPckg<TInt> newEventSpecIdDes(newEventSpecId);
+ aMessage.WriteL(FIRST_ARGUMENT, newEventSpecIdDes);
+ }
+
+TInt CEventMediatorSession::DeletePrivateFiles()
+ {
+ TRAPD(err, DeletePrivateFilesL());
+ if ( err )
+ {
+ LOG(Log::Printf(_L("DeletePrivateFilesL() leave error %d\n"), err));
+ return err;
+ }
+
+ return KErrNone;
+ }
+
+void CEventMediatorSession::DeletePrivateFilesL()
+ {
+ LOG(Log::Printf(_L("DeletePrivateFilesL() called\n")));
+
+ CFileMan* fileMan = CFileMan::NewL(iFs);
+ CleanupStack::PushL(fileMan);
+
+ TPath privateDir;
+ User::LeaveIfError(iFs.PrivatePath(privateDir));
+
+ TInt err = fileMan->RmDir(privateDir);
+ if (err != KErrNone && err != KErrPathNotFound && err != KErrNotFound)
+ {
+ User::Leave(err);
+ }
+ CleanupStack::PopAndDestroy(); //fileMan
+ }
+
+TInt CEventMediatorSession::GetEventLogSize(
+ const RMessage2& aMessage)
+ {
+ if ( iEventLogFileOpen )
+ {
+ iEventLogFile.Close();
+ iEventLogFileOpen = EFalse;
+ }
+
+ TInt err = iEventLogFile.Open(iFs, iServer->EventLogFileName(), EFileRead | EFileShareAny);
+ if ( err )
+ return err;
+
+ TInt size(0);
+ err = iEventLogFile.Size(size);
+ if ( err )
+ {
+ iEventLogFile.Close();
+ return err;
+ }
+
+ TPckg<TInt> sizePckg(size);
+ err = aMessage.Write(FIRST_ARGUMENT, sizePckg);
+ if ( err )
+ {
+ iEventLogFile.Close();
+ return err;
+ }
+
+ iEventLogFileOpen = ETrue;
+
+ return KErrNone;
+ }
+
+TInt CEventMediatorSession::GetEventLogHeader(
+ const RMessage2& aMessage)
+ {
+ TInt err(0);
+
+ if ( !iEventLogFileOpen )
+ {
+ err = iEventLogFile.Open(iFs, iServer->EventLogFileName(), EFileRead | EFileShareAny);
+ if ( err )
+ return err;
+ iEventLogFileOpen = ETrue;
+ }
+
+ TInt position = 0;
+ err = iEventLogFile.Seek(ESeekStart, position);
+ if (err != KErrNone)
+ return err;
+
+ TBuf8<EVENTLOG_FILE_HEADER_LTH> fileHeaderBuf;
+ err = iEventLogFile.Read(fileHeaderBuf, EVENTLOG_FILE_HEADER_LTH);
+ if (err != KErrNone)
+ return err;
+
+ TRAP(err, aMessage.WriteL(FIRST_ARGUMENT, fileHeaderBuf));
+ if ( err )
+ return err;
+
+ return KErrNone;
+ }
+
+TInt CEventMediatorSession::GetEventLogData(
+ const RMessage2& aMessage)
+ {
+ TInt err(0);
+
+ if ( !iEventLogFileOpen )
+ {
+ err = iEventLogFile.Open(iFs, iServer->EventLogFileName(), EFileRead | EFileShareAny);
+ if ( err )
+ return err;
+ iEventLogFileOpen = ETrue;
+ }
+
+ TInt size(0);
+ err = iEventLogFile.Size(size);
+ if ( err )
+ return err;
+
+ if ( size < EVENTLOG_FILE_HEADER_LTH )
+ return KErrNotFound;
+
+ HBufC8* eventLogFileBuf = NULL;
+ TRAP(err, eventLogFileBuf = HBufC8::NewL(size));
+ if ( err )
+ {
+ return err;
+ }
+
+ TPtr8 eventLogDataPtr(eventLogFileBuf->Des());
+ TInt position(0);
+ err = iEventLogFile.Seek(ESeekStart, position);
+ if ( err )
+ {
+ delete eventLogFileBuf;
+ return err;
+ }
+ err = iEventLogFile.Read(eventLogDataPtr); // iLogFileSize);
+ if ( err )
+ {
+ delete eventLogFileBuf;
+ return err;
+ }
+
+ TRAP( err, aMessage.WriteL(FIRST_ARGUMENT, eventLogDataPtr));
+ if ( err )
+ {
+ delete eventLogFileBuf;
+ return err;
+ }
+
+ delete eventLogFileBuf;
+ eventLogFileBuf = NULL;
+
+ return KErrNone;
+ }
+
+TInt CEventMediatorSession::ClearEventLog()
+ {
+ if ( iEventLogFileOpen )
+ {
+ iEventLogFile.Close();
+ iEventLogFileOpen = EFalse;
+ }
+
+ TInt err = iFs.Delete(iServer->EventLogFileName());
+
+ return err;
+ }
+
+
+
+// ============================= CEventMediatorServer =============================
+
+CListenerContainer::CListenerContainer(const RMessage2& aMessage, TDesC8* aSpec,
+ CEventMediatorServer* aServer)
+ : iSpec(aSpec), iMessage(aMessage), iServer(aServer)
+ {
+ iEventType = Type();
+ }
+
+void CListenerContainer::AnalyzeRequestL()
+ {
+ LOG(Log::Printf(_L("CListenerContainer::AnalyzeRequestL\n")));
+ if (CSit::EventRequiresSit(iEventType))
+ {
+ LOG(Log::Printf(_L("CListenerContainer::AnalyzeRequestL - event type = %d, requires SIT\n"), iEventType));
+ iServer->MakeSureSitIsRunningL();
+ iServer->TaskRequestArrivedL(this);
+ }
+
+ // If this event listening request is the one
+ // made by the SIT task arrival observer...
+ if (iEventType == ETaskArrivedEvent)
+ {
+ iServer->SetTaskArrivalListenerL(this);
+ iServer->TaskArrivalObservationRequestArrivedL();
+ }
+
+ // If this event listening request is one
+ // made by a SIT TH to fetch a task...
+ if (iEventType == EFetchTaskInfoEvent)
+ {
+ iServer->TaskRequestEventSpecFetchingRequestArrivedL(this);
+ }
+
+ // If the event listening request is one
+ // made by a SIT TH to listen to the cancellation
+ // of the task request it is handling
+ if (CSit::IsTaskCancellationObservationRequest(iEventType))
+ {
+ iServer->TaskCancellationObservationRequestArrivedL(this);
+ }
+ }
+
+CListenerContainer::~CListenerContainer()
+ {
+ delete iSpec;
+
+ if (iServer->TaskArrivalListener() == this)
+ {
+ iServer->ClearTaskArrivalListener();
+ }
+ }
+
+TBool CListenerContainer::HandlesEvent(TEventType aEventType, const TDesC8* aEventSpec)
+ {
+ if (iEventType == aEventType)
+ {
+ // Specs are same if both are NULL
+ if (iSpec == NULL && aEventSpec == NULL)
+ {
+ return ETrue;
+ }
+ // or data in buffers are identical
+ else if (iSpec != NULL && aEventSpec != NULL && (*iSpec) == (*aEventSpec))
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+void CListenerContainer::Complete(TInt status)
+ {
+ // If there's a SIT fulfilling this event listening
+ // request (i.e. if this is a task request) and this
+ // task request is being cancelled...
+ if (status == KErrCancel)
+ {
+ // See if we can find a task request cancellation observation
+ // event type that corresponds to this event type
+ TEventType cancelEventType = CSit::FindCancelEventType(iEventType);
+
+ if (cancelEventType != EUnfoundEvent)
+ {
+ // Complete the task request cancellation
+ // observation, if found
+ iServer->CompleteListener(cancelEventType, iSpec, KErrNone);
+ }
+ }
+
+ iMessage.Complete(status);
+ }
+
+TBool CListenerContainer::WaitingForFulfilling()
+ {
+ if (CSit::EventRequiresSit(iEventType) && !iBeingFulfilledBySit)
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+void CListenerContainer::MarkAsBeingFulfilled()
+ {
+ iBeingFulfilledBySit = ETrue;
+ }
+
+TBool CListenerContainer::BeingFulfilled()
+ {
+ return iBeingFulfilledBySit;
+ }