OLD | NEW |
1 /* | 1 /* |
2 * | 2 * |
3 * Connection Manager | 3 * Connection Manager |
4 * | 4 * |
5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved. | 5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved. |
6 * | 6 * |
7 * This program is free software; you can redistribute it and/or modify | 7 * This program is free software; you can redistribute it and/or modify |
8 * it under the terms of the GNU General Public License version 2 as | 8 * it under the terms of the GNU General Public License version 2 as |
9 * published by the Free Software Foundation. | 9 * published by the Free Software Foundation. |
10 * | 10 * |
(...skipping 21 matching lines...) Expand all Loading... |
32 | 32 |
33 #include "connman.h" | 33 #include "connman.h" |
34 | 34 |
35 #define PROFILE_DEFAULT_IDENT "default" | 35 #define PROFILE_DEFAULT_IDENT "default" |
36 #define PROFILE_MAX 3 /* 2 is probably sufficient */ | 36 #define PROFILE_MAX 3 /* 2 is probably sufficient */ |
37 | 37 |
38 #define _DBG_PROFILE(fmt, arg...) DBG(DBG_PROFILE, fmt, ## arg) | 38 #define _DBG_PROFILE(fmt, arg...) DBG(DBG_PROFILE, fmt, ## arg) |
39 | 39 |
40 struct connman_profile { | 40 struct connman_profile { |
41 struct connman_storage_ident ident; | 41 struct connman_storage_ident ident; |
| 42 guint changed_timeout; |
42 char *path; | 43 char *path; |
43 char *name; | 44 char *name; |
44 connman_bool_t offlinemode; | 45 connman_bool_t offlinemode; |
45 }; | 46 }; |
46 | 47 |
47 static GHashTable *profile_hash = NULL; | 48 static GHashTable *profile_hash = NULL; |
48 | 49 |
49 static struct connman_profile *profile_stack[PROFILE_MAX]; | 50 static struct connman_profile *profile_stack[PROFILE_MAX]; |
50 static int cur_profile = -1; | 51 static int cur_profile = -1; |
51 | 52 |
52 static struct connman_storage_ident default_ident = { | 53 static struct connman_storage_ident default_ident = { |
53 .ident = PROFILE_DEFAULT_IDENT | 54 .ident = PROFILE_DEFAULT_IDENT |
54 }; | 55 }; |
55 static struct connman_profile *default_profile = NULL; | 56 static struct connman_profile *default_profile = NULL; |
56 | 57 |
| 58 static guint changed_timeout = 0; /* for NULL profile handling */ |
| 59 |
57 static DBusConnection *connection = NULL; | 60 static DBusConnection *connection = NULL; |
58 | 61 |
| 62 /* |
| 63 * Loading/Saving objects. |
| 64 * |
| 65 * Service objects go to the profile they are pinned to (typically |
| 66 * the active profile at the time they were created but this can be |
| 67 * changed, e.g. from private -> global). |
| 68 * |
| 69 * Device and ipconfig objects go in the global profile (if any). |
| 70 * This ensures that enable/disable state is maintained between |
| 71 * users (and reboots); or possibly discarded (e.g. for testing). |
| 72 * |
| 73 * Likewise global state like offline mode is stored in the global |
| 74 * profile (see above). |
| 75 */ |
| 76 |
| 77 /* |
| 78 * Return the active profile; it's on the top of the stack. |
| 79 */ |
| 80 static inline struct connman_profile *active_profile(void) |
| 81 { |
| 82 return cur_profile >= 0 ? profile_stack[cur_profile] : NULL; |
| 83 } |
| 84 |
| 85 /* |
| 86 * Return the global profile; it's top-most non-user profile. |
| 87 */ |
| 88 static struct connman_profile *global_profile(void) |
| 89 { |
| 90 /* TODO(sleffler) cheat for now */ |
| 91 return default_profile != NULL ? default_profile : NULL; |
| 92 } |
| 93 |
59 static int ident_equal(const struct connman_storage_ident *a, | 94 static int ident_equal(const struct connman_storage_ident *a, |
60 const struct connman_storage_ident *b) | 95 const struct connman_storage_ident *b) |
61 { | 96 { |
62 return (g_strcmp0(a->user, b->user) == 0 && | 97 return (g_strcmp0(a->user, b->user) == 0 && |
63 g_strcmp0(a->ident, b->ident) == 0); | 98 g_strcmp0(a->ident, b->ident) == 0); |
64 } | 99 } |
65 | 100 |
66 static void append_path(gpointer key, gpointer value, gpointer user_data) | 101 static void append_path(gpointer key, gpointer value, gpointer user_data) |
67 { | 102 { |
68 struct connman_profile *profile = value; | 103 struct connman_profile *profile = value; |
(...skipping 10 matching lines...) Expand all Loading... |
79 | 114 |
80 static void profiles_changed(void) | 115 static void profiles_changed(void) |
81 { | 116 { |
82 connman_dbus_send_property_changed_array(CONNMAN_MANAGER_PATH, | 117 connman_dbus_send_property_changed_array(CONNMAN_MANAGER_PATH, |
83 CONNMAN_MANAGER_INTERFACE, "Profiles", | 118 CONNMAN_MANAGER_INTERFACE, "Profiles", |
84 DBUS_TYPE_OBJECT_PATH, __connman_profile_list, NULL); | 119 DBUS_TYPE_OBJECT_PATH, __connman_profile_list, NULL); |
85 } | 120 } |
86 | 121 |
87 connman_bool_t __connman_profile_get_offlinemode(void) | 122 connman_bool_t __connman_profile_get_offlinemode(void) |
88 { | 123 { |
89 » return (default_profile == NULL) ? FALSE : default_profile->offlinemode; | 124 » struct connman_profile *profile = global_profile(); |
| 125 » return (profile == NULL) ? FALSE : profile->offlinemode; |
90 } | 126 } |
91 | 127 |
92 int __connman_profile_set_offlinemode(connman_bool_t offlinemode) | 128 int __connman_profile_set_offlinemode(connman_bool_t offlinemode) |
93 { | 129 { |
94 » _DBG_PROFILE("offlinemode %d", offlinemode); | 130 » struct connman_profile *profile = global_profile(); |
| 131 » int ret; |
95 | 132 |
96 » /* TODO(sleffler) disallow if no default profile? */ | 133 » _DBG_PROFILE("offlinemode %d profile %p", offlinemode, profile); |
97 » if (default_profile != NULL) { | 134 |
| 135 » /* NB: always succeeds (ATM) */ |
| 136 » ret = __connman_device_set_offlinemode(offlinemode); |
| 137 » if (ret != 0) |
| 138 » » return ret; |
| 139 |
| 140 » /* TODO(sleffler) sallow even if no global profile? */ |
| 141 » if (profile != NULL) { |
98 /* | 142 /* |
99 * OfflineMode is only saved to the default profile; | 143 * OfflineMode is only saved to the default profile; |
100 * this ensures it is preserved across user changes. | 144 * this ensures it is preserved across user changes. |
101 */ | 145 */ |
102 » » if (default_profile->offlinemode == offlinemode) | 146 » » if (profile->offlinemode == offlinemode) |
103 return -EALREADY; | 147 return -EALREADY; |
104 | 148 |
105 » » default_profile->offlinemode = offlinemode; | 149 » » profile->offlinemode = offlinemode; |
106 | 150 |
107 connman_dbus_send_property_changed_variant( | 151 connman_dbus_send_property_changed_variant( |
108 » » default_profile->path, | 152 » » profile->path, |
109 CONNMAN_PROFILE_INTERFACE, "OfflineMode", | 153 CONNMAN_PROFILE_INTERFACE, "OfflineMode", |
110 DBUS_TYPE_BOOLEAN, &offlinemode); | 154 DBUS_TYPE_BOOLEAN, &offlinemode); |
| 155 |
| 156 __connman_storage_save_profile(profile); |
111 } | 157 } |
112 » return __connman_device_set_offlinemode(offlinemode); | 158 » return 0; |
113 } | 159 } |
114 | 160 |
115 /* | |
116 * Return the active profile; it's on the top of the stack. | |
117 */ | |
118 static inline struct connman_profile *active_profile(void) | |
119 { | |
120 return cur_profile >= 0 ? profile_stack[cur_profile] : NULL; | |
121 } | |
122 | |
123 /* | |
124 * Load/Save objects. When loading we walk the stack of profiles | |
125 * until we find a successful load. Saving always happens to the | |
126 * top-most/active profile. | |
127 */ | |
128 | |
129 static inline int load_continue(int err) | 161 static inline int load_continue(int err) |
130 { | 162 { |
131 » /* NB: ENXIO for no file, ESRCH for no group/key */ | 163 » /* NB: ENXIO for no file, ESRCH for no entry */ |
132 return (err == -ENXIO || err == -ESRCH); | 164 return (err == -ENXIO || err == -ESRCH); |
133 } | 165 } |
134 | 166 |
135 int __connman_profile_load_service(struct connman_service *service) | 167 int __connman_profile_load_service(struct connman_service *service) |
136 { | 168 { |
137 » int i, err; | 169 » struct connman_profile *profile = |
| 170 » __connman_service_get_profile(service); |
| 171 » int err, i; |
138 | 172 |
139 » _DBG_PROFILE("service %p", service); | 173 » _DBG_PROFILE("service %p profile %p", service, profile); |
140 | 174 |
| 175 if (profile != NULL) |
| 176 return __connman_storage_load_service(service, &profile->ident); |
| 177 /* |
| 178 * Not bound to a profile yet, search the stack for an |
| 179 * entry and if found bind the profile to the service. |
| 180 */ |
141 err = 0; | 181 err = 0; |
142 for (i = cur_profile; i >= 0; i--) { | 182 for (i = cur_profile; i >= 0; i--) { |
143 » » const struct connman_profile *profile = profile_stack[i]; | 183 » » profile = profile_stack[i]; |
144 | |
145 err = __connman_storage_load_service(service, &profile->ident); | 184 err = __connman_storage_load_service(service, &profile->ident); |
| 185 if (err == 0) { |
| 186 _DBG_PROFILE("bind to profile %p", profile); |
| 187 __connman_service_set_profile(service, profile); |
| 188 return 0; |
| 189 } |
146 if (!load_continue(err)) | 190 if (!load_continue(err)) |
147 break; | 191 break; |
148 } | 192 } |
149 return err; | 193 return err; |
150 } | 194 } |
151 | 195 |
152 int __connman_profile_save_service(struct connman_service *service) | 196 int __connman_profile_save_service(struct connman_service *service) |
153 { | 197 { |
154 » struct connman_profile *profile = active_profile(); | 198 » struct connman_profile *profile = |
| 199 » __connman_service_get_profile(service); |
155 | 200 |
156 _DBG_PROFILE("service %p profile %p", service, profile); | 201 _DBG_PROFILE("service %p profile %p", service, profile); |
157 | 202 |
| 203 if (profile == NULL) { |
| 204 /* not bound yet, bind to the active profile */ |
| 205 profile = active_profile(); |
| 206 _DBG_PROFILE("bind to profile %p", profile); |
| 207 __connman_service_set_profile(service, profile); |
| 208 } |
158 return (profile == NULL) ? 0 : | 209 return (profile == NULL) ? 0 : |
159 __connman_storage_save_service(service, &profile->ident); | 210 __connman_storage_save_service(service, &profile->ident); |
160 } | 211 } |
161 | 212 |
162 int __connman_profile_load_device(struct connman_device *device) | 213 int __connman_profile_load_device(struct connman_device *device) |
163 { | 214 { |
164 » int i, err; | 215 » struct connman_profile *profile = global_profile(); |
165 | 216 |
166 » _DBG_PROFILE("device %p", device); | 217 » _DBG_PROFILE("device %p profile %p", device, profile); |
167 | 218 |
168 » err = 0; | 219 » return (profile == NULL) ? 0 : |
169 » for (i = cur_profile; i >= 0; i--) { | 220 » __connman_storage_load_device(device, &profile->ident); |
170 » » const struct connman_profile *profile = profile_stack[i]; | |
171 | |
172 » » err = __connman_storage_load_device(device, &profile->ident); | |
173 » » if (!load_continue(err)) | |
174 » » » break; | |
175 » } | |
176 » return err; | |
177 } | 221 } |
178 | 222 |
179 int __connman_profile_save_device(struct connman_device *device) | 223 int __connman_profile_save_device(struct connman_device *device) |
180 { | 224 { |
181 » struct connman_profile *profile = active_profile(); | 225 » struct connman_profile *profile = global_profile(); |
182 | 226 |
183 _DBG_PROFILE("device %p profile %p", device, profile); | 227 _DBG_PROFILE("device %p profile %p", device, profile); |
184 | 228 |
185 return (profile == NULL) ? 0: | 229 return (profile == NULL) ? 0: |
186 __connman_storage_save_device(device, &profile->ident); | 230 __connman_storage_save_device(device, &profile->ident); |
187 } | 231 } |
188 | 232 |
189 int __connman_profile_load_ipconfig(struct connman_ipconfig *ipconfig) | 233 int __connman_profile_load_ipconfig(struct connman_ipconfig *ipconfig) |
190 { | 234 { |
191 » int i, err; | 235 » struct connman_profile *profile = global_profile(); |
192 | 236 |
193 » _DBG_PROFILE("ipconfig %p", ipconfig); | 237 » _DBG_PROFILE("ipconfig %p profile %p", ipconfig, profile); |
194 | 238 |
195 » err = 0; | 239 » return (profile == NULL) ? 0: |
196 » for (i = cur_profile; i >= 0; i--) { | 240 » __connman_storage_load_ipconfig(ipconfig, &profile->ident); |
197 » » const struct connman_profile *profile = profile_stack[i]; | |
198 | |
199 » » err = __connman_storage_load_ipconfig(ipconfig, | |
200 » » &profile->ident); | |
201 » » if (!load_continue(err)) | |
202 » » » break; | |
203 » } | |
204 » return err; | |
205 } | 241 } |
206 | 242 |
207 int __connman_profile_save_ipconfig(const struct connman_ipconfig *ipconfig) | 243 int __connman_profile_save_ipconfig(const struct connman_ipconfig *ipconfig) |
208 { | 244 { |
209 » struct connman_profile *profile = active_profile(); | 245 » struct connman_profile *profile = global_profile(); |
210 | 246 |
211 _DBG_PROFILE("ipconfig %p profile %p", ipconfig, profile); | 247 _DBG_PROFILE("ipconfig %p profile %p", ipconfig, profile); |
212 | 248 |
213 return (profile == NULL) ? 0 : | 249 return (profile == NULL) ? 0 : |
214 __connman_storage_save_ipconfig(ipconfig, &profile->ident); | 250 __connman_storage_save_ipconfig(ipconfig, &profile->ident); |
215 } | 251 } |
216 | 252 |
217 int __connman_profile_append_hidden_ssids(GSList **hidden_ssids, | 253 int __connman_profile_append_hidden_ssids(GSList **hidden_ssids, |
218 void (*append_hidden_ssids)(GKeyFile *keyfile, GSList **hidden_ssids)) | 254 void (*append_hidden_ssids)(GKeyFile *keyfile, GSList **hidden_ssids)) |
219 { | 255 { |
220 int i; | 256 int i; |
221 | 257 |
222 _DBG_PROFILE(""); | 258 _DBG_PROFILE(""); |
223 | 259 |
224 for (i = cur_profile; i >= 0; i--) { | 260 for (i = cur_profile; i >= 0; i--) { |
225 const struct connman_profile *profile = profile_stack[i]; | 261 const struct connman_profile *profile = profile_stack[i]; |
226 GKeyFile *keyfile; | 262 GKeyFile *keyfile; |
227 | 263 |
228 keyfile = __connman_storage_open(&profile->ident); | 264 keyfile = __connman_storage_open(&profile->ident); |
229 if (keyfile != NULL) { | 265 if (keyfile != NULL) { |
230 append_hidden_ssids(keyfile, hidden_ssids); | 266 append_hidden_ssids(keyfile, hidden_ssids); |
231 __connman_storage_close(&profile->ident, keyfile, | 267 __connman_storage_close(&profile->ident, keyfile, |
232 FALSE); | 268 FALSE); |
233 } | 269 } |
234 } | 270 } |
235 return 0; | 271 return 0; |
236 } | 272 } |
237 | 273 |
238 /* | 274 /* |
239 * Save the default profile if registered. | 275 * Return the object path for the specified profile. |
240 */ | 276 */ |
241 int __connman_profile_save_default(void) | 277 const char *__connman_profile_get_path(const struct connman_profile *profile) |
242 { | 278 { |
243 » if (default_profile != NULL) | 279 » return profile != NULL ? profile->path : NULL; |
244 » » __connman_storage_save_profile(default_profile); | |
245 » return 0; | |
246 } | 280 } |
247 | 281 |
248 /* | 282 /* |
249 * Save the active profile (if any). | 283 * Return the profile given an object path. |
250 */ | 284 */ |
251 int __connman_profile_save_active(void) | 285 struct connman_profile *__connman_profile_lookup_profile(const char *path) |
252 { | 286 { |
253 » struct connman_profile *profile = active_profile(); | 287 » return g_hash_table_lookup(profile_hash, path); |
254 » return (profile == NULL) ? -EINVAL : | |
255 » __connman_storage_save_profile(profile); | |
256 } | 288 } |
257 | 289 |
258 /* | 290 /* |
259 * Return the identifier for the active profile or NULL | 291 * Return the active profile or NULL |
260 * if there is none. | |
261 */ | 292 */ |
| 293 struct connman_profile *__connman_profile_active_profile(void) |
| 294 { |
| 295 return active_profile(); |
| 296 } |
| 297 |
262 const struct connman_storage_ident *__connman_profile_active_ident(void) | 298 const struct connman_storage_ident *__connman_profile_active_ident(void) |
263 { | 299 { |
264 struct connman_profile *profile = active_profile(); | 300 struct connman_profile *profile = active_profile(); |
265 return profile != NULL ? &profile->ident : NULL; | 301 return profile != NULL ? &profile->ident : NULL; |
266 } | 302 } |
267 | 303 |
268 /* | 304 /* |
269 * Return the object path for the active profile or NULL | 305 * Return the object path for the active profile or NULL |
270 * if there is none. | 306 * if there is none. |
271 */ | 307 */ |
272 const char *__connman_profile_active_path(void) | 308 const char *__connman_profile_active_path(void) |
273 { | 309 { |
274 struct connman_profile *profile = active_profile(); | 310 struct connman_profile *profile = active_profile(); |
275 return profile != NULL ? profile->path : NULL; | 311 return profile != NULL ? profile->path : NULL; |
276 } | 312 } |
277 | 313 |
278 static guint changed_timeout = 0; | 314 /* |
| 315 * Delete an entry in the specified profile. |
| 316 */ |
| 317 int __connman_profile_delete_entry(struct connman_profile *profile, |
| 318 const char *group) |
| 319 { |
| 320 » GKeyFile *keyfile; |
| 321 » gboolean status; |
279 | 322 |
280 static void clear_timeout(void) | 323 » _DBG_PROFILE("profile %p group %s", profile, group); |
| 324 |
| 325 » keyfile = __connman_storage_open(&profile->ident); |
| 326 » if (keyfile == NULL) { |
| 327 » » _DBG_PROFILE("cannot open key file"); |
| 328 » » return -EINVAL; |
| 329 » } |
| 330 |
| 331 » status = g_key_file_remove_group(keyfile, group, NULL); |
| 332 » __connman_storage_close(&profile->ident, keyfile, status); |
| 333 |
| 334 » if (status == FALSE) { |
| 335 » » _DBG_PROFILE("cannot remove %s", group); |
| 336 » » return -ENXIO; |
| 337 » } |
| 338 » return 0; |
| 339 } |
| 340 |
| 341 static void __clear_timeout(guint *pchanged_timeout) |
281 { | 342 { |
282 » if (changed_timeout > 0) { | 343 » if (*pchanged_timeout > 0) { |
283 » » g_source_remove(changed_timeout); | 344 » » g_source_remove(*pchanged_timeout); |
284 » » changed_timeout = 0; | 345 » » *pchanged_timeout = 0; |
285 } | 346 } |
286 } | 347 } |
287 | 348 |
| 349 static void clear_timeout(struct connman_profile *profile) |
| 350 { |
| 351 if (profile != NULL) |
| 352 __clear_timeout(&profile->changed_timeout); |
| 353 else |
| 354 __clear_timeout(&changed_timeout); |
| 355 } |
| 356 |
288 static void append_services(DBusMessageIter *iter, void *arg) | 357 static void append_services(DBusMessageIter *iter, void *arg) |
289 { | 358 { |
290 __connman_service_list(iter, arg); | 359 __connman_service_list(iter, arg); |
291 } | 360 } |
292 static gboolean services_changed(gpointer user_data) | 361 static gboolean services_changed(gpointer user_data) |
293 { | 362 { |
294 » struct connman_profile *profile = active_profile(); | 363 » struct connman_profile *profile = user_data; |
295 | |
296 » changed_timeout = 0; | |
297 | 364 |
298 if (profile != NULL) { | 365 if (profile != NULL) { |
| 366 profile->changed_timeout = 0; |
| 367 |
299 connman_dbus_send_property_changed_array(profile->path, | 368 connman_dbus_send_property_changed_array(profile->path, |
300 CONNMAN_PROFILE_INTERFACE, "Services", | 369 CONNMAN_PROFILE_INTERFACE, "Services", |
301 DBUS_TYPE_OBJECT_PATH, append_services, NULL); | 370 DBUS_TYPE_OBJECT_PATH, append_services, NULL); |
302 » } | 371 » } else |
| 372 » » changed_timeout = 0; |
303 | 373 |
304 connman_dbus_send_property_changed_array(CONNMAN_MANAGER_PATH, | 374 connman_dbus_send_property_changed_array(CONNMAN_MANAGER_PATH, |
305 CONNMAN_MANAGER_INTERFACE, "Services", | 375 CONNMAN_MANAGER_INTERFACE, "Services", |
306 DBUS_TYPE_OBJECT_PATH, append_services, NULL); | 376 DBUS_TYPE_OBJECT_PATH, append_services, NULL); |
307 return FALSE; | 377 return FALSE; |
308 } | 378 } |
309 | 379 |
310 /* | 380 /* |
311 * Handle changes to the profile. Generate PropertyChanged signals | 381 * Handle changes to a profile. Generate PropertyChanged signals |
312 * on Manager.Services and Profile.Services for the currently active | 382 * on Manager.Services and Profile.Services for the currently active |
313 * profile. To minimize overhead requests may be coalesced using a | 383 * profile. To minimize overhead requests may be coalesced using a |
314 * 1 second delay on the signals. | 384 * 1 second delay on the signals. |
315 */ | 385 */ |
316 void __connman_profile_changed(gboolean delayed) | 386 void __connman_profile_changed(struct connman_profile *profile, |
| 387 gboolean delayed) |
317 { | 388 { |
318 » _DBG_PROFILE("delayed %d changed_timeout %d", delayed, changed_timeout); | 389 » _DBG_PROFILE("profile %p delayed %d changed_timeout %d", |
| 390 » profile, delayed, profile != NULL ? |
| 391 » profile->changed_timeout : changed_timeout); |
319 | 392 |
320 » clear_timeout(); | 393 » clear_timeout(profile); |
321 | 394 |
322 if (delayed == TRUE) { | 395 if (delayed == TRUE) { |
323 » » changed_timeout = g_timeout_add_seconds(1, services_changed, | 396 » » guint timeout = g_timeout_add_seconds(1, |
324 » » NULL); | 397 » » services_changed, profile); |
| 398 » » if (profile != NULL) |
| 399 » » » profile->changed_timeout = timeout; |
| 400 » » else |
| 401 » » » changed_timeout = timeout; |
325 } else | 402 } else |
326 » » services_changed(NULL); | 403 » » services_changed(profile); |
327 } | 404 } |
328 | 405 |
329 int __connman_profile_add_device(struct connman_device *device) | 406 int __connman_profile_add_device(struct connman_device *device) |
330 { | 407 { |
331 struct connman_service *service; | 408 struct connman_service *service; |
332 | 409 |
333 _DBG_PROFILE("device %p", device); | 410 _DBG_PROFILE("device %p", device); |
334 | 411 |
335 service = __connman_service_create_from_device(device); | 412 service = __connman_service_create_from_device(device); |
336 if (service == NULL) | 413 if (service == NULL) |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 | 531 |
455 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, | 532 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, |
456 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING | 533 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING |
457 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING | 534 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING |
458 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); | 535 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); |
459 | 536 |
460 if (profile->name != NULL) | 537 if (profile->name != NULL) |
461 connman_dbus_dict_append_variant(&dict, "Name", | 538 connman_dbus_dict_append_variant(&dict, "Name", |
462 DBUS_TYPE_STRING, &profile->name); | 539 DBUS_TYPE_STRING, &profile->name); |
463 | 540 |
464 » if (profile == default_profile) | 541 » if (profile == global_profile()) |
465 connman_dbus_dict_append_variant(&dict, "OfflineMode", | 542 connman_dbus_dict_append_variant(&dict, "OfflineMode", |
466 DBUS_TYPE_BOOLEAN, &profile->offlinemode); | 543 DBUS_TYPE_BOOLEAN, &profile->offlinemode); |
467 | 544 |
468 if (profile == active_profile()) | 545 if (profile == active_profile()) |
469 connman_dbus_dict_append_variant_array(&dict, "Services", | 546 connman_dbus_dict_append_variant_array(&dict, "Services", |
470 DBUS_TYPE_OBJECT_PATH, __connman_service_list, NULL); | 547 DBUS_TYPE_OBJECT_PATH, __connman_service_list, NULL); |
471 | 548 |
472 connman_dbus_dict_append_variant_array(&dict, "Entries", | 549 connman_dbus_dict_append_variant_array(&dict, "Entries", |
473 DBUS_TYPE_STRING, __profile_entry_list, profile); | 550 DBUS_TYPE_STRING, __profile_entry_list, profile); |
474 | 551 |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 #undef ADD_STR | 720 #undef ADD_STR |
644 } | 721 } |
645 | 722 |
646 static DBusMessage *delete_entry(DBusConnection *conn, | 723 static DBusMessage *delete_entry(DBusConnection *conn, |
647 DBusMessage *msg, void *data) | 724 DBusMessage *msg, void *data) |
648 { | 725 { |
649 struct connman_profile *profile = data; | 726 struct connman_profile *profile = data; |
650 DBusMessageIter iter; | 727 DBusMessageIter iter; |
651 const char *identifier; | 728 const char *identifier; |
652 struct connman_service *service; | 729 struct connman_service *service; |
653 » GKeyFile *keyfile; | 730 » int err; |
654 » gboolean status; | |
655 | 731 |
656 _DBG_PROFILE("profile %s:%s", profile->ident.user, | 732 _DBG_PROFILE("profile %s:%s", profile->ident.user, |
657 profile->ident.ident); | 733 profile->ident.ident); |
658 | 734 |
659 if (dbus_message_iter_init(msg, &iter) == FALSE) | 735 if (dbus_message_iter_init(msg, &iter) == FALSE) |
660 return __connman_error_invalid_arguments(msg); | 736 return __connman_error_invalid_arguments(msg); |
661 | 737 |
662 dbus_message_iter_get_basic(&iter, &identifier); | 738 dbus_message_iter_get_basic(&iter, &identifier); |
663 | 739 |
664 if (__connman_security_check_privilege(msg, | 740 if (__connman_security_check_privilege(msg, |
665 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0) | 741 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0) |
666 return __connman_error_permission_denied(msg); | 742 return __connman_error_permission_denied(msg); |
667 | 743 |
668 service = __connman_service_lookup(identifier); | 744 service = __connman_service_lookup(identifier); |
669 if (service != NULL) { | 745 if (service != NULL) { |
670 /* NB: this does not remove the service */ | 746 /* NB: this does not remove the service */ |
671 __connman_service_reset(service); | 747 __connman_service_reset(service); |
672 } | 748 } |
673 | 749 |
674 /* Remove directly from profile */ | 750 /* Remove directly from profile */ |
675 » keyfile = __connman_storage_open(&profile->ident); | 751 » err = __connman_profile_delete_entry(profile, identifier); |
676 » if (keyfile == NULL) { | 752 » if (err) |
677 » » _DBG_PROFILE("cannot open key file"); | 753 » » return __connman_error_failed(msg, -err); |
678 » » return __connman_error_invalid_arguments(msg); | |
679 » } | |
680 | |
681 » status = g_key_file_remove_group(keyfile, identifier, NULL); | |
682 » __connman_storage_close(&profile->ident, keyfile, status); | |
683 | |
684 » if (status == FALSE) { | |
685 » » _DBG_PROFILE("cannot remove %s", identifier); | |
686 » » return __connman_error_not_found(msg); | |
687 » } | |
688 | 754 |
689 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); | 755 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); |
690 } | 756 } |
691 | 757 |
692 static GDBusMethodTable profile_methods[] = { | 758 static GDBusMethodTable profile_methods[] = { |
693 { "GetProperties", "", "a{sv}", get_properties }, | 759 { "GetProperties", "", "a{sv}", get_properties }, |
694 { "SetProperty", "sv", "", set_property }, | 760 { "SetProperty", "sv", "", set_property }, |
695 { "GetEntry", "s", "a{sv}", get_entry }, | 761 { "GetEntry", "s", "a{sv}", get_entry }, |
696 { "DeleteEntry", "s", "", delete_entry }, | 762 { "DeleteEntry", "s", "", delete_entry }, |
697 { }, | 763 { }, |
(...skipping 26 matching lines...) Expand all Loading... |
724 struct connman_profile *profile = data; | 790 struct connman_profile *profile = data; |
725 | 791 |
726 _DBG_PROFILE("profile %p", profile); | 792 _DBG_PROFILE("profile %p", profile); |
727 | 793 |
728 connman_info("Remove profile %s:%s", profile->ident.user, | 794 connman_info("Remove profile %s:%s", profile->ident.user, |
729 profile->ident.ident); | 795 profile->ident.ident); |
730 | 796 |
731 g_dbus_unregister_interface(connection, profile->path, | 797 g_dbus_unregister_interface(connection, profile->path, |
732 CONNMAN_PROFILE_INTERFACE); | 798 CONNMAN_PROFILE_INTERFACE); |
733 | 799 |
| 800 clear_timeout(profile); |
| 801 |
734 if (profile == default_profile) | 802 if (profile == default_profile) |
735 default_profile = NULL; | 803 default_profile = NULL; |
736 | 804 |
737 free_profile(profile); | 805 free_profile(profile); |
738 } | 806 } |
739 | 807 |
740 static char *getpath(const struct connman_storage_ident *ident) | 808 static char *getpath(const struct connman_storage_ident *ident) |
741 { | 809 { |
742 if (ident->user != NULL) { | 810 if (ident->user != NULL) { |
743 /* NB: check for two tokens done in validate_ident */ | 811 /* NB: check for two tokens done in validate_ident */ |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 return -EEXIST; | 1011 return -EEXIST; |
944 } | 1012 } |
945 if (path != NULL) | 1013 if (path != NULL) |
946 *path = profile->path; | 1014 *path = profile->path; |
947 } | 1015 } |
948 | 1016 |
949 profile_stack[++cur_profile] = profile; | 1017 profile_stack[++cur_profile] = profile; |
950 | 1018 |
951 profiles_changed(); | 1019 profiles_changed(); |
952 | 1020 |
953 » /* NB: this is a noop if we are online (or trying to get online) */ | 1021 » __connman_notifier_profile_push(profile); |
954 » __connman_service_auto_connect_any(); | |
955 | 1022 |
956 return 0; | 1023 return 0; |
957 } | 1024 } |
958 | 1025 |
959 /* | 1026 /* |
960 * Pop the profile from the top of the stack and remove it from | 1027 * Pop the profile from the top of the stack and remove it from |
961 * the in-memory table. Any associated services are invalidated | 1028 * the in-memory table. Any associated services are invalidated |
962 * (credentials revoked and connections closed). After a pop we | 1029 * (credentials revoked and connections closed). After a pop we |
963 * generate a PropertyChanged signal for Manager.Profiles. | 1030 * generate a PropertyChanged signal for Manager.Profiles. |
964 * | 1031 * |
(...skipping 26 matching lines...) Expand all Loading... |
991 } | 1058 } |
992 if (ident_equal(&profile->ident, &sid) == FALSE) { | 1059 if (ident_equal(&profile->ident, &sid) == FALSE) { |
993 connman_error("%s: %s is not the active profile", | 1060 connman_error("%s: %s is not the active profile", |
994 __func__, ident); | 1061 __func__, ident); |
995 free_ident(&sid); | 1062 free_ident(&sid); |
996 return -ENXIO; | 1063 return -ENXIO; |
997 } | 1064 } |
998 free_ident(&sid); | 1065 free_ident(&sid); |
999 } | 1066 } |
1000 | 1067 |
1001 » __connman_service_invalidate_profile(&profile->ident); | 1068 » /* |
| 1069 » * Pop the stack, invalidate all objects holding references |
| 1070 » * to the profile, then remove it from the in-memory table. |
| 1071 » * We do the reclaim after notification in case anyone holding |
| 1072 » * a reference tries to use it. |
| 1073 » */ |
| 1074 » cur_profile--; |
| 1075 |
| 1076 » __connman_notifier_profile_pop(profile); |
1002 | 1077 |
1003 g_hash_table_remove(profile_hash, profile->path); | 1078 g_hash_table_remove(profile_hash, profile->path); |
1004 cur_profile--; | |
1005 | 1079 |
1006 profiles_changed(); | 1080 profiles_changed(); |
1007 | 1081 |
1008 /* NB: no need to kick auto-connect; it will happen due to invalidate */ | |
1009 | |
1010 return 0; | 1082 return 0; |
1011 } | 1083 } |
1012 | 1084 |
1013 /* | 1085 /* |
1014 * Create a profile file and register it in memory. The | 1086 * Create a profile file and register it in memory. The |
1015 * file is created with minimal contents. | 1087 * file is created with minimal contents. |
1016 * TODO(sleffler) disallow overwriting an existing file? | 1088 * TODO(sleffler) disallow overwriting an existing file? |
1017 */ | 1089 */ |
1018 int __connman_profile_create(const char *name, const char **path) | 1090 int __connman_profile_create(const char *name, const char **path) |
1019 { | 1091 { |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 void __connman_profile_cleanup(void) | 1284 void __connman_profile_cleanup(void) |
1213 { | 1285 { |
1214 _DBG_PROFILE(""); | 1286 _DBG_PROFILE(""); |
1215 | 1287 |
1216 if (connection == NULL) | 1288 if (connection == NULL) |
1217 return; | 1289 return; |
1218 | 1290 |
1219 while (cur_profile >= 0) | 1291 while (cur_profile >= 0) |
1220 __connman_profile_pop(NULL); | 1292 __connman_profile_pop(NULL); |
1221 | 1293 |
| 1294 clear_timeout(NULL); /* NB: clear global timer */ |
| 1295 |
1222 g_hash_table_destroy(profile_hash); | 1296 g_hash_table_destroy(profile_hash); |
1223 profile_hash = NULL; | 1297 profile_hash = NULL; |
1224 | 1298 |
1225 clear_timeout(); /* cancel any pending timer */ | |
1226 | |
1227 connman_storage_unregister(&profile_storage); | 1299 connman_storage_unregister(&profile_storage); |
1228 | 1300 |
1229 dbus_connection_unref(connection); | 1301 dbus_connection_unref(connection); |
1230 } | 1302 } |
OLD | NEW |