2343d2116650a9bcd752c63ab46c5c3bf040565e
[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
278         DBG("network %p", network);
279
280         group = lookup_group(__connman_network_get_group(network));
281         if (group == NULL)
282                 return -EINVAL;
283
284         g_free(group->type);
285         g_free(group->name);
286
287         group->type = g_strdup(__connman_network_get_type(network));
288         group->name = g_strdup(connman_network_get_string(network, "Name"));
289
290         group->strength = connman_network_get_uint8(network, "Strength");
291
292         if (group->network == NULL) {
293                 group->network = network;
294
295                 group->mode = g_strdup(connman_network_get_string(network,
296                                                                 "WiFi.Mode"));
297                 group->security = g_strdup(connman_network_get_string(network,
298                                                         "WiFi.Security"));
299         }
300
301         return 0;
302 }
303
304 int __connman_profile_remove_network(struct connman_network *network)
305 {
306         struct connman_group *group;
307
308         DBG("network %p", network);
309
310         group = lookup_group(__connman_network_get_group(network));
311         if (group == NULL)
312                 return -EINVAL;
313
314         if (group->network == network) {
315                 g_free(group->security);
316                 group->security = NULL;
317
318                 g_free(group->mode);
319                 group->mode = NULL;
320
321                 group->network = NULL;
322         }
323
324         return 0;
325 }
326
327 const char *__connman_profile_active(void)
328 {
329         DBG("");
330
331         return PROFILE_DEFAULT;
332 }
333
334 void __connman_profile_list(DBusMessageIter *iter)
335 {
336         const char *path = __connman_profile_active();
337
338         DBG("");
339
340         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
341 }
342
343 static void append_path(gpointer value, gpointer user_data)
344 {
345         struct connman_group *group = value;
346         DBusMessageIter *iter = user_data;
347
348         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
349                                                         &group->path);
350 }
351
352 void __connman_profile_list_services(DBusMessageIter *iter)
353 {
354         DBG("");
355
356         g_sequence_foreach(groups, append_path, iter);
357 }
358
359 static void append_services(DBusMessageIter *dict)
360 {
361         DBusMessageIter entry, value, iter;
362         const char *key = "Services";
363
364         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
365                                                                 NULL, &entry);
366
367         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
368
369         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
370                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
371                                                                 &value);
372
373         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
374                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
375         __connman_profile_list_services(&iter);
376         dbus_message_iter_close_container(&value, &iter);
377
378         dbus_message_iter_close_container(&entry, &value);
379
380         dbus_message_iter_close_container(dict, &entry);
381 }
382
383 static DBusMessage *profile_properties(DBusConnection *conn,
384                                         DBusMessage *msg, void *data)
385 {
386         const char *name = "Default";
387         DBusMessage *reply;
388         DBusMessageIter array, dict;
389
390         DBG("conn %p", conn);
391
392         reply = dbus_message_new_method_return(msg);
393         if (reply == NULL)
394                 return NULL;
395
396         dbus_message_iter_init_append(reply, &array);
397
398         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
399                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
400                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
401                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
402
403         connman_dbus_dict_append_variant(&dict, "Name",
404                                                 DBUS_TYPE_STRING, &name);
405
406         append_services(&dict);
407
408         dbus_message_iter_close_container(&array, &dict);
409
410         return reply;
411 }
412
413 static GDBusMethodTable profile_methods[] = {
414         { "GetProperties", "", "a{sv}", profile_properties },
415         { },
416 };
417
418 int __connman_profile_init(DBusConnection *conn)
419 {
420         DBG("conn %p", conn);
421
422         connection = dbus_connection_ref(conn);
423         if (connection == NULL)
424                 return -1;
425
426         groups = g_sequence_new(free_group);
427
428         g_dbus_register_interface(connection, PROFILE_DEFAULT,
429                                                 CONNMAN_PROFILE_INTERFACE,
430                                                 profile_methods,
431                                                 NULL, NULL, NULL, NULL);
432
433         return 0;
434 }
435
436 void __connman_profile_cleanup(void)
437 {
438         DBG("conn %p", connection);
439
440         g_dbus_unregister_interface(connection, PROFILE_DEFAULT,
441                                                 CONNMAN_PROFILE_INTERFACE);
442
443         g_sequence_free(groups);
444         groups = NULL;
445
446         if (connection == NULL)
447                 return;
448
449         dbus_connection_unref(connection);
450 }