summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Wagner <daniel.wagner@bmw-carit.de>2011-03-31 12:36:12 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2011-03-31 12:36:12 +0200
commiteca42aa6eefa7dadb1d0d8829f753c6a76b66f70 (patch)
treee24f1a0abb5d370a442a5c85729f7e45aaec67b3
parent70534def72a9e59f0df63c7c02ba34c883c88fe1 (diff)
downloadconnman-eca42aa6eefa7dadb1d0d8829f753c6a76b66f70.tar.gz
connman-eca42aa6eefa7dadb1d0d8829f753c6a76b66f70.tar.bz2
connman-eca42aa6eefa7dadb1d0d8829f753c6a76b66f70.zip
session: Refactor session API
Refactor the D-Bus API of the session according the documentation. All function and properties are only empty stubs.
-rw-r--r--include/dbus.h2
-rw-r--r--src/connman-dbus.conf1
-rw-r--r--src/connman.h6
-rw-r--r--src/manager.c32
-rw-r--r--src/session.c359
5 files changed, 208 insertions, 192 deletions
diff --git a/include/dbus.h b/include/dbus.h
index 9be76b2f..83f3d30c 100644
--- a/include/dbus.h
+++ b/include/dbus.h
@@ -44,6 +44,8 @@ extern "C" {
#define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service"
#define CONNMAN_PROVIDER_INTERFACE CONNMAN_SERVICE ".Provider"
#define CONNMAN_TECHNOLOGY_INTERFACE CONNMAN_SERVICE ".Technology"
+#define CONNMAN_SESSION_INTERFACE CONNMAN_SERVICE ".Session"
+#define CONNMAN_NOTIFICATION_INTERFACE CONNMAN_SERVICE ".Notification"
#define CONNMAN_PRIVILEGE_MODIFY 1
#define CONNMAN_PRIVILEGE_SECRET 2
diff --git a/src/connman-dbus.conf b/src/connman-dbus.conf
index 311f28c7..98a773ea 100644
--- a/src/connman-dbus.conf
+++ b/src/connman-dbus.conf
@@ -6,6 +6,7 @@
<allow send_destination="net.connman"/>
<allow send_interface="net.connman.Agent"/>
<allow send_interface="net.connman.Counter"/>
+ <allow send_interface="net.connman.Notification"/>
</policy>
<policy at_console="true">
<allow send_destination="net.connman"/>
diff --git a/src/connman.h b/src/connman.h
index 4196127e..bb08267e 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -610,8 +610,10 @@ int __connman_rtnl_send(const void *buf, size_t len);
connman_bool_t __connman_session_mode();
void __connman_session_set_mode(connman_bool_t enable);
-int __connman_session_release(const char *owner);
-struct connman_service *__connman_session_request(const char *bearer, const char *owner);
+
+int __connman_session_create(DBusMessage *msg);
+int __connman_session_destroy(DBusMessage *msg);
+
int __connman_session_init(void);
void __connman_session_cleanup(void);
diff --git a/src/manager.c b/src/manager.c
index 198875da..349ddb41 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -589,40 +589,28 @@ static DBusMessage *unregister_counter(DBusConnection *conn,
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
-static DBusMessage *request_session(DBusConnection *conn,
+static DBusMessage *create_session(DBusConnection *conn,
DBusMessage *msg, void *data)
{
- const char *bearer, *sender, *service_path;
- struct connman_service *service;
+ int err;
DBG("conn %p", conn);
- sender = dbus_message_get_sender(msg);
-
- dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &bearer,
- DBUS_TYPE_INVALID);
-
- service = __connman_session_request(bearer, sender);
- if (service == NULL)
- return __connman_error_failed(msg, EINVAL);
-
- service_path = __connman_service_get_path(service);
+ err = __connman_session_create(msg);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
- return g_dbus_create_reply(msg, DBUS_TYPE_OBJECT_PATH, &service_path,
- DBUS_TYPE_INVALID);
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
-static DBusMessage *release_session(DBusConnection *conn,
+static DBusMessage *destroy_session(DBusConnection *conn,
DBusMessage *msg, void *data)
{
- const char *sender;
int err;
DBG("conn %p", conn);
- sender = dbus_message_get_sender(msg);
-
- err = __connman_session_release(sender);
+ err = __connman_session_destroy(msg);
if (err < 0)
return __connman_error_failed(msg, -err);
@@ -651,8 +639,8 @@ static GDBusMethodTable manager_methods[] = {
{ "UnregisterAgent", "o", "", unregister_agent },
{ "RegisterCounter", "ouu", "", register_counter },
{ "UnregisterCounter", "o", "", unregister_counter },
- { "RequestSession", "s", "o", request_session },
- { "ReleaseSession", "s", "", release_session },
+ { "CreateSession", "a{sv}o", "o", create_session },
+ { "DestroySession", "o", "", destroy_session },
{ },
};
diff --git a/src/session.c b/src/session.c
index 391899fb..1540d6b9 100644
--- a/src/session.c
+++ b/src/session.c
@@ -3,6 +3,7 @@
* Connection Manager
*
* Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright (C) 2011 BWM CarIT GmbH. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -23,244 +24,268 @@
#include <config.h>
#endif
-#include <string.h>
-
#include <gdbus.h>
#include "connman.h"
static DBusConnection *connection;
static GHashTable *session_hash;
-static GHashTable *bearer_hash;
static connman_bool_t sessionmode;
-struct connman_bearer {
- gint refcount;
- char *name;
-};
-
struct connman_session {
- gint refcount;
char *owner;
- guint watch;
- struct connman_bearer *bearer;
- struct connman_service *service;
+ char *session_path;
+ char *notify_path;
+ guint notify_watch;
};
-static enum connman_service_type bearer2service(const char *bearer)
-{
- if (bearer == NULL)
- return CONNMAN_SERVICE_TYPE_UNKNOWN;
-
- DBG("%s", bearer);
-
- if (g_strcmp0(bearer, "ethernet") == 0)
- return CONNMAN_SERVICE_TYPE_ETHERNET;
- else if (g_strcmp0(bearer, "wifi") == 0)
- return CONNMAN_SERVICE_TYPE_WIFI;
- else if (g_strcmp0(bearer, "wimax") == 0)
- return CONNMAN_SERVICE_TYPE_WIMAX;
- else if (g_strcmp0(bearer, "bluetooth") == 0)
- return CONNMAN_SERVICE_TYPE_BLUETOOTH;
- else if (g_strcmp0(bearer, "3g") == 0)
- return CONNMAN_SERVICE_TYPE_CELLULAR;
- else
- return CONNMAN_SERVICE_TYPE_UNKNOWN;
-}
-
-static char *service2bearer(enum connman_service_type type)
+static gboolean session_notify_all(gpointer user_data)
{
- DBG("%d", type);
-
- switch (type) {
- case CONNMAN_SERVICE_TYPE_ETHERNET:
- return "ethernet";
- case CONNMAN_SERVICE_TYPE_WIFI:
- return "wifi";
- case CONNMAN_SERVICE_TYPE_WIMAX:
- return "wimax";
- case CONNMAN_SERVICE_TYPE_BLUETOOTH:
- return "bluetooth";
- case CONNMAN_SERVICE_TYPE_CELLULAR:
- return "3g";
- case CONNMAN_SERVICE_TYPE_UNKNOWN:
- case CONNMAN_SERVICE_TYPE_SYSTEM:
- case CONNMAN_SERVICE_TYPE_GPS:
- case CONNMAN_SERVICE_TYPE_VPN:
- case CONNMAN_SERVICE_TYPE_GADGET:
- return NULL;
+ struct connman_session *session = user_data;
+ DBusMessage *msg;
+ DBusMessageIter array, dict;
+
+ DBG("session %p owner %s notify_path %s", session,
+ session->owner, session->notify_path);
+
+ msg = dbus_message_new_method_call(session->owner, session->notify_path,
+ CONNMAN_NOTIFICATION_INTERFACE,
+ "Update");
+ if (msg == NULL) {
+ connman_error("Could not create notification message");
+ return FALSE;
}
- return NULL;
-}
+ dbus_message_iter_init_append(msg, &array);
-static void remove_bearer(gpointer user_data)
-{
- struct connman_bearer *bearer = user_data;
+ connman_dbus_dict_open(&array, &dict);
+
+ /* append settings */
- g_free(bearer->name);
- g_free(bearer);
+ connman_dbus_dict_close(&array, &dict);
+
+ g_dbus_send_message(connection, msg);
+
+ return FALSE;
}
-static void remove_session(gpointer user_data)
+static void cleanup_session(gpointer user_data)
{
struct connman_session *session = user_data;
- session->bearer = NULL;
- if (session->service)
- connman_service_unref(session->service);
+ DBG("remove %s", session->session_path);
+
g_free(session->owner);
+ g_free(session->session_path);
+ g_free(session->notify_path);
+
g_free(session);
}
-static int session_disconnect(struct connman_session *session)
+static void release_session(gpointer key, gpointer value, gpointer user_data)
{
- struct connman_bearer *bearer = session->bearer;
+ struct connman_session *session = value;
+ DBusMessage *message;
- DBG("%s", session->owner);
+ DBG("owner %s path %s", session->owner, session->notify_path);
- if (session == NULL)
- return -EINVAL;
+ if (session->notify_watch > 0)
+ g_dbus_remove_watch(connection, session->notify_watch);
- /*
- * Once a bearer is no longer referenced we actually disconnect
- * the corresponding service.
- */
- if (bearer == NULL || g_atomic_int_dec_and_test(&bearer->refcount)) {
- struct connman_network *network;
- struct connman_device *device;
-
- /*
- * We toggle the reconnect flag to false when releasing a
- * session. This way a previously connected service will
- * not autoconnect once we've completely release a session.
- */
- network = __connman_service_get_network(session->service);
- if (network == NULL)
- return -EINVAL;
-
- device = connman_network_get_device(network);
- if (device == NULL)
- return -EINVAL;
-
- __connman_device_set_reconnect(device, FALSE);
-
- __connman_service_disconnect(session->service);
- connman_service_unref(session->service);
-
- g_hash_table_remove(bearer_hash, bearer);
- }
+ g_dbus_unregister_interface(connection, session->session_path,
+ CONNMAN_SESSION_INTERFACE);
+
+ message = dbus_message_new_method_call(session->owner,
+ session->notify_path,
+ CONNMAN_NOTIFICATION_INTERFACE,
+ "Release");
+ if (message == NULL)
+ return;
- if (session->watch > 0)
- g_dbus_remove_watch(connection, session->watch);
+ dbus_message_set_no_reply(message, TRUE);
- g_hash_table_remove(session_hash, session);
+ g_dbus_send_message(connection, message);
+}
+
+static int session_disconnect(struct connman_session *session)
+{
+ DBG("session %p, %s", session, session->owner);
+
+ if (session->notify_watch > 0)
+ g_dbus_remove_watch(connection, session->notify_watch);
+
+ g_dbus_unregister_interface(connection, session->session_path,
+ CONNMAN_SESSION_INTERFACE);
+
+ g_hash_table_remove(session_hash, session->session_path);
return 0;
}
-static void owner_disconnect(DBusConnection *connection, void *user_data)
+static void owner_disconnect(DBusConnection *conn, void *user_data)
{
struct connman_session *session = user_data;
- DBG("%s died", session->owner);
+ DBG("session %p, %s died", session, session->owner);
session_disconnect(session);
}
-int __connman_session_release(const char *owner)
+static DBusMessage *destroy_session(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
{
- struct connman_session *session;
+ struct connman_session *session = user_data;
- DBG("owner %s", owner);
+ DBG("session %p", session);
- session = g_hash_table_lookup(session_hash, owner);
- if (session == NULL)
- return -EINVAL;
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *connect_session(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_session *session = user_data;
- if (g_atomic_int_dec_and_test(&session->refcount))
- return session_disconnect(session);
+ DBG("session %p", session);
- return 0;
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *disconnect_session(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_session *session = user_data;
+
+ DBG("session %p", session);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *change_session(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_session *session = user_data;
+
+ DBG("session %p", session);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
-struct connman_service *__connman_session_request(const char *bearer_name,
- const char *owner)
+static GDBusMethodTable session_methods[] = {
+ { "Destroy", "", "", destroy_session },
+ { "Connect", "", "", connect_session },
+ { "Disconnect", "", "", disconnect_session },
+ { "Change", "sv", "", change_session },
+ { },
+};
+
+int __connman_session_create(DBusMessage *msg)
{
+ const char *owner, *notify_path;
+ char *session_path;
+ DBusMessageIter iter, array;
struct connman_session *session;
- struct connman_bearer *bearer;
- enum connman_service_type service_type;
- const char *bearer_name_new;
- size_t bearer_name_len;
+ int err;
+
+ owner = dbus_message_get_sender(msg);
- if (bearer_name == NULL)
- return NULL;
+ DBG("owner %s", owner);
- DBG("owner %s bearer %s", owner, bearer_name);
+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_recurse(&iter, &array);
- bearer_name_len = strlen(bearer_name);
+ while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY)
+ dbus_message_iter_next(&array);
- session = g_hash_table_lookup(session_hash, owner);
- if (session) {
- /* we only support one bearer per process */
- if (bearer_name_len &&
- g_strcmp0(session->bearer->name, bearer_name))
- return NULL;
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &notify_path);
+
+ if (notify_path == NULL) {
+ session_path = NULL;
+ err = -EINVAL;
+ goto err;
+ }
- g_atomic_int_inc(&session->refcount);
+ session_path = g_strdup_printf("/sessions%s", notify_path);
+ if (session_path == NULL) {
+ err = -ENOMEM;
+ goto err;
+ }
- return session->service;
+ session = g_hash_table_lookup(session_hash, session_path);
+ if (session != NULL) {
+ err = -EEXIST;
+ goto err;
}
session = g_try_new0(struct connman_session, 1);
- if (session == NULL)
- return NULL;
+ if (session == NULL) {
+ err = -ENOMEM;
+ goto err;
+ }
- session->refcount = 1;
session->owner = g_strdup(owner);
- session->service = NULL;
- g_hash_table_replace(session_hash, session->owner, session);
+ session->session_path = session_path;
+ session->notify_path = g_strdup(notify_path);
+ session->notify_watch =
+ g_dbus_add_disconnect_watch(connection, session->owner,
+ owner_disconnect, session, NULL);
+
+ g_hash_table_replace(session_hash, session->session_path, session);
- /* Find and connect service */
- service_type = bearer2service(bearer_name);
+ DBG("add %s", session->session_path);
- session->service = __connman_service_connect_type(service_type);
- if (session->service == NULL)
- goto failed_connect;
+ if (g_dbus_register_interface(connection, session->session_path,
+ CONNMAN_SESSION_INTERFACE,
+ session_methods, NULL,
+ NULL, session, NULL) == FALSE) {
+ connman_error("Failed to register %s", session->session_path);
+ g_hash_table_remove(session_hash, session->session_path);
+ session = NULL;
- connman_service_ref(session->service);
+ err = -EINVAL;
+ goto err;
+ }
- service_type = connman_service_get_type(session->service);
+ g_dbus_send_reply(connection, msg,
+ DBUS_TYPE_OBJECT_PATH, &session->session_path,
+ DBUS_TYPE_INVALID);
- /* We might get a different bearer from the one we requested */
- bearer_name_new = service2bearer(service_type);
+ g_timeout_add_seconds(0, session_notify_all, session);
- /* Refcount the exisiting bearer, or create one */
- bearer = g_hash_table_lookup(bearer_hash, bearer_name_new);
- if (bearer == NULL) {
- bearer = g_try_new0(struct connman_bearer, 1);
- if (bearer == NULL)
- goto failed_bearer;
+ return 0;
- bearer->refcount = 0;
- bearer->name = g_strdup(bearer_name_new);
- g_hash_table_replace(bearer_hash, bearer->name, bearer);
- }
+err:
+ connman_error("Failed to create session");
+ g_free(session_path);
- g_atomic_int_inc(&bearer->refcount);
- session->bearer = bearer;
+ return err;
+}
- session->watch = g_dbus_add_disconnect_watch(connection, session->owner,
- owner_disconnect, session, NULL);
- return session->service;
+int __connman_session_destroy(DBusMessage *msg)
+{
+ const char *owner, *session_path;
+ struct connman_session *session;
-failed_bearer:
- session_disconnect(session);
+ owner = dbus_message_get_sender(msg);
+
+ DBG("owner %s", owner);
-failed_connect:
- g_hash_table_remove(session_hash, session);
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &session_path,
+ DBUS_TYPE_INVALID);
+ if (session_path == NULL)
+ return -EINVAL;
+
+ session = g_hash_table_lookup(session_hash, session_path);
+ if (session == NULL)
+ return -EINVAL;
+
+ if (g_strcmp0(owner, session->owner) != 0)
+ return -EACCES;
- return NULL;
+ session_disconnect(session);
+
+ return 0;
}
connman_bool_t __connman_session_mode()
@@ -290,10 +315,7 @@ int __connman_session_init(void)
return -1;
session_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
- NULL, remove_session);
-
- bearer_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
- NULL, remove_bearer);
+ NULL, cleanup_session);
sessionmode = FALSE;
return 0;
@@ -306,7 +328,8 @@ void __connman_session_cleanup(void)
if (connection == NULL)
return;
- g_hash_table_destroy(bearer_hash);
+ g_hash_table_foreach(session_hash, release_session, NULL);
g_hash_table_destroy(session_hash);
+
dbus_connection_unref(connection);
}