a270654602631f8cebec0867e3fff0b8563e40ed
[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 struct connman_group {
34         char *path;
35         char *type;
36         char *name;
37         char *mode;
38         char *security;
39         connman_uint8_t strength;
40         struct connman_network *network;
41 };
42
43 static GHashTable *groups = NULL;
44
45 static DBusConnection *connection = NULL;
46
47 static DBusMessage *get_properties(DBusConnection *conn,
48                                         DBusMessage *msg, void *data)
49 {
50         struct connman_group *group = data;
51         DBusMessage *reply;
52         DBusMessageIter array, dict;
53
54         DBG("conn %p", conn);
55
56         reply = dbus_message_new_method_return(msg);
57         if (reply == NULL)
58                 return NULL;
59
60         dbus_message_iter_init_append(reply, &array);
61
62         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
63                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
64                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
65                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
66
67         if (group->type != NULL)
68                 connman_dbus_dict_append_variant(&dict, "Type",
69                                         DBUS_TYPE_STRING, &group->type);
70
71         if (group->name != NULL)
72                 connman_dbus_dict_append_variant(&dict, "Name",
73                                         DBUS_TYPE_STRING, &group->name);
74
75         if (group->mode != NULL)
76                 connman_dbus_dict_append_variant(&dict, "Mode",
77                                         DBUS_TYPE_STRING, &group->mode);
78
79         if (group->security != NULL)
80                 connman_dbus_dict_append_variant(&dict, "Security",
81                                         DBUS_TYPE_STRING, &group->security);
82
83         if (group->strength > 0)
84                 connman_dbus_dict_append_variant(&dict, "Strength",
85                                         DBUS_TYPE_BYTE, &group->strength);
86
87         dbus_message_iter_close_container(&array, &dict);
88
89         return reply;
90 }
91
92 static GDBusMethodTable service_methods[] = {
93         { "GetProperties", "", "a{sv}", get_properties },
94         { },
95 };
96
97 static void free_group(gpointer data)
98 {
99         struct connman_group *group = data;
100
101         DBG("group %p", group);
102
103         g_dbus_unregister_interface(connection, group->path,
104                                                 CONNMAN_SERVICE_INTERFACE);
105
106         g_free(group->security);
107         g_free(group->mode);
108         g_free(group->name);
109         g_free(group->type);
110         g_free(group->path);
111         g_free(group);
112 }
113
114 static struct connman_group *lookup_group(const char *name)
115 {
116         struct connman_group *group;
117
118         DBG("name %s", name);
119
120         if (name == NULL)
121                 return NULL;
122
123         group = g_hash_table_lookup(groups, name);
124         if (group != NULL)
125                 goto done;
126
127         group = g_try_new0(struct connman_group, 1);
128         if (group == NULL)
129                 return NULL;
130
131         group->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
132         group->path = g_strdup_printf("%s/%s", PROFILE_DEFAULT, name);
133
134         g_hash_table_insert(groups, g_strdup(name), group);
135
136         g_dbus_register_interface(connection, group->path,
137                                                 CONNMAN_SERVICE_INTERFACE,
138                                                 service_methods,
139                                                 NULL, NULL, group, NULL);
140
141 done:
142         DBG("group %p", group);
143
144         return group;
145 }
146
147 int __connman_profile_add_device(struct connman_device *device)
148 {
149         struct connman_group *group;
150         char *name;
151
152         DBG("device %p", device);
153
154         name = g_strdup_printf("%s_%d", __connman_device_get_type(device),
155                                         connman_device_get_index(device));
156         group = lookup_group(name);
157         g_free(name);
158
159         if (group == NULL)
160                 return -EINVAL;
161
162         group->type = g_strdup(__connman_device_get_type(device));
163         group->name = g_strdup(connman_device_get_string(device, "Name"));
164
165         return 0;
166 }
167
168 int __connman_profile_remove_device(struct connman_device *device)
169 {
170         struct connman_group *group;
171         char *name;
172
173         DBG("device %p", device);
174
175         name = g_strdup_printf("%s_%d", __connman_device_get_type(device),
176                                         connman_device_get_index(device));
177         group = lookup_group(name);
178         g_free(name);
179
180         if (group == NULL)
181                 return -EINVAL;
182
183         return 0;
184 }
185
186 int __connman_profile_add_network(struct connman_network *network)
187 {
188         struct connman_group *group;
189
190         DBG("network %p", network);
191
192         group = lookup_group(__connman_network_get_group(network));
193         if (group == NULL)
194                 return -EINVAL;
195
196         g_free(group->type);
197         g_free(group->name);
198
199         group->type = g_strdup(__connman_network_get_type(network));
200         group->name = g_strdup(connman_network_get_string(network, "Name"));
201
202         group->strength = connman_network_get_uint8(network, "Strength");
203
204         if (group->network == NULL) {
205                 group->network = network;
206
207                 group->mode = g_strdup(connman_network_get_string(network,
208                                                                 "WiFi.Mode"));
209                 group->security = g_strdup(connman_network_get_string(network,
210                                                         "WiFi.Security"));
211         }
212
213         return 0;
214 }
215
216 int __connman_profile_remove_network(struct connman_network *network)
217 {
218         struct connman_group *group;
219
220         DBG("network %p", network);
221
222         group = lookup_group(__connman_network_get_group(network));
223         if (group == NULL)
224                 return -EINVAL;
225
226         if (group->network == network) {
227                 g_free(group->security);
228                 group->security = NULL;
229
230                 g_free(group->mode);
231                 group->mode = NULL;
232
233                 group->network = NULL;
234         }
235
236         return 0;
237 }
238
239 const char *__connman_profile_active(void)
240 {
241         DBG("");
242
243         return PROFILE_DEFAULT;
244 }
245
246 void __connman_profile_list(DBusMessageIter *iter)
247 {
248         const char *path = __connman_profile_active();
249
250         DBG("");
251
252         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
253 }
254
255 static void append_path(gpointer key, gpointer value, gpointer user_data)
256 {
257         struct connman_group *group = value;
258         DBusMessageIter *iter = user_data;
259
260         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
261                                                         &group->path);
262 }
263
264 void __connman_profile_list_services(DBusMessageIter *iter)
265 {
266         DBG("");
267
268         g_hash_table_foreach(groups, append_path, iter);
269 }
270
271 static void append_services(DBusMessageIter *dict)
272 {
273         DBusMessageIter entry, value, iter;
274         const char *key = "Services";
275
276         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
277                                                                 NULL, &entry);
278
279         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
280
281         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
282                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
283                                                                 &value);
284
285         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
286                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
287         __connman_profile_list_services(&iter);
288         dbus_message_iter_close_container(&value, &iter);
289
290         dbus_message_iter_close_container(&entry, &value);
291
292         dbus_message_iter_close_container(dict, &entry);
293 }
294
295 static DBusMessage *profile_properties(DBusConnection *conn,
296                                         DBusMessage *msg, void *data)
297 {
298         const char *name = "Default";
299         DBusMessage *reply;
300         DBusMessageIter array, dict;
301
302         DBG("conn %p", conn);
303
304         reply = dbus_message_new_method_return(msg);
305         if (reply == NULL)
306                 return NULL;
307
308         dbus_message_iter_init_append(reply, &array);
309
310         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
311                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
312                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
313                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
314
315         connman_dbus_dict_append_variant(&dict, "Name",
316                                                 DBUS_TYPE_STRING, &name);
317
318         append_services(&dict);
319
320         dbus_message_iter_close_container(&array, &dict);
321
322         return reply;
323 }
324
325 static GDBusMethodTable profile_methods[] = {
326         { "GetProperties", "", "a{sv}", profile_properties },
327         { },
328 };
329
330 int __connman_profile_init(DBusConnection *conn)
331 {
332         DBG("conn %p", conn);
333
334         connection = dbus_connection_ref(conn);
335         if (connection == NULL)
336                 return -1;
337
338         groups = g_hash_table_new_full(g_str_hash, g_str_equal,
339                                                         g_free, free_group);
340
341         g_dbus_register_interface(connection, PROFILE_DEFAULT,
342                                                 CONNMAN_PROFILE_INTERFACE,
343                                                 profile_methods,
344                                                 NULL, NULL, NULL, NULL);
345
346         return 0;
347 }
348
349 void __connman_profile_cleanup(void)
350 {
351         DBG("conn %p", connection);
352
353         g_dbus_unregister_interface(connection, PROFILE_DEFAULT,
354                                                 CONNMAN_PROFILE_INTERFACE);
355
356         g_hash_table_destroy(groups);
357         groups = NULL;
358
359         if (connection == NULL)
360                 return;
361
362         dbus_connection_unref(connection);
363 }