Prefix group names with the service type
[connman] / src / profile.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
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
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <glib.h>
27 #include <gdbus.h>
28
29 #include "connman.h"
30
31 #define PROFILE_DEFAULT  "/profile/default"
32
33 enum connman_service_state {
34         CONNMAN_SERVICE_STATE_UNKNOWN = 0,
35         CONNMAN_SERVICE_STATE_IDLE    = 1,
36 };
37
38 struct connman_group {
39         GSequenceIter *iter;
40         char *id;
41         char *path;
42         char *type;
43         char *name;
44         char *mode;
45         char *security;
46         connman_uint8_t strength;
47         connman_bool_t favorite;
48         enum connman_service_state state;
49         struct connman_network *network;
50 };
51
52 static GSequence *groups = NULL;
53
54 static DBusConnection *connection = NULL;
55
56 static const char *state2string(enum connman_service_state state)
57 {
58         switch (state) {
59         case CONNMAN_SERVICE_STATE_UNKNOWN:
60                 break;
61         case CONNMAN_SERVICE_STATE_IDLE:
62                 return "idle";
63         }
64
65         return NULL;
66 }
67
68 static DBusMessage *get_properties(DBusConnection *conn,
69                                         DBusMessage *msg, void *data)
70 {
71         struct connman_group *group = data;
72         DBusMessage *reply;
73         DBusMessageIter array, dict;
74         const char *str;
75
76         DBG("conn %p", conn);
77
78         reply = dbus_message_new_method_return(msg);
79         if (reply == NULL)
80                 return NULL;
81
82         dbus_message_iter_init_append(reply, &array);
83
84         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
85                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
86                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
87                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
88
89         str = state2string(group->state);
90         if (str != NULL)
91                 connman_dbus_dict_append_variant(&dict, "State",
92                                                 DBUS_TYPE_STRING, &str);
93
94         if (group->type != NULL)
95                 connman_dbus_dict_append_variant(&dict, "Type",
96                                         DBUS_TYPE_STRING, &group->type);
97
98         if (group->name != NULL)
99                 connman_dbus_dict_append_variant(&dict, "Name",
100                                         DBUS_TYPE_STRING, &group->name);
101
102         if (group->mode != NULL)
103                 connman_dbus_dict_append_variant(&dict, "Mode",
104                                         DBUS_TYPE_STRING, &group->mode);
105
106         if (group->security != NULL)
107                 connman_dbus_dict_append_variant(&dict, "Security",
108                                         DBUS_TYPE_STRING, &group->security);
109
110         if (group->strength > 0)
111                 connman_dbus_dict_append_variant(&dict, "Strength",
112                                         DBUS_TYPE_BYTE, &group->strength);
113
114         connman_dbus_dict_append_variant(&dict, "Favorite",
115                                         DBUS_TYPE_BOOLEAN, &group->favorite);
116
117         dbus_message_iter_close_container(&array, &dict);
118
119         return reply;
120 }
121
122 static DBusMessage *connect_service(DBusConnection *conn,
123                                         DBusMessage *msg, void *data)
124 {
125         return __connman_error_not_implemented(msg);
126 }
127
128 static DBusMessage *disconnect_service(DBusConnection *conn,
129                                         DBusMessage *msg, void *data)
130 {
131         return __connman_error_not_implemented(msg);
132 }
133
134 static DBusMessage *remove_service(DBusConnection *conn,
135                                         DBusMessage *msg, void *data)
136 {
137         return __connman_error_not_implemented(msg);
138 }
139
140 static DBusMessage *move_before(DBusConnection *conn,
141                                         DBusMessage *msg, void *data)
142 {
143         return __connman_error_not_implemented(msg);
144 }
145
146 static DBusMessage *move_after(DBusConnection *conn,
147                                         DBusMessage *msg, void *data)
148 {
149         return __connman_error_not_implemented(msg);
150 }
151
152 static GDBusMethodTable service_methods[] = {
153         { "GetProperties", "",  "a{sv}", get_properties     },
154         { "Connect",       "",  "",      connect_service    },
155         { "Disconnect",    "",  "",      disconnect_service },
156         { "Remove",        "",  "",      remove_service     },
157         { "MoveBefore",    "o", "",      move_before        },
158         { "MoveAfter",     "o", "",      move_after         },
159         { },
160 };
161
162 static GDBusSignalTable service_signals[] = {
163         { "PropertyChanged", "sv" },
164         { },
165 };
166
167 static void free_group(gpointer data)
168 {
169         struct connman_group *group = data;
170
171         DBG("group %p", group);
172
173         g_dbus_unregister_interface(connection, group->path,
174                                                 CONNMAN_SERVICE_INTERFACE);
175
176         g_free(group->security);
177         g_free(group->mode);
178         g_free(group->name);
179         g_free(group->type);
180         g_free(group->path);
181         g_free(group->id);
182         g_free(group);
183 }
184
185 static gint compare_group(gconstpointer a, gconstpointer b, gpointer user_data)
186 {
187         struct connman_group *group = (void *) a;
188
189         return g_strcmp0(group->id, user_data);
190 }
191
192 static struct connman_group *lookup_group(const char *name)
193 {
194         GSequenceIter *iter;
195         struct connman_group *group;
196
197         DBG("name %s", name);
198
199         if (name == NULL)
200                 return NULL;
201
202         iter = g_sequence_search(groups, NULL, compare_group, (char *) name);
203         if (g_sequence_iter_is_begin(iter) == FALSE &&
204                                 g_sequence_iter_is_end(iter) == FALSE) {
205                 group = g_sequence_get(iter);
206                 if (group != NULL)
207                         goto done;
208         }
209
210         group = g_try_new0(struct connman_group, 1);
211         if (group == NULL)
212                 return NULL;
213
214         group->id = g_strdup(name);
215
216         group->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
217         group->path = g_strdup_printf("%s/%s", PROFILE_DEFAULT, name);
218
219         group->favorite = FALSE;
220
221         group->state = CONNMAN_SERVICE_STATE_IDLE;
222
223         group->iter = g_sequence_append(groups, group);
224
225         g_dbus_register_interface(connection, group->path,
226                                         CONNMAN_SERVICE_INTERFACE,
227                                         service_methods, service_signals,
228                                                         NULL, group, NULL);
229
230 done:
231         DBG("group %p", group);
232
233         return group;
234 }
235
236 int __connman_profile_add_device(struct connman_device *device)
237 {
238         struct connman_group *group;
239         char *name;
240
241         DBG("device %p", device);
242
243         name = g_strdup_printf("%s_%d", __connman_device_get_type(device),
244                                         connman_device_get_index(device));
245         group = lookup_group(name);
246         g_free(name);
247
248         if (group == NULL)
249                 return -EINVAL;
250
251         group->type = g_strdup(__connman_device_get_type(device));
252
253         return 0;
254 }
255
256 int __connman_profile_remove_device(struct connman_device *device)
257 {
258         struct connman_group *group;
259         char *name;
260
261         DBG("device %p", device);
262
263         name = g_strdup_printf("%s_%d", __connman_device_get_type(device),
264                                         connman_device_get_index(device));
265         group = lookup_group(name);
266         g_free(name);
267
268         if (group == NULL)
269                 return -EINVAL;
270
271         return 0;
272 }
273
274 int __connman_profile_add_network(struct connman_network *network)
275 {
276         struct connman_group *group;
277         char *name;
278
279         DBG("network %p", network);
280
281         if (__connman_network_get_group(network) == NULL)
282                 return -EINVAL;
283
284         name = g_strdup_printf("%s_%s", __connman_network_get_type(network),
285                                         __connman_network_get_group(network));
286         group = lookup_group(name);
287         g_free(name);
288
289         if (group == NULL)
290                 return -EINVAL;
291
292         g_free(group->type);
293         g_free(group->name);
294
295         group->type = g_strdup(__connman_network_get_type(network));
296         group->name = g_strdup(connman_network_get_string(network, "Name"));
297
298         group->strength = connman_network_get_uint8(network, "Strength");
299
300         if (group->network == NULL) {
301                 group->network = network;
302
303                 group->mode = g_strdup(connman_network_get_string(network,
304                                                                 "WiFi.Mode"));
305                 group->security = g_strdup(connman_network_get_string(network,
306                                                         "WiFi.Security"));
307         }
308
309         return 0;
310 }
311
312 int __connman_profile_remove_network(struct connman_network *network)
313 {
314         struct connman_group *group;
315         char *name;
316
317         DBG("network %p", network);
318
319         if (__connman_network_get_group(network) == NULL)
320                 return -EINVAL;
321
322         name = g_strdup_printf("%s_%s", __connman_network_get_type(network),
323                                         __connman_network_get_group(network));
324         group = lookup_group(name);
325         g_free(name);
326
327         if (group == NULL)
328                 return -EINVAL;
329
330         if (group->network == network) {
331                 g_free(group->security);
332                 group->security = NULL;
333
334                 g_free(group->mode);
335                 group->mode = NULL;
336
337                 group->network = NULL;
338         }
339
340         return 0;
341 }
342
343 const char *__connman_profile_active(void)
344 {
345         DBG("");
346
347         return PROFILE_DEFAULT;
348 }
349
350 void __connman_profile_list(DBusMessageIter *iter)
351 {
352         const char *path = __connman_profile_active();
353
354         DBG("");
355
356         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
357 }
358
359 static void append_path(gpointer value, gpointer user_data)
360 {
361         struct connman_group *group = value;
362         DBusMessageIter *iter = user_data;
363
364         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
365                                                         &group->path);
366 }
367
368 void __connman_profile_list_services(DBusMessageIter *iter)
369 {
370         DBG("");
371
372         g_sequence_foreach(groups, append_path, iter);
373 }
374
375 static void append_services(DBusMessageIter *dict)
376 {
377         DBusMessageIter entry, value, iter;
378         const char *key = "Services";
379
380         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
381                                                                 NULL, &entry);
382
383         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
384
385         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
386                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
387                                                                 &value);
388
389         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
390                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
391         __connman_profile_list_services(&iter);
392         dbus_message_iter_close_container(&value, &iter);
393
394         dbus_message_iter_close_container(&entry, &value);
395
396         dbus_message_iter_close_container(dict, &entry);
397 }
398
399 static DBusMessage *profile_properties(DBusConnection *conn,
400                                         DBusMessage *msg, void *data)
401 {
402         const char *name = "Default";
403         DBusMessage *reply;
404         DBusMessageIter array, dict;
405
406         DBG("conn %p", conn);
407
408         reply = dbus_message_new_method_return(msg);
409         if (reply == NULL)
410                 return NULL;
411
412         dbus_message_iter_init_append(reply, &array);
413
414         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
415                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
416                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
417                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
418
419         connman_dbus_dict_append_variant(&dict, "Name",
420                                                 DBUS_TYPE_STRING, &name);
421
422         append_services(&dict);
423
424         dbus_message_iter_close_container(&array, &dict);
425
426         return reply;
427 }
428
429 static GDBusMethodTable profile_methods[] = {
430         { "GetProperties", "", "a{sv}", profile_properties },
431         { },
432 };
433
434 int __connman_profile_init(DBusConnection *conn)
435 {
436         DBG("conn %p", conn);
437
438         connection = dbus_connection_ref(conn);
439         if (connection == NULL)
440                 return -1;
441
442         groups = g_sequence_new(free_group);
443
444         g_dbus_register_interface(connection, PROFILE_DEFAULT,
445                                                 CONNMAN_PROFILE_INTERFACE,
446                                                 profile_methods,
447                                                 NULL, NULL, NULL, NULL);
448
449         return 0;
450 }
451
452 void __connman_profile_cleanup(void)
453 {
454         DBG("conn %p", connection);
455
456         g_dbus_unregister_interface(connection, PROFILE_DEFAULT,
457                                                 CONNMAN_PROFILE_INTERFACE);
458
459         g_sequence_free(groups);
460         groups = NULL;
461
462         if (connection == NULL)
463                 return;
464
465         dbus_connection_unref(connection);
466 }