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