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