Index: src/service.c |
diff --git a/src/service.c b/src/service.c |
index 27c1fd9c2b567ea656c33611ed4f699bda6f5036..a16a3c037a82dcbca76efa0d4df147f8fc5e2187 100644 |
--- a/src/service.c |
+++ b/src/service.c |
@@ -59,6 +59,7 @@ struct connman_service { |
gint refcount; |
char *identifier; |
char *path; |
+ struct connman_profile *profile; |
enum connman_service_type type; |
enum connman_service_mode mode; |
enum connman_service_security security; |
@@ -96,7 +97,6 @@ struct connman_service { |
char *key_mgmt; |
} eap; |
- const struct connman_storage_ident *profile; |
char *proxy_config; |
/* TODO(sleffler) overlay storage */ |
@@ -396,17 +396,39 @@ static struct connman_service *find_service(const char *path) |
return data.service; |
} |
+struct connman_profile *__connman_service_get_profile( |
+ struct connman_service *service) |
+{ |
+ return service->profile; |
+} |
+ |
+/* |
+ * Set the service's bound profile. |
+ */ |
+void __connman_service_set_profile(struct connman_service *service, |
+ struct connman_profile *profile) |
+{ |
+ _DBG_SERVICE("profile %p -> %p", service->profile, profile); |
+ |
+ service->profile = profile; |
+} |
+ |
+/* |
+ * Handle a profile being pop'd off the stack (e.g. on logout). |
+ * Invalidate and possibly disconnect all services bound to the |
+ * specified profile. Then re-load state from the profile (if |
+ * available). Note this is assumed called AFTER the specified |
+ * profile is pop'd off the stack (so we can explicitly re-load |
+ * state and get any other data present, e.g. in the global profile). |
+ */ |
static void invalidate_profile(gpointer value, gpointer user_data) |
{ |
struct connman_service *service = value; |
- const struct connman_storage_ident *profile = user_data; |
+ const struct connman_profile *profile = user_data; |
if (service->profile == profile) { |
- /* |
- * Invalidate profile-related data and force a re-load |
- * the next time the service is to be used (so it can |
- * come from the active profile). |
- */ |
+ _DBG_SERVICE("service %p", service); |
+ |
service->profile = NULL; |
/* |
@@ -415,19 +437,46 @@ static void invalidate_profile(gpointer value, gpointer user_data) |
* temporarily until we are done with it. |
*/ |
connman_service_ref(service); |
+ |
/* TODO(sleffler) skip wired ethernet, open auth? */ |
+ service->autoconnect = FALSE; |
__connman_service_disconnect(service); |
service_clear_passphrase(service); |
service_clear_eap(service); |
+ |
+ /* re-load profile state */ |
+ __connman_profile_load_service(service); |
+ |
connman_service_unref(service); |
} |
} |
+static void service_profile_pop(struct connman_profile *profile) |
+{ |
+ _DBG_SERVICE("profile %p", profile); |
+ |
+ g_sequence_foreach(service_list, invalidate_profile, (gpointer)profile); |
+ /* NB: no need to kick auto-connect; it will happen due to invalidate */ |
+} |
+ |
+/* |
+ * Handle a profile being push'd on the stack (e.g. on login). |
+ * Try to bind any service objects that are currently unbound |
+ * and kick the autoconnect logic in case we can now login. |
+ */ |
+static void load_profile(gpointer value, gpointer user_data) |
+{ |
+ struct connman_service *service = value; |
-void __connman_service_invalidate_profile(const struct connman_storage_ident *ident) |
+ if (service->profile == NULL) |
+ __connman_profile_load_service(service); |
+} |
+static void service_profile_push(struct connman_profile *profile) |
{ |
- _DBG_SERVICE("ident %s/%s", ident->user, ident->ident); |
+ _DBG_SERVICE("profile %p", profile); |
+ |
+ g_sequence_foreach(service_list, load_profile, NULL); |
- g_sequence_foreach(service_list, invalidate_profile, (gpointer) ident); |
+ __connman_service_auto_connect_any(); |
} |
static const char *identifier(struct connman_service *service) |
@@ -880,6 +929,18 @@ static void proxy_configuration_changed(struct connman_service *service) |
DBUS_TYPE_STRING, &service->proxy_config); |
} |
+static void profile_changed(struct connman_service *service) |
+{ |
+ const char *path; |
+ |
+ CONNMAN_ASSERT(service->profile != NULL); |
+ |
+ path = __connman_profile_get_path(service->profile); |
+ connman_dbus_send_property_changed_variant(service->path, |
+ CONNMAN_SERVICE_INTERFACE, "Profile", |
+ DBUS_TYPE_STRING, &path); |
+} |
+ |
static void get_properties_802_1x(DBusMessageIter *dict, |
struct connman_service *service) |
{ |
@@ -997,6 +1058,12 @@ static DBusMessage *get_properties(DBusConnection *conn, |
connman_dbus_dict_append_variant(&dict, "State", |
DBUS_TYPE_STRING, &str); |
+ if (service->profile != NULL) { |
+ str = __connman_profile_get_path(service->profile); |
+ connman_dbus_dict_append_variant(&dict, "Profile", |
+ DBUS_TYPE_STRING, &str); |
+ } |
+ |
str = error2string(service->error); |
if (str != NULL) |
connman_dbus_dict_append_variant(&dict, "Error", |
@@ -1562,7 +1629,33 @@ static DBusMessage *set_property(DBusConnection *conn, |
type = dbus_message_iter_get_arg_type(&value); |
- if (g_str_equal(name, "WiFi.HiddenSSID") == TRUE) { |
+ if (g_str_equal(name, "Profile") == TRUE) { |
+ const char *path; |
+ struct connman_profile *profile; |
+ |
+ if (type != DBUS_TYPE_STRING) |
+ return __connman_error_invalid_arguments(msg); |
+ |
+ dbus_message_iter_get_basic(&value, &path); |
+ |
+ profile = __connman_profile_lookup_profile(path); |
+ /* TODO(sleffler) support setting a NULL profile? */ |
+ if (profile == NULL) |
+ return __connman_error_not_found(msg); |
+ |
+ if (service->profile != profile) { |
+ if (service->profile != NULL) { |
+ /* remove old entry */ |
+ (void) __connman_profile_delete_entry( |
+ service->profile, service->identifier); |
+ } |
+ service->profile = profile; |
+ |
+ profile_changed(service); |
+ |
+ service_modified(service); |
+ } |
+ } else if (g_str_equal(name, "WiFi.HiddenSSID") == TRUE) { |
connman_bool_t hidden_ssid; |
if (type != DBUS_TYPE_BOOLEAN) |
@@ -1829,7 +1922,6 @@ static void service_modified(struct connman_service *service) |
{ |
g_get_current_time(&service->modified); |
- service->profile = __connman_profile_active_ident(); |
__connman_profile_save_service(service); |
} |
@@ -2678,7 +2770,7 @@ static DBusMessage *move_before(DBusConnection *conn, |
g_sequence_move(src, dst); |
- __connman_profile_changed(FALSE); |
+ __connman_profile_changed(service->profile, FALSE); |
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); |
} |
@@ -2786,7 +2878,7 @@ static void service_free(gpointer user_data) |
service->path = NULL; |
if (path != NULL) { |
- __connman_profile_changed(FALSE); |
+ __connman_profile_changed(service->profile, FALSE); |
g_dbus_unregister_interface(connection, path, |
CONNMAN_SERVICE_INTERFACE); |
@@ -3120,7 +3212,7 @@ int connman_service_set_favorite(struct connman_service *service, |
g_sequence_sort_changed(iter, service_compare, NULL); |
- __connman_profile_changed(FALSE); |
+ __connman_profile_changed(service->profile, FALSE); |
return 0; |
} |
@@ -3236,7 +3328,7 @@ int __connman_service_indicate_state(struct connman_service *service, |
} else if (state != CONNMAN_SERVICE_STATE_ACTIVATION_FAILURE) |
service->error = CONNMAN_SERVICE_ERROR_UNKNOWN; |
- __connman_profile_changed(FALSE); |
+ __connman_profile_changed(service->profile, FALSE); |
if (state == CONNMAN_SERVICE_STATE_DISCONNECT) { |
struct connman_service *act_service = get_active_service(); |
@@ -3934,8 +4026,6 @@ static struct connman_service *__connman_service_get(const char *identifier) |
service->identifier = g_strdup(identifier); |
- service->profile = __connman_profile_active_ident(); |
- |
__connman_profile_load_service(service); |
iter = g_sequence_insert_sorted(service_list, service, |
@@ -3948,16 +4038,12 @@ static struct connman_service *__connman_service_get(const char *identifier) |
static int service_register(struct connman_service *service) |
{ |
- const char *path = __connman_profile_active_path(); |
- |
_DBG_SERVICE("service %p", service); |
if (service->path != NULL) |
return -EALREADY; |
- service->path = g_strdup_printf("%s/%s", path, service->identifier); |
- |
- _DBG_SERVICE("path %s", service->path); |
+ service->path = g_strdup_printf("/%s", service->identifier); |
g_dbus_register_interface(connection, service->path, |
CONNMAN_SERVICE_INTERFACE, |
@@ -3968,7 +4054,7 @@ static int service_register(struct connman_service *service) |
__service_resort(service); |
- __connman_profile_changed(TRUE); |
+ __connman_profile_changed(service->profile, TRUE); |
return 0; |
} |
@@ -4023,7 +4109,7 @@ __connman_service_create_from_device(struct connman_device *device) |
return NULL; |
if (service->path != NULL) { |
- __connman_profile_changed(TRUE); |
+ __connman_profile_changed(service->profile, TRUE); |
return service; |
} |
@@ -4037,7 +4123,7 @@ __connman_service_create_from_device(struct connman_device *device) |
service_register(service); |
- __connman_profile_changed(TRUE); |
+ __connman_profile_changed(service->profile, TRUE); |
if (service->favorite == TRUE) |
connman_service_auto_connect(service); |
@@ -4409,7 +4495,7 @@ __connman_service_create_from_network(struct connman_network *network) |
if (service->path != NULL) { |
update_from_network(service, network, FALSE); |
- __connman_profile_changed(TRUE); |
+ __connman_profile_changed(service->profile, TRUE); |
return service; |
} |
@@ -4454,7 +4540,7 @@ __connman_service_create_from_network(struct connman_network *network) |
service_register(service); |
- __connman_profile_changed(TRUE); |
+ __connman_profile_changed(service->profile, TRUE); |
if (service->favorite == TRUE) |
connman_service_auto_connect(service); |
@@ -5117,6 +5203,8 @@ static struct connman_notifier service_notifier = { |
.service_state_changed = notify_state_changed, |
.system_suspend = service_system_suspend, |
.system_resume = service_system_resume, |
+ .profile_push = service_profile_push, |
+ .profile_pop = service_profile_pop, |
}; |
int __connman_service_init(const char *option_order) |