Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'jb-49681' into 'master'
[sensorfw] track D-Bus sender of requestSensor

See merge request mer-core/sensorfw!54
  • Loading branch information
Matti Kosola committed Aug 24, 2020
2 parents 89ed1ef + 6f0e45d commit 0fba832
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 2 deletions.
125 changes: 124 additions & 1 deletion core/sensormanager.cpp
Expand Up @@ -41,11 +41,13 @@
#endif // SENSORFW_LUNA_SERVICE_CLIENT
#include <QSocketNotifier>
#include <errno.h>
#include <functional>
#include "sockethandler.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <QTimer>
#include <QSettings>


Expand All @@ -55,6 +57,8 @@ typedef struct {
void* buffer;
} PipeData;

const int SensorManager::SOCKET_CONNECTION_TIMEOUT_MS = 10000;

SensorManager* SensorManager::instance_ = NULL;
int SensorManager::sessionIdCount_ = 0;

Expand Down Expand Up @@ -91,6 +95,59 @@ DeviceAdaptorInstanceEntry::~DeviceAdaptorInstanceEntry()
{
}

SessionInstanceEntry::SessionInstanceEntry(QObject* parent, int sessionId, const QString& clientName)
: QObject(parent)
, m_sessionId(sessionId)
, m_clientName(clientName)
, m_timer(nullptr)
{
}

SessionInstanceEntry::~SessionInstanceEntry()
{
if (m_timer) {
delete m_timer;
m_timer = nullptr;
}
}

void SessionInstanceEntry::expectConnection(int msec)
{
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
m_timer->setInterval(msec);
connect(m_timer, &QTimer::timeout, this, &SessionInstanceEntry::timerTimeout);
m_timer->start();

SocketHandler& socketHandler = SensorManager::instance().socketHandler();
connect(&socketHandler, &SocketHandler::connectedSession,
this, &SessionInstanceEntry::sessionConnected);
}

void SessionInstanceEntry::timerTimeout()
{
m_timer->deleteLater();
m_timer = nullptr;

SocketHandler& socketHandler = SensorManager::instance().socketHandler();
disconnect(&socketHandler, &SocketHandler::connectedSession, this, nullptr);
socketHandler.checkConnectionEstablished(m_sessionId);
}

void SessionInstanceEntry::sessionConnected(int sessionId)
{
if (sessionId == m_sessionId) {
if (m_timer) {
m_timer->stop();
m_timer->deleteLater();
m_timer = nullptr;
}

SocketHandler& socketHandler = SensorManager::instance().socketHandler();
disconnect(&socketHandler, &SocketHandler::connectedSession, this, nullptr);
}
}

inline QDBusConnection bus()
{
return QDBusConnection::systemBus();
Expand Down Expand Up @@ -138,6 +195,11 @@ SensorManager::SensorManager()
sensordLogW() << "Error setting socket permissions! " << SOCKET_NAME;
}

serviceWatcher_ = new QDBusServiceWatcher(this);
serviceWatcher_->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
QObject::connect(serviceWatcher_, &QDBusServiceWatcher::serviceUnregistered,
this, &SensorManager::dbusClientUnregistered);

#ifdef SENSORFW_MCE_WATCHER
mceWatcher_ = new MceWatcher(this);
connect(mceWatcher_, SIGNAL(displayStateChanged(const bool)),
Expand Down Expand Up @@ -211,6 +273,7 @@ SensorManager::~SensorManager()

delete socketHandler_;
delete pipeNotifier_;
delete serviceWatcher_;
if (pipefds_[0]) close(pipefds_[0]);
if (pipefds_[1]) close(pipefds_[1]);

Expand Down Expand Up @@ -260,6 +323,7 @@ bool SensorManager::registerService()
setError(SmCanNotRegisterService, error.message());
return false;
}
serviceWatcher_->setConnection(bus());
return true;
}

Expand Down Expand Up @@ -368,8 +432,12 @@ int SensorManager::requestSensor(const QString& id)
return INVALID_SESSION;
}

QString clientName = "";
if ( calledFromDBus() )
clientName = message().service();

int sessionId = createNewSessionId();
if(!entryIt.value().sensor_)
if (!entryIt.value().sensor_)
{
AbstractSensorChannel* sensor = addSensor(id);
if ( sensor == NULL )
Expand All @@ -380,12 +448,32 @@ int SensorManager::requestSensor(const QString& id)
entryIt.value().sensor_ = sensor;
}
entryIt.value().sessions_.insert(sessionId);
if ( !clientName.isEmpty() )
{
QMap<int, SessionInstanceEntry*>::iterator sessionIt = sessionInstanceMap_.insert(
sessionId, new SessionInstanceEntry(this, sessionId, clientName));
serviceWatcher_->addWatchedService(clientName);
sessionIt.value()->expectConnection(SOCKET_CONNECTION_TIMEOUT_MS);
}

return sessionId;
}

bool SensorManager::releaseSensor(const QString& id, int sessionId)
{
QString clientName = "";
QMap<int, SessionInstanceEntry*>::iterator sessionIt = sessionInstanceMap_.find(sessionId);
if ( calledFromDBus() )
{
clientName = message().service();
if ( sessionIt == sessionInstanceMap_.end() || sessionIt.value()->m_clientName != clientName )
{
sensordLogW() << "Ignoring attempt to release session" << sessionId
<< "that wasn't previously registered for D-Bus client" << clientName;
return false;
}
}

sensordLogD() << "Releasing sensor '" << id << "' for session: " << sessionId;

clearError();
Expand Down Expand Up @@ -431,6 +519,28 @@ bool SensorManager::releaseSensor(const QString& id, int sessionId)
setError( SmNotInstantiated, tr("invalid sessionId, no session to release") );
}

if ( sessionIt != sessionInstanceMap_.end() )
{
delete sessionIt.value();
sessionInstanceMap_.erase(sessionIt);
}

if (!clientName.isEmpty())
{
bool hasMoreSessions = false;
for (sessionIt = sessionInstanceMap_.begin(); sessionIt != sessionInstanceMap_.end(); ++sessionIt)
{
if (sessionIt.value()->m_clientName == clientName)
{
hasMoreSessions = true;
break;
}
}

if (!hasMoreSessions)
serviceWatcher_->removeWatchedService(clientName);
}

socketHandler_->removeSession(sessionId);

return returnValue;
Expand Down Expand Up @@ -689,6 +799,19 @@ void SensorManager::lostClient(int sessionId)
sensordLogW() << "[SensorManager]: Lost session " << sessionId << " detected, but not found from session list";
}

void SensorManager::dbusClientUnregistered(const QString &clientName)
{
sensordLogD() << "Watched D-Bus service '" << clientName << "' unregistered";
QMap<int, SessionInstanceEntry*>::iterator it = sessionInstanceMap_.begin();
while (it != sessionInstanceMap_.end())
{
QMap<int, SessionInstanceEntry*>::iterator prev = it;
++it;
if (prev.value()->m_clientName == clientName)
lostClient(prev.key());
}
}

void SensorManager::displayStateChanged(bool displayState)
{
sensordLogD() << "Signal detected, display state changed to:" << displayState;
Expand Down
63 changes: 62 additions & 1 deletion core/sensormanager.h
Expand Up @@ -30,6 +30,9 @@
#ifndef SENSORMANAGER_H
#define SENSORMANAGER_H

#include <QDBusContext>
#include <QDBusServiceWatcher>

#include "abstractsensor.h"
#include "abstractchain.h"
#include "deviceadaptor.h"
Expand All @@ -50,6 +53,7 @@ class MceWatcher;
#endif

class QSocketNotifier;
class QTimer;
class SocketHandler;

/**
Expand Down Expand Up @@ -123,11 +127,57 @@ class DeviceAdaptorInstanceEntry
QString type_; /**< Type */
};

/**
* Sensor session instance entry. Contains session ID, D-Bus service name of
* connecting side and timer for initial connection timeout.
*/
class SessionInstanceEntry : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(SessionInstanceEntry)
public:
/**
* Constructor.
*
* @param sessionId Sensor ID
* @param clientName D-Bus service name of requesting side
*/
SessionInstanceEntry(QObject* parent, int sessionId, const QString& clientName);

/**
* Destructor.
*/
~SessionInstanceEntry();

/**
* Start timer to check if socket connection has been established after timeout.
*
* @param msec time to wait for socket connection.
*/
void expectConnection(int msec);

int m_sessionId; /**< Session ID */
QString m_clientName; /**< D-Bus private client name */
QTimer* m_timer; /**< timer for initial connection */

public slots:

/**
* Callback for initial connection timer.
*/
void timerTimeout();

/**
* Callback for session socket connection getting established.
*/
void sessionConnected(int sessionId);
};

/**
* Sensor manager. Singleton class which manages client sessions and
* track existence and usage of sensors, chains and adaptors.
*/
class SensorManager : public QObject
class SensorManager : public QObject, protected QDBusContext
{
Q_OBJECT
Q_DISABLE_COPY(SensorManager)
Expand Down Expand Up @@ -367,6 +417,13 @@ private Q_SLOTS:
*/
void lostClient(int sessionId);

/**
* Callback for D-Bus service unregistration.
*
* @param sessionId Session ID.
*/
void dbusClientUnregistered(const QString &clientName);

/**
* Callback for MCE or LS display state change event.
*
Expand Down Expand Up @@ -473,6 +530,7 @@ private Q_SLOTS:

QMap<QString, SensorChannelFactoryMethod> sensorFactoryMap_; /**< factories for sensor types */
QMap<QString, SensorInstanceEntry> sensorInstanceMap_; /**< sensor instances */
QMap<int, SessionInstanceEntry*> sessionInstanceMap_; /**< sensor session instances */

QMap<QString, DeviceAdaptorFactoryMethod> deviceAdaptorFactoryMap_; /**< factories for adaptor types. */
QMap<QString, DeviceAdaptorInstanceEntry> deviceAdaptorInstanceMap_; /**< adaptor instances */
Expand All @@ -483,6 +541,7 @@ private Q_SLOTS:
QMap<QString, FilterFactoryMethod> filterFactoryMap_; /**< factories for filter types */

SocketHandler* socketHandler_; /**< socket handler */
QDBusServiceWatcher* serviceWatcher_; /**< D-Bus service watcher */
MceWatcher* mceWatcher_; /**< MCE watcher */
#ifdef SENSORFW_LUNA_SERVICE_CLIENT
LSClient* lsClient_; /**< LS client */
Expand All @@ -496,6 +555,8 @@ private Q_SLOTS:
static int sessionIdCount_; /** session ID counter */

double deviation;

static const int SOCKET_CONNECTION_TIMEOUT_MS;
};

template<class SENSOR_TYPE>
Expand Down
9 changes: 9 additions & 0 deletions core/sockethandler.cpp
Expand Up @@ -276,6 +276,15 @@ bool SocketHandler::removeSession(int sessionId)
return true;
}

void SocketHandler::checkConnectionEstablished(int sessionId)
{
if (!(m_idMap.keys().contains(sessionId))) {
sensordLogW() << "[SocketHandler]: Socket connection for session" << sessionId
<< "hasn't been estabilished. Considering session lost";
emit lostSession(sessionId);
}
}

void SocketHandler::newConnection()
{
sensordLogT() << "[SocketHandler]: New connection received.";
Expand Down
17 changes: 17 additions & 0 deletions core/sockethandler.h
Expand Up @@ -236,6 +236,15 @@ class SocketHandler : public QObject
*/
bool removeSession(int sessionId);

/**
* Verify if socket connection for a given session has been established.
* If there has been no connection, session is considered lost and
* lostSession signal is emitted.
*
* @param sessionId Session ID.
*/
void checkConnectionEstablished(int sessionId);

/**
* Get socket file descriptor for given session.
*
Expand Down Expand Up @@ -338,6 +347,14 @@ class SocketHandler : public QObject
void setDownsampling(int sessionId, bool value);

Q_SIGNALS:
/**
* Signal is emitted for new client connection after it sent the
session id.
*
* @param sessionId Session ID.
*/
void connectedSession(int sessionId);

/**
* Signal is emitted for lost sessions which can happen for example
* if application using sensorfw crashes.
Expand Down

0 comments on commit 0fba832

Please sign in to comment.