diff options
-rw-r--r-- | plugins/vpn.c | 118 |
1 files changed, 79 insertions, 39 deletions
diff --git a/plugins/vpn.c b/plugins/vpn.c index 39c47e74..c0cde951 100644 --- a/plugins/vpn.c +++ b/plugins/vpn.c @@ -62,9 +62,11 @@ struct vpn_route { struct connection_data { char *path; + char *ident; struct connman_provider *provider; int index; DBusPendingCall *call; + connman_bool_t connect_pending; char *state; char *type; @@ -245,18 +247,13 @@ static void set_provider_state(struct connection_data *data) static int create_provider(struct connection_data *data, void *user_data) { struct connman_provider_driver *driver = user_data; - char *ident; - int err = 0; + int err; DBG("%s", data->path); - ident = g_strdup(get_ident(data->path)); - - data->provider = connman_provider_get(ident); - if (data->provider == NULL) { - err = -ENOMEM; - goto out; - } + data->provider = connman_provider_get(data->ident); + if (data->provider == NULL) + return -ENOMEM; DBG("provider %p name %s", data->provider, data->name); @@ -276,9 +273,7 @@ static int create_provider(struct connection_data *data, void *user_data) set_provider_state(data); } -out: - g_free(ident); - return err; + return 0; } static void destroy_route(gpointer user_data) @@ -302,6 +297,7 @@ static struct connection_data *create_connection_data(const char *path) DBG("path %s", path); data->path = g_strdup(path); + data->ident = g_strdup(get_ident(path)); data->index = -1; data->setting_strings = g_hash_table_new_full(g_str_hash, @@ -490,14 +486,22 @@ static void add_connection(const char *path, DBusMessageIter *properties, { struct connection_data *data; int err; + char *ident = get_ident(path); - data = g_hash_table_lookup(vpn_connections, path); - if (data != NULL) - return; - - data = create_connection_data(path); - if (data == NULL) - return; + data = g_hash_table_lookup(vpn_connections, ident); + if (data != NULL) { + /* + * We might have a dummy connection struct here that + * was created by configuration_create_reply() so in + * that case just continue. + */ + if (data->connect_pending == FALSE) + return; + } else { + data = create_connection_data(path); + if (data == NULL) + return; + } DBG("data %p path %s", data, path); @@ -551,7 +555,7 @@ static void add_connection(const char *path, DBusMessageIter *properties, dbus_message_iter_next(properties); } - g_hash_table_insert(vpn_connections, g_strdup(path), data); + g_hash_table_insert(vpn_connections, g_strdup(data->ident), data); err = create_provider(data, user_data); if (err < 0) @@ -559,11 +563,16 @@ static void add_connection(const char *path, DBusMessageIter *properties, resolv_host_addr(data); + if (data->connect_pending == TRUE) { + connect_provider(data, NULL); + data->connect_pending = FALSE; + } + return; out: - DBG("removing %s", path); - g_hash_table_remove(vpn_connections, path); + DBG("removing %s", data->ident); + g_hash_table_remove(vpn_connections, data->ident); } static void get_connections_reply(DBusPendingCall *call, void *user_data) @@ -581,17 +590,13 @@ static void get_connections_reply(DBusPendingCall *call, void *user_data) DBUS_DICT_ENTRY_END_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING; + if (dbus_pending_call_get_completed(call) == FALSE) + return; + DBG(""); reply = dbus_pending_call_steal_reply(call); - if (dbus_message_has_signature(reply, signature) == FALSE) { - connman_error("vpnd signature \"%s\" does not match " - "expected \"%s\"", - dbus_message_get_signature(reply), signature); - goto done; - } - dbus_error_init(&error); if (dbus_set_error_from_message(&error, reply) == TRUE) { @@ -600,6 +605,13 @@ static void get_connections_reply(DBusPendingCall *call, void *user_data) goto done; } + if (dbus_message_has_signature(reply, signature) == FALSE) { + connman_error("vpnd signature \"%s\" does not match " + "expected \"%s\"", + dbus_message_get_signature(reply), signature); + goto done; + } + if (dbus_message_iter_init(reply, &array) == FALSE) goto done; @@ -670,6 +682,9 @@ static void remove_connection_reply(DBusPendingCall *call, void *user_data) DBusMessage *reply; DBusError error; + if (dbus_pending_call_get_completed(call) == FALSE) + return; + DBG(""); reply = dbus_pending_call_steal_reply(call); @@ -758,6 +773,9 @@ static void disconnect_reply(DBusPendingCall *call, void *user_data) DBusMessage *reply; DBusError error; + if (dbus_pending_call_get_completed(call) == FALSE) + return; + DBG(""); reply = dbus_pending_call_steal_reply(call); @@ -842,18 +860,16 @@ static void configuration_create_reply(DBusPendingCall *call, void *user_data) DBusMessageIter iter; const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING; const char *path; + char *ident; + struct connection_data *data; + + if (dbus_pending_call_get_completed(call) == FALSE) + return; DBG("user %p", user_data); reply = dbus_pending_call_steal_reply(call); - if (dbus_message_has_signature(reply, signature) == FALSE) { - connman_error("vpn configuration signature \"%s\" does not " - "match expected \"%s\"", - dbus_message_get_signature(reply), signature); - goto done; - } - dbus_error_init(&error); if (dbus_set_error_from_message(&error, reply) == TRUE) { @@ -862,6 +878,13 @@ static void configuration_create_reply(DBusPendingCall *call, void *user_data) goto done; } + if (dbus_message_has_signature(reply, signature) == FALSE) { + connman_error("vpn configuration signature \"%s\" does not " + "match expected \"%s\"", + dbus_message_get_signature(reply), signature); + goto done; + } + if (dbus_message_iter_init(reply, &iter) == FALSE) goto done; @@ -870,7 +893,23 @@ static void configuration_create_reply(DBusPendingCall *call, void *user_data) /* * Then try to connect the VPN as expected by ConnectProvider API */ - // XXX: + ident = get_ident(path); + + data = g_hash_table_lookup(vpn_connections, ident); + if (data == NULL) { + /* + * We have not yet received service created message + * from vpnd. So create a dummy connection struct + * and wait a while. + */ + data = create_connection_data(path); + data->connect_pending = TRUE; + + g_hash_table_insert(vpn_connections, g_strdup(ident), data); + + } else { + connect_provider(data, NULL); + } done: dbus_message_unref(reply); @@ -1313,6 +1352,7 @@ static void connection_destroy(gpointer hash_data) destroy_provider(data); g_free(data->path); + g_free(data->ident); g_free(data->state); g_free(data->type); g_free(data->name); @@ -1355,7 +1395,7 @@ static void remove_connection(DBusConnection *conn, const char *path) { DBG("path %s", path); - g_hash_table_remove(vpn_connections, path); + g_hash_table_remove(vpn_connections, get_ident(path)); } static gboolean connection_removed(DBusConnection *conn, DBusMessage *message, @@ -1553,7 +1593,7 @@ static gboolean property_changed(DBusConnection *conn, return TRUE; } - data = g_hash_table_lookup(vpn_connections, path); + data = g_hash_table_lookup(vpn_connections, get_ident(path)); if (data == NULL) return TRUE; |