summaryrefslogtreecommitdiff
path: root/plugins/vpn.c
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-11-12 14:07:43 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-11-23 12:58:52 +0200
commit9c1129aa6a665f7663fcbf73b20994c8592e46d5 (patch)
tree78a7d3dfb3f067841155be11bce6c6f65dbbe50a /plugins/vpn.c
parentae693881d0d2bac1d9edea534918b6cc238b06ce (diff)
downloadconnman-9c1129aa6a665f7663fcbf73b20994c8592e46d5.tar.gz
connman-9c1129aa6a665f7663fcbf73b20994c8592e46d5.tar.bz2
connman-9c1129aa6a665f7663fcbf73b20994c8592e46d5.zip
provider: Add callback when creating vpn provider
Because the vpnd Create() in manager API only creates and does not connect the vpn, we must do the connect part after the vpn is created. This requires a callback which is called when the connection is established. Eventually this patch becomes obsolete because the CreateProvider() connman API is deprecated.
Diffstat (limited to 'plugins/vpn.c')
-rw-r--r--plugins/vpn.c168
1 files changed, 126 insertions, 42 deletions
diff --git a/plugins/vpn.c b/plugins/vpn.c
index c0cde951..b29dcc04 100644
--- a/plugins/vpn.c
+++ b/plugins/vpn.c
@@ -60,6 +60,12 @@ struct vpn_route {
char *gateway;
};
+struct config_create_data {
+ connection_ready_cb callback;
+ DBusMessage *message;
+ char *path;
+};
+
struct connection_data {
char *path;
char *ident;
@@ -67,6 +73,7 @@ struct connection_data {
int index;
DBusPendingCall *call;
connman_bool_t connect_pending;
+ struct config_create_data *cb_data;
char *state;
char *type;
@@ -222,26 +229,58 @@ static void resolv_host_addr(struct connection_data *data)
resolv_result, data);
}
+static void free_config_cb_data(struct config_create_data *cb_data)
+{
+ if (cb_data == NULL)
+ return;
+
+ g_free(cb_data->path);
+ cb_data->path = NULL;
+
+ if (cb_data->message != NULL) {
+ dbus_message_unref(cb_data->message);
+ cb_data->message = NULL;
+ }
+
+ cb_data->callback = NULL;
+
+ g_free(cb_data);
+}
+
static void set_provider_state(struct connection_data *data)
{
- if (g_str_equal(data->state, "ready") == TRUE)
- connman_provider_set_state(data->provider,
- CONNMAN_PROVIDER_STATE_READY);
- else if (g_str_equal(data->state, "configuration") == TRUE)
- connman_provider_set_state(data->provider,
- CONNMAN_PROVIDER_STATE_CONNECT);
- else if (g_str_equal(data->state, "idle") == TRUE)
- connman_provider_set_state(data->provider,
- CONNMAN_PROVIDER_STATE_IDLE);
- else if (g_str_equal(data->state, "disconnect") == TRUE)
- connman_provider_set_state(data->provider,
- CONNMAN_PROVIDER_STATE_DISCONNECT);
- else if (g_str_equal(data->state, "failure") == TRUE)
- connman_provider_set_state(data->provider,
- CONNMAN_PROVIDER_STATE_FAILURE);
- else
- connman_provider_set_state(data->provider,
- CONNMAN_PROVIDER_STATE_UNKNOWN);
+ enum connman_provider_state state = CONNMAN_PROVIDER_STATE_UNKNOWN;
+ int err = 0;
+
+ if (g_str_equal(data->state, "ready") == TRUE) {
+ state = CONNMAN_PROVIDER_STATE_READY;
+ goto set;
+ } else if (g_str_equal(data->state, "configuration") == TRUE) {
+ state = CONNMAN_PROVIDER_STATE_CONNECT;
+ } else if (g_str_equal(data->state, "idle") == TRUE) {
+ state = CONNMAN_PROVIDER_STATE_IDLE;
+ } else if (g_str_equal(data->state, "disconnect") == TRUE) {
+ err = ECONNREFUSED;
+ state = CONNMAN_PROVIDER_STATE_DISCONNECT;
+ goto set;
+ } else if (g_str_equal(data->state, "failure") == TRUE) {
+ err = ECONNREFUSED;
+ state = CONNMAN_PROVIDER_STATE_FAILURE;
+ goto set;
+ }
+
+ connman_provider_set_state(data->provider, state);
+ return;
+
+set:
+ if (data->cb_data != NULL)
+ data->cb_data->callback(data->cb_data->message,
+ err, data->ident);
+
+ connman_provider_set_state(data->provider, state);
+
+ free_config_cb_data(data->cb_data);
+ data->cb_data = NULL;
}
static int create_provider(struct connection_data *data, void *user_data)
@@ -415,11 +454,13 @@ static void connect_reply(DBusPendingCall *call, void *user_data)
{
DBusMessage *reply;
DBusError error;
+ struct connection_data *data;
+ struct config_create_data *cb_data = user_data;
if (dbus_pending_call_get_completed(call) == FALSE)
return;
- DBG("user_data %p", user_data);
+ DBG("user_data %p path %s", user_data, cb_data ? cb_data->path : NULL);
reply = dbus_pending_call_steal_reply(call);
@@ -431,6 +472,13 @@ static void connect_reply(DBusPendingCall *call, void *user_data)
connman_error("Connect reply: %s (%s)", error.message,
error.name);
dbus_error_free(&error);
+
+ if (cb_data != NULL) {
+ cb_data->callback(cb_data->message,
+ ECONNREFUSED, NULL);
+ free_config_cb_data(cb_data);
+ }
+ data->cb_data = NULL;
goto done;
}
dbus_error_free(&error);
@@ -452,8 +500,9 @@ static int connect_provider(struct connection_data *data, void *user_data)
{
DBusPendingCall *call;
DBusMessage *message;
+ struct config_create_data *cb_data = user_data;
- DBG("data %p", data);
+ DBG("data %p user %p path %s", data, cb_data, data->path);
message = dbus_message_new_method_call(VPN_SERVICE, data->path,
VPN_CONNECTION_INTERFACE,
@@ -474,7 +523,12 @@ static int connect_provider(struct connection_data *data, void *user_data)
return -EINVAL;
}
- dbus_pending_call_set_notify(call, connect_reply, NULL, NULL);
+ if (cb_data != NULL) {
+ g_free(cb_data->path);
+ cb_data->path = g_strdup(data->path);
+ }
+
+ dbus_pending_call_set_notify(call, connect_reply, cb_data, NULL);
dbus_message_unref(message);
@@ -487,6 +541,7 @@ static void add_connection(const char *path, DBusMessageIter *properties,
struct connection_data *data;
int err;
char *ident = get_ident(path);
+ connman_bool_t found = FALSE;
data = g_hash_table_lookup(vpn_connections, ident);
if (data != NULL) {
@@ -497,6 +552,8 @@ static void add_connection(const char *path, DBusMessageIter *properties,
*/
if (data->connect_pending == FALSE)
return;
+
+ found = TRUE;
} else {
data = create_connection_data(path);
if (data == NULL)
@@ -555,7 +612,9 @@ static void add_connection(const char *path, DBusMessageIter *properties,
dbus_message_iter_next(properties);
}
- g_hash_table_insert(vpn_connections, g_strdup(data->ident), data);
+ if (found == FALSE)
+ g_hash_table_insert(vpn_connections, g_strdup(data->ident),
+ data);
err = create_provider(data, user_data);
if (err < 0)
@@ -563,10 +622,8 @@ 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;
- }
+ if (data->connect_pending == TRUE)
+ connect_provider(data, data->cb_data);
return;
@@ -765,7 +822,6 @@ static int provider_connect(struct connman_provider *provider)
return -EINVAL;
return connect_provider(data, NULL);
-
}
static void disconnect_reply(DBusPendingCall *call, void *user_data)
@@ -776,7 +832,7 @@ static void disconnect_reply(DBusPendingCall *call, void *user_data)
if (dbus_pending_call_get_completed(call) == FALSE)
return;
- DBG("");
+ DBG("user %p", user_data);
reply = dbus_pending_call_steal_reply(call);
@@ -862,11 +918,12 @@ static void configuration_create_reply(DBusPendingCall *call, void *user_data)
const char *path;
char *ident;
struct connection_data *data;
+ struct config_create_data *cb_data = user_data;
if (dbus_pending_call_get_completed(call) == FALSE)
return;
- DBG("user %p", user_data);
+ DBG("user %p", cb_data);
reply = dbus_pending_call_steal_reply(call);
@@ -898,17 +955,25 @@ static void configuration_create_reply(DBusPendingCall *call, void *user_data)
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.
+ * Someone removed the data. We cannot really continue.
*/
- data = create_connection_data(path);
+ DBG("Pending data not found for %s, cannot continue!", ident);
+ } else {
+ data->call = NULL;
data->connect_pending = TRUE;
- g_hash_table_insert(vpn_connections, g_strdup(ident), data);
+ if (data->cb_data == NULL)
+ data->cb_data = cb_data;
+ else
+ DBG("Connection callback data already in use!");
- } else {
- connect_provider(data, NULL);
+ /*
+ * Connection is created in add_connections() after
+ * we have received the ConnectionAdded signal.
+ */
+
+ DBG("cb %p msg %p", data->cb_data,
+ data->cb_data ? data->cb_data->message : NULL);
}
done:
@@ -1071,9 +1136,9 @@ static void append_routes(DBusMessageIter *iter, void *user_data)
}
}
-static int create_configuration(DBusMessage *msg)
+static int create_configuration(DBusMessage *msg, connection_ready_cb callback)
{
- DBusMessage *new_msg;
+ DBusMessage *new_msg = NULL;
DBusPendingCall *call;
DBusMessageIter iter, array, new_iter, new_dict;
const char *type = NULL, *name = NULL;
@@ -1082,6 +1147,7 @@ static int create_configuration(DBusMessage *msg)
int err = 0;
dbus_bool_t result;
struct connection_data *data;
+ struct config_create_data *user_data = NULL;
GSList *networks = NULL;
/*
@@ -1174,7 +1240,11 @@ static int create_configuration(DBusMessage *msg)
goto done;
}
} else {
- data = create_connection_data(ident);
+ char *path = g_strdup_printf("%s/connection/%s", VPN_PATH,
+ ident);
+ data = create_connection_data(path);
+ g_free(path);
+
if (data == NULL) {
err = -ENOMEM;
goto done;
@@ -1202,17 +1272,31 @@ static int create_configuration(DBusMessage *msg)
goto done;
}
+ if (data->cb_data == NULL) {
+ user_data = g_try_new(struct config_create_data, 1);
+ if (user_data != NULL) {
+ user_data->callback = callback;
+ user_data->message = dbus_message_ref(msg);
+ user_data->path = NULL;
+
+ DBG("cb %p msg %p", user_data, msg);
+ }
+ } else {
+ DBG("Configuration callback data already pending, "
+ "discarding new data.");
+ }
+
dbus_pending_call_set_notify(call, configuration_create_reply,
- NULL, NULL);
+ user_data, NULL);
data->call = call;
done:
- dbus_message_unref(new_msg);
+ if (new_msg != NULL)
+ dbus_message_unref(new_msg);
if (networks != NULL)
g_slist_free_full(networks, destroy_route);
-
g_free(me);
return err;
}