public:
virtual ~ServiceBase();
- GDBusConnection* getConnection();
-
+ // These functions should not be called from individual services
bool start();
-
void stop();
+ void notifyUserNew();
+ void notifyUserRemoved();
+ static void setActiveUser(uid_t uid);
+ static void setSingleThreading();
+ // ---
// If the GVariant 'param' is floating, it is consumed.
void publish(const std::string& busName, const std::string& signalName, GVariant* param);
- uid_t getActiveUser();
+ GDBusConnection* getConnection();
- static void setSingleThreading();
+ static uid_t getActiveUser();
+
+ virtual bool isUserService() = 0;
protected:
ServiceBase(GDBusConnection* conn, const char* serviceName, const char* methodSpecs);
virtual void cleanup() = 0;
- virtual void onUserActivated(uid_t uid) = 0;
-
virtual ClientBase* createClient(const std::string& busName) = 0;
+ virtual void onUserActivated();
+
+ virtual void onUserDeactivated();
+
private:
static gpointer __threadFunc(gpointer data);
- static void __onUserNew(GDBusConnection* conn, const gchar* sender,
- const gchar* path, const gchar* iface, const gchar* name,
- GVariant* param, gpointer userData);
-
static void __onMethodCalled(GDBusConnection* conn, const gchar* sender,
const gchar* path, const gchar* iface, const gchar* name,
GVariant* param, GDBusMethodInvocation* invocation, gpointer userData);
const gchar* path, const gchar* iface, const gchar* name,
GVariant* param, gpointer userData);
+ static gboolean __onUserActivated(gpointer data);
+
+ static gboolean __onUserDeactivated(gpointer data);
+
static gboolean __stopMainLoop(gpointer data);
void __onMethodCalled(const std::string& sender,
unsigned int __watch(const std::string& busName, ClientBase* client);
void __unwatch(unsigned int watchId);
+ bool __running;
const char* __serviceName;
GMainContext* __mainContext;
GDBusNodeInfo* __nodeInfo;
guint __registrationId;
- guint __userNewSignalId;
- uid_t __activeUid;
struct ClientInfo {
ClientBase* client;
* limitations under the License.
*/
-#include <systemd/sd-login.h>
+#include <atomic>
#include <ScopeMutex.h>
#include <ClientBase.h>
#include <MethodCall.h>
using namespace ctx;
+static std::atomic_uint __activeUid;
+
bool ServiceBase::__singleThreading = false;
ServiceBase::ServiceBase(GDBusConnection* conn, const char* serviceName, const char* methodSpecs) :
+ __running(false),
__serviceName(serviceName),
__mainContext(NULL),
__mainLoop(NULL),
__objPath(CTX_DBUS_PATH),
__interface(CTX_DBUS_IFACE),
__nodeInfo(NULL),
- __registrationId(0),
- __userNewSignalId(0),
- __activeUid(0)
+ __registrationId(0)
{
__objPath += serviceName;
__interface += serviceName;
bool ServiceBase::start()
{
+ IF_FAIL_RETURN(!__running, true);
+ __running = true;
+
_I("Preparing '%s'", __serviceName);
if (__singleThreading) {
void ServiceBase::stop()
{
+ IF_FAIL_VOID(__running);
+ __running = false;
+
if (__singleThreading) {
__release();
} else {
uid_t ServiceBase::getActiveUser()
{
- if (__activeUid == 0) {
- uid_t* users = NULL;
- int numUsers = sd_get_active_uids(&users);
- if (numUsers > 0)
- __activeUid = users[0];
- free(users);
- }
- return __activeUid;
+ return __activeUid.load();
+}
+
+void ServiceBase::setActiveUser(uid_t uid)
+{
+ __activeUid.store(uid);
+}
+
+void ServiceBase::onUserActivated()
+{
+}
+
+void ServiceBase::onUserDeactivated()
+{
+}
+
+void ServiceBase::notifyUserNew()
+{
+ GSource* gSrc = g_idle_source_new();
+ IF_FAIL_VOID_TAG(gSrc, _E, "Memory allocation failed");
+
+ g_source_set_callback(gSrc, __onUserActivated, this, NULL);
+ g_source_attach(gSrc, __mainContext);
+}
+
+void ServiceBase::notifyUserRemoved()
+{
+ GSource* gSrc = g_idle_source_new();
+ IF_FAIL_VOID_TAG(gSrc, _E, "Memory allocation failed");
+
+ g_source_set_callback(gSrc, __onUserDeactivated, this, NULL);
+ g_source_attach(gSrc, __mainContext);
+}
+
+gboolean ServiceBase::__onUserActivated(gpointer data)
+{
+ ServiceBase* svc = static_cast<ServiceBase*>(data);
+ svc->onUserActivated();
+ return G_SOURCE_REMOVE;
+}
+
+gboolean ServiceBase::__onUserDeactivated(gpointer data)
+{
+ ServiceBase* svc = static_cast<ServiceBase*>(data);
+ svc->onUserDeactivated();
+ return G_SOURCE_REMOVE;
}
gpointer ServiceBase::__threadFunc(gpointer data)
HANDLE_GERROR(gerr);
IF_FAIL_RETURN_TAG(__registrationId > 0, false, _E, "Object registration failed");
- __userNewSignalId = g_dbus_connection_signal_subscribe(__connection,
- NULL, "org.freedesktop.login1.Manager", "UserNew", NULL,
- NULL, G_DBUS_SIGNAL_FLAGS_NONE, __onUserNew, this, NULL);
-
return prepare();
}
cleanup();
- if (__userNewSignalId > 0)
- g_dbus_connection_signal_unsubscribe(__connection, __userNewSignalId);
-
if (__registrationId > 0)
g_dbus_connection_unregister_object(__connection, __registrationId);
g_main_context_unref(__mainContext);
}
-void ServiceBase::__onUserNew(GDBusConnection* conn, const gchar* sender,
- const gchar* path, const gchar* iface, const gchar* name,
- GVariant* param, gpointer userData)
-{
- uint32_t uid = 0;
- g_variant_get_child(param, 0, "u", &uid);
- IF_FAIL_VOID_TAG(uid > 0, _W, "UID == 0");
-
- ServiceBase* svc = static_cast<ServiceBase*>(userData);
-
- if (svc->__activeUid == static_cast<uid_t>(uid))
- return;
-
- svc->__activeUid = static_cast<uid_t>(uid);
- svc->onUserActivated(svc->__activeUid);
-}
-
void ServiceBase::__onMethodCalled(GDBusConnection* conn, const gchar* sender,
const gchar* path, const gchar* iface, const gchar* name,
GVariant* param, GDBusMethodInvocation* invocation, gpointer userData)