unit: handling type of connection into session api
[framework/connectivity/connman.git] / unit / session-api.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2011  BWM CarIT GmbH. 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 <errno.h>
27
28 #include <gdbus/gdbus.h>
29
30 #include "test-connman.h"
31
32 static enum connman_session_state string2state(const char *state)
33 {
34         if (g_strcmp0(state, "connected") == 0)
35                 return CONNMAN_SESSION_STATE_CONNECTED;
36         if (g_strcmp0(state, "online") == 0)
37                 return CONNMAN_SESSION_STATE_ONLINE;
38
39         return CONNMAN_SESSION_STATE_DISCONNECTED;
40 }
41
42 static enum connman_session_state string2type(const char *type)
43 {
44         if (g_strcmp0(type, "local") == 0)
45                 return CONNMAN_SESSION_TYPE_LOCAL;
46         if (g_strcmp0(type, "internet") == 0)
47                 return CONNMAN_SESSION_TYPE_INTERNET;
48
49         return CONNMAN_SESSION_TYPE_ANY;
50 }
51
52 static const char *roamingpolicy2string(enum connman_session_roaming_policy policy)
53 {
54         switch (policy) {
55         case CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN:
56                 break;
57         case CONNMAN_SESSION_ROAMING_POLICY_DEFAULT:
58                 return "default";
59         case CONNMAN_SESSION_ROAMING_POLICY_ALWAYS:
60                 return "always";
61         case CONNMAN_SESSION_ROAMING_POLICY_FORBIDDEN:
62                 return "forbidden";
63         case CONNMAN_SESSION_ROAMING_POLICY_NATIONAL:
64                 return "national";
65         case CONNMAN_SESSION_ROAMING_POLICY_INTERNATIONAL:
66                 return "international";
67         }
68
69         return "";
70 }
71
72 static enum connman_session_roaming_policy string2roamingpolicy(const char *policy)
73 {
74         if (g_strcmp0(policy, "default") == 0)
75                 return CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
76         else if (g_strcmp0(policy, "always") == 0)
77                 return CONNMAN_SESSION_ROAMING_POLICY_ALWAYS;
78         else if (g_strcmp0(policy, "forbidden") == 0)
79                 return CONNMAN_SESSION_ROAMING_POLICY_FORBIDDEN;
80         else if (g_strcmp0(policy, "national") == 0)
81                 return CONNMAN_SESSION_ROAMING_POLICY_NATIONAL;
82         else if (g_strcmp0(policy, "international") == 0)
83                 return CONNMAN_SESSION_ROAMING_POLICY_INTERNATIONAL;
84         else
85                 return CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN;
86 }
87
88 void bearer_info_cleanup(gpointer data, gpointer user_data)
89 {
90         struct test_bearer_info *info = data;
91
92         g_free(info->name);
93         g_free(info);
94 }
95
96 static GSList *session_parse_allowed_bearers(DBusMessageIter *iter)
97 {
98         struct test_bearer_info *info;
99         DBusMessageIter array;
100         GSList *list = NULL;
101
102         dbus_message_iter_recurse(iter, &array);
103
104         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
105                 char *bearer = NULL;
106
107                 dbus_message_iter_get_basic(&array, &bearer);
108
109                 info = g_try_new0(struct test_bearer_info, 1);
110                 if (info == NULL) {
111                         g_slist_foreach(list, bearer_info_cleanup, NULL);
112                         g_slist_free(list);
113
114                         return NULL;
115                 }
116
117                 info->name = g_strdup(bearer);
118
119                 list = g_slist_append(list, info);
120
121                 dbus_message_iter_next(&array);
122         }
123
124         return list;
125 }
126
127 static DBusMessage *notify_release(DBusConnection *conn,
128                                         DBusMessage *msg, void *user_data)
129 {
130         struct test_session *session = user_data;
131
132         LOG("session %p", session);
133
134         if (session->notify != NULL)
135                 session->notify(session);
136
137         return NULL;
138 }
139
140 static DBusMessage *notify_update(DBusConnection *conn,
141                                         DBusMessage *msg, void *user_data)
142 {
143         struct test_session *session = user_data;
144         struct test_session_info *info = session->info;
145         DBusMessageIter iter, array;
146         GSList *allowed_bearers;
147
148         LOG("session %p notify %s", session, session->notify_path);
149
150         dbus_message_iter_init(msg, &iter);
151         dbus_message_iter_recurse(&iter, &array);
152
153         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
154                 DBusMessageIter entry, value;
155                 const char *key;
156
157                 dbus_message_iter_recurse(&array, &entry);
158                 dbus_message_iter_get_basic(&entry, &key);
159
160                 dbus_message_iter_next(&entry);
161                 dbus_message_iter_recurse(&entry, &value);
162
163                 switch (dbus_message_iter_get_arg_type(&value)) {
164                 case DBUS_TYPE_ARRAY:
165                         if (g_str_equal(key, "AllowedBearers") == TRUE) {
166                                 allowed_bearers = session_parse_allowed_bearers(&value);
167
168                                 g_slist_foreach(info->allowed_bearers,
169                                                 bearer_info_cleanup, NULL);
170                                 g_slist_free(info->allowed_bearers);
171
172                                 info->allowed_bearers = allowed_bearers;
173
174                         } else if (g_str_equal(key, "IPv4") == TRUE) {
175                                 /* XXX */
176
177                         } else if (g_str_equal(key, "IPv6") == TRUE) {
178                                 /* XXX */
179
180                         } else {
181                                 g_assert(FALSE);
182                                 return __connman_error_invalid_arguments(msg);
183                         }
184                         break;
185                 case DBUS_TYPE_BOOLEAN:
186                         if (g_str_equal(key, "Priority") == TRUE) {
187                                 dbus_message_iter_get_basic(&value,
188                                                         &info->priority);
189
190                         } else if (g_str_equal(key, "AvoidHandover") == TRUE) {
191                                 dbus_message_iter_get_basic(&value,
192                                                         &info->avoid_handover);
193
194                         } else if (g_str_equal(key, "StayConnected") == TRUE) {
195                                 dbus_message_iter_get_basic(&value,
196                                                         &info->stay_connected);
197
198                         } else if (g_str_equal(key, "EmergencyCall") == TRUE) {
199                                 dbus_message_iter_get_basic(&value,
200                                                         &info->ecall);
201
202                         } else {
203                                 g_assert(FALSE);
204                                 return __connman_error_invalid_arguments(msg);
205                         }
206                         break;
207                 case DBUS_TYPE_UINT32:
208                         if (g_str_equal(key, "PeriodicConnect") == TRUE) {
209                                 dbus_message_iter_get_basic(&value,
210                                                         &info->periodic_connect);
211
212                         } else if (g_str_equal(key, "IdleTimeout") == TRUE) {
213                                 dbus_message_iter_get_basic(&value,
214                                                         &info->idle_timeout);
215
216                         } else if (g_str_equal(key, "SessionMarker") == TRUE) {
217                                 dbus_message_iter_get_basic(&value,
218                                                         &info->marker);
219
220                         } else {
221                                 g_assert(FALSE);
222                                 return __connman_error_invalid_arguments(msg);
223                         }
224                         break;
225                 case DBUS_TYPE_STRING:
226                         if (g_str_equal(key, "State") == TRUE) {
227                                 const char *val;
228                                 dbus_message_iter_get_basic(&value, &val);
229
230                                 info->state = string2state(val);
231                         } else if (g_str_equal(key, "Bearer") == TRUE) {
232                                 const char *val;
233                                 dbus_message_iter_get_basic(&value, &val);
234
235                                 if (info->bearer != NULL)
236                                         g_free(info->bearer);
237
238                                 info->bearer = g_strdup(val);
239
240                         } else if (g_str_equal(key, "Name") == TRUE) {
241                                 const char *val;
242                                 dbus_message_iter_get_basic(&value, &val);
243
244                                 if (info->name != NULL)
245                                         g_free(info->name);
246
247                                 info->name = g_strdup(val);
248
249                         } else if (g_str_equal(key, "RoamingPolicy") == TRUE) {
250                                 const char *val;
251                                 dbus_message_iter_get_basic(&value, &val);
252                                 info->roaming_policy =
253                                         string2roamingpolicy(val);
254
255                         } else if (g_str_equal(key, "Interface") == TRUE) {
256                                 const char *val;
257                                 dbus_message_iter_get_basic(&value, &val);
258
259                                 if (info->interface != NULL)
260                                         g_free(info->interface);
261
262                                 info->interface = g_strdup(val);
263
264                         } else if (g_str_equal(key, "ConnectionType")
265                                                                 == TRUE) {
266                                 const char *val;
267                                 dbus_message_iter_get_basic(&value, &val);
268
269                                 info->type = string2type(val);
270                         } else {
271                                 g_assert(FALSE);
272                                 return __connman_error_invalid_arguments(msg);
273                         }
274                         break;
275                 default:
276                         g_assert(FALSE);
277                         return __connman_error_invalid_arguments(msg);
278                 }
279                 dbus_message_iter_next(&array);
280         }
281
282         if (session->notify != NULL)
283                 session->notify(session);
284
285         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
286 }
287
288 static GDBusMethodTable notify_methods[] = {
289         { "Release", "",      "", notify_release },
290         { "Update",  "a{sv}", "", notify_update  },
291         { },
292 };
293
294 int session_notify_register(struct test_session *session,
295                                 const char *notify_path)
296 {
297         if (g_dbus_register_interface(session->connection, notify_path,
298                         CONNMAN_NOTIFICATION_INTERFACE,
299                         notify_methods, NULL, NULL,
300                         session, NULL) == FALSE) {
301                 return -EINVAL;
302         }
303
304         return 0;
305 }
306
307 int session_notify_unregister(struct test_session *session,
308                                 const char *notify_path)
309 {
310         if (g_dbus_unregister_interface(session->connection, notify_path,
311                                 CONNMAN_NOTIFICATION_INTERFACE) == FALSE) {
312                 return -EINVAL;
313         }
314
315         return 0;
316 }
317
318 static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
319 {
320         struct test_session_info *info = user_data;
321         GSList *list;
322
323         for (list = info->allowed_bearers;
324                         list != NULL; list = list->next) {
325                 struct test_bearer_info *info = list->data;
326
327                 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
328                                                 &info->name);
329         }
330 }
331
332 void session_append_settings(DBusMessageIter *dict,
333                                 struct test_session_info *info)
334 {
335         const char *policy;
336
337         connman_dbus_dict_append_basic(dict, "Priority",
338                                                 DBUS_TYPE_BOOLEAN,
339                                                 &info->priority);
340
341         connman_dbus_dict_append_array(dict, "AllowedBearers",
342                                                 DBUS_TYPE_STRING,
343                                                 append_allowed_bearers,
344                                                 info);
345
346         connman_dbus_dict_append_basic(dict, "AvoidHandover",
347                                                 DBUS_TYPE_BOOLEAN,
348                                                 &info->avoid_handover);
349
350         connman_dbus_dict_append_basic(dict, "StayConnected",
351                                                 DBUS_TYPE_BOOLEAN,
352                                                 &info->stay_connected);
353
354         connman_dbus_dict_append_basic(dict, "PeriodicConnect",
355                                                 DBUS_TYPE_UINT32,
356                                                 &info->periodic_connect);
357
358         connman_dbus_dict_append_basic(dict, "IdleTimeout",
359                                                 DBUS_TYPE_UINT32,
360                                                 &info->idle_timeout);
361
362         connman_dbus_dict_append_basic(dict, "EmergencyCall",
363                                                 DBUS_TYPE_BOOLEAN,
364                                                 &info->ecall);
365
366         policy = roamingpolicy2string(info->roaming_policy);
367         connman_dbus_dict_append_basic(dict, "RoamingPolicy",
368                                                 DBUS_TYPE_STRING,
369                                                 &policy);
370 }
371
372 DBusMessage *session_connect(DBusConnection *connection,
373                                 struct test_session *session)
374 {
375         DBusMessage *message, *reply;
376         DBusError error;
377
378         message = dbus_message_new_method_call(CONNMAN_SERVICE,
379                                                 session->session_path,
380                                                 CONNMAN_SESSION_INTERFACE,
381                                                         "Connect");
382         if (message == NULL)
383                 return NULL;
384
385         dbus_error_init(&error);
386
387         reply = dbus_connection_send_with_reply_and_block(connection,
388                                                         message, -1, &error);
389         if (reply == NULL) {
390                 if (dbus_error_is_set(&error) == TRUE) {
391                         LOG("%s", error.message);
392                         dbus_error_free(&error);
393                 } else {
394                         LOG("Failed to get properties");
395                 }
396                 dbus_message_unref(message);
397                 return NULL;
398         }
399
400         dbus_message_unref(message);
401
402         return reply;
403 }
404
405 DBusMessage *session_disconnect(DBusConnection *connection,
406                                         struct test_session *session)
407 {
408         DBusMessage *message, *reply;
409         DBusError error;
410
411         message = dbus_message_new_method_call(CONNMAN_SERVICE,
412                                                 session->session_path,
413                                                 CONNMAN_SESSION_INTERFACE,
414                                                         "Disconnect");
415         if (message == NULL)
416                 return NULL;
417
418         dbus_error_init(&error);
419
420         reply = dbus_connection_send_with_reply_and_block(connection,
421                                                         message, -1, &error);
422         if (reply == NULL) {
423                 if (dbus_error_is_set(&error) == TRUE) {
424                         LOG("%s", error.message);
425                         dbus_error_free(&error);
426                 } else {
427                         LOG("Failed to get properties");
428                 }
429                 dbus_message_unref(message);
430                 return NULL;
431         }
432
433         dbus_message_unref(message);
434
435         return reply;
436 }