| 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)
|
|
|