summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-05-13 22:01:16 -0700
committerMarcel Holtmann <marcel@holtmann.org>2009-05-13 22:01:16 -0700
commitbe4f8242a9946a059d85cfa855edcb5d45d1811b (patch)
treecfcba92f81c4806ccca62c27184546bb75a6c315 /src
parent4e2598a7793f9957188a0d3b9858b121f04afb82 (diff)
downloadconnman-be4f8242a9946a059d85cfa855edcb5d45d1811b.tar.gz
connman-be4f8242a9946a059d85cfa855edcb5d45d1811b.tar.bz2
connman-be4f8242a9946a059d85cfa855edcb5d45d1811b.zip
Add support for async service connect and timeout handling
Diffstat (limited to 'src')
-rw-r--r--src/element.c6
-rw-r--r--src/service.c95
2 files changed, 98 insertions, 3 deletions
diff --git a/src/element.c b/src/element.c
index ecdf4bfa..1ae88bb8 100644
--- a/src/element.c
+++ b/src/element.c
@@ -1312,6 +1312,8 @@ int connman_element_set_enabled(struct connman_element *element,
void connman_element_set_error(struct connman_element *element,
enum connman_element_error error)
{
+ struct connman_service *service;
+
DBG("element %p error %d", element, error);
if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
@@ -1322,6 +1324,10 @@ void connman_element_set_error(struct connman_element *element,
if (element->driver && element->driver->change)
element->driver->change(element);
+
+ service = __connman_element_get_service(element);
+ __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_FAILURE);
}
int __connman_element_init(DBusConnection *conn, const char *device,
diff --git a/src/service.c b/src/service.c
index 3a971fee..c3d4e201 100644
--- a/src/service.c
+++ b/src/service.c
@@ -48,6 +48,8 @@ struct connman_service {
char *profile;
struct connman_device *device;
struct connman_network *network;
+ DBusMessage *pending;
+ guint timeout;
};
static void append_path(gpointer value, gpointer user_data)
@@ -282,11 +284,39 @@ static DBusMessage *set_property(DBusConnection *conn,
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
+static gboolean connect_timeout(gpointer user_data)
+{
+ struct connman_service *service = user_data;
+
+ DBG("service %p", service);
+
+ service->timeout = 0;
+
+ if (service->pending != NULL) {
+ DBusMessage *reply;
+
+ reply = __connman_error_operation_timeout(service->pending);
+ if (reply != NULL)
+ g_dbus_send_message(connection, reply);
+
+ dbus_message_unref(service->pending);
+ service->pending = NULL;
+ }
+
+ return FALSE;
+}
+
static DBusMessage *connect_service(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct connman_service *service = data;
+ if (service->pending != NULL)
+ return __connman_error_in_progress(msg);
+
+ if (service->state == CONNMAN_SERVICE_STATE_READY)
+ return __connman_error_already_connected(msg);
+
if (service->network != NULL) {
int err;
@@ -297,7 +327,12 @@ static DBusMessage *connect_service(DBusConnection *conn,
if (err < 0 && err != -EINPROGRESS)
return __connman_error_failed(msg, -err);
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ service->pending = dbus_message_ref(msg);
+
+ service->timeout = g_timeout_add_seconds(45,
+ connect_timeout, service);
+
+ return NULL;
} else if (service->device != NULL) {
if (service->favorite == FALSE)
return __connman_error_no_carrier(msg);
@@ -305,7 +340,11 @@ static DBusMessage *connect_service(DBusConnection *conn,
if (__connman_device_connect(service->device) < 0)
return __connman_error_failed(msg, EINVAL);
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ service->pending = dbus_message_ref(msg);
+ service->timeout = g_timeout_add_seconds(15,
+ connect_timeout, service);
+
+ return NULL;
}
return __connman_error_not_supported(msg);
@@ -316,6 +355,19 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
{
struct connman_service *service = data;
+ if (service->pending != NULL) {
+ DBusMessage *reply;
+
+ reply = __connman_error_operation_aborted(service->pending);
+ if (reply != NULL)
+ g_dbus_send_message(conn, reply);
+
+ dbus_message_unref(service->pending);
+ service->pending = NULL;
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
+
if (service->network != NULL) {
int err;
@@ -387,7 +439,8 @@ static DBusMessage *move_after(DBusConnection *conn,
static GDBusMethodTable service_methods[] = {
{ "GetProperties", "", "a{sv}", get_properties },
{ "SetProperty", "sv", "", set_property },
- { "Connect", "", "", connect_service },
+ { "Connect", "", "", connect_service,
+ G_DBUS_METHOD_FLAG_ASYNC },
{ "Disconnect", "", "", disconnect_service },
{ "Remove", "", "", remove_service },
{ "MoveBefore", "o", "", move_before },
@@ -409,6 +462,14 @@ static void service_free(gpointer data)
g_hash_table_remove(service_hash, service->identifier);
+ if (service->timeout > 0)
+ g_source_remove(service->timeout);
+
+ if (service->pending != NULL) {
+ dbus_message_unref(service->pending);
+ service->pending = NULL;
+ }
+
service->path = NULL;
if (path != NULL) {
@@ -622,6 +683,34 @@ int __connman_service_indicate_state(struct connman_service *service,
if (state == CONNMAN_SERVICE_STATE_READY) {
connman_service_set_favorite(service, TRUE);
__connman_storage_save_service(service);
+
+ if (service->timeout > 0)
+ g_source_remove(service->timeout);
+
+ if (service->pending != NULL) {
+ g_dbus_send_reply(connection, service->pending,
+ DBUS_TYPE_INVALID);
+
+ dbus_message_unref(service->pending);
+ service->pending = NULL;
+ }
+
+ }
+
+ if (state == CONNMAN_SERVICE_STATE_FAILURE) {
+ if (service->timeout > 0)
+ g_source_remove(service->timeout);
+
+ if (service->pending != NULL) {
+ DBusMessage *reply;
+
+ reply = __connman_error_failed(service->pending, EIO);
+ if (reply != NULL)
+ g_dbus_send_message(connection, reply);
+
+ dbus_message_unref(service->pending);
+ service->pending = NULL;
+ }
}
return 0;