blob: b97cfc0195bde64b6664ac3be6b46936f08ef16b [file] [log] [blame]
/*
*
* Connection Manager
*
* Copyright (C) 2011-2014 BMW Car IT GmbH.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <gdbus.h>
#include "session-test.h"
static enum connman_session_state string2state(const char *state)
{
if (g_strcmp0(state, "connected") == 0)
return CONNMAN_SESSION_STATE_CONNECTED;
if (g_strcmp0(state, "online") == 0)
return CONNMAN_SESSION_STATE_ONLINE;
return CONNMAN_SESSION_STATE_DISCONNECTED;
}
static enum connman_session_type string2type(const char *type)
{
if (g_strcmp0(type, "any") == 0)
return CONNMAN_SESSION_TYPE_ANY;
if (g_strcmp0(type, "local") == 0)
return CONNMAN_SESSION_TYPE_LOCAL;
if (g_strcmp0(type, "internet") == 0)
return CONNMAN_SESSION_TYPE_INTERNET;
return CONNMAN_SESSION_TYPE_UNKNOWN;
}
void bearer_info_cleanup(gpointer data, gpointer user_data)
{
struct test_bearer_info *info = data;
g_free(info->name);
g_free(info);
}
static GSList *session_parse_allowed_bearers(DBusMessageIter *iter)
{
struct test_bearer_info *info;
DBusMessageIter array;
GSList *list = NULL;
dbus_message_iter_recurse(iter, &array);
while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
char *bearer = NULL;
dbus_message_iter_get_basic(&array, &bearer);
info = g_try_new0(struct test_bearer_info, 1);
if (!info) {
g_slist_foreach(list, bearer_info_cleanup, NULL);
g_slist_free(list);
return NULL;
}
info->name = g_strdup(bearer);
list = g_slist_append(list, info);
dbus_message_iter_next(&array);
}
return list;
}
static DBusMessage *notify_release(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
struct test_session *session = user_data;
LOG("session %p", session);
if (session->notify)
session->notify(session);
return NULL;
}
static DBusMessage *notify_update(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
struct test_session *session = user_data;
struct test_session_info *info = session->info;
DBusMessageIter iter, array;
GSList *allowed_bearers;
LOG("session %p notify %s", session, session->notify_path);
dbus_message_iter_init(msg, &iter);
dbus_message_iter_recurse(&iter, &array);
while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry, value;
const char *key;
dbus_message_iter_recurse(&array, &entry);
dbus_message_iter_get_basic(&entry, &key);
dbus_message_iter_next(&entry);
dbus_message_iter_recurse(&entry, &value);
switch (dbus_message_iter_get_arg_type(&value)) {
case DBUS_TYPE_ARRAY:
if (g_str_equal(key, "AllowedBearers")) {
allowed_bearers = session_parse_allowed_bearers(&value);
g_slist_foreach(info->allowed_bearers,
bearer_info_cleanup, NULL);
g_slist_free(info->allowed_bearers);
info->allowed_bearers = allowed_bearers;
} else if (g_str_equal(key, "IPv4")) {
/* XXX */
} else if (g_str_equal(key, "IPv6")) {
/* XXX */
} else {
g_assert(FALSE);
return __connman_error_invalid_arguments(msg);
}
break;
case DBUS_TYPE_STRING:
if (g_str_equal(key, "State")) {
const char *val;
dbus_message_iter_get_basic(&value, &val);
info->state = string2state(val);
} else if (g_str_equal(key, "Bearer")) {
const char *val;
dbus_message_iter_get_basic(&value, &val);
if (info->bearer)
g_free(info->bearer);
info->bearer = g_strdup(val);
} else if (g_str_equal(key, "Name")) {
const char *val;
dbus_message_iter_get_basic(&value, &val);
if (info->name)
g_free(info->name);
info->name = g_strdup(val);
} else if (g_str_equal(key, "Interface")) {
const char *val;
dbus_message_iter_get_basic(&value, &val);
if (info->interface)
g_free(info->interface);
info->interface = g_strdup(val);
} else if (g_str_equal(key, "ConnectionType")
) {
const char *val;
dbus_message_iter_get_basic(&value, &val);
info->type = string2type(val);
} else {
g_assert(FALSE);
return __connman_error_invalid_arguments(msg);
}
break;
default:
g_assert(FALSE);
return __connman_error_invalid_arguments(msg);
}
dbus_message_iter_next(&array);
}
if (session->notify)
session->notify(session);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static const GDBusMethodTable notify_methods[] = {
{ GDBUS_METHOD("Release", NULL, NULL, notify_release) },
{ GDBUS_METHOD("Update",
GDBUS_ARGS({ "settings", "a{sv}" }), NULL,
notify_update) },
{ },
};
int session_notify_register(struct test_session *session,
const char *notify_path)
{
if (!g_dbus_register_interface(session->connection, notify_path, CONNMAN_NOTIFICATION_INTERFACE, notify_methods, NULL, NULL, session, NULL)) {
return -EINVAL;
}
return 0;
}
int session_notify_unregister(struct test_session *session,
const char *notify_path)
{
if (!g_dbus_unregister_interface(session->connection, notify_path, CONNMAN_NOTIFICATION_INTERFACE)) {
return -EINVAL;
}
return 0;
}
static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
{
struct test_session_info *info = user_data;
GSList *list;
for (list = info->allowed_bearers;
list; list = list->next) {
struct test_bearer_info *bearer_info = list->data;
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
&bearer_info->name);
}
}
void session_append_settings(DBusMessageIter *dict,
struct test_session_info *info)
{
if (!info->allowed_bearers)
return;
connman_dbus_dict_append_array(dict, "AllowedBearers",
DBUS_TYPE_STRING,
append_allowed_bearers,
info);
}
DBusMessage *session_connect(DBusConnection *connection,
struct test_session *session)
{
DBusMessage *message, *reply;
DBusError error;
message = dbus_message_new_method_call(CONNMAN_SERVICE,
session->session_path,
CONNMAN_SESSION_INTERFACE,
"Connect");
if (!message)
return NULL;
dbus_error_init(&error);
reply = dbus_connection_send_with_reply_and_block(connection,
message, -1, &error);
if (!reply) {
if (dbus_error_is_set(&error)) {
LOG("%s", error.message);
dbus_error_free(&error);
} else {
LOG("Failed to get properties");
}
dbus_message_unref(message);
return NULL;
}
dbus_message_unref(message);
return reply;
}
DBusMessage *session_disconnect(DBusConnection *connection,
struct test_session *session)
{
DBusMessage *message, *reply;
DBusError error;
message = dbus_message_new_method_call(CONNMAN_SERVICE,
session->session_path,
CONNMAN_SESSION_INTERFACE,
"Disconnect");
if (!message)
return NULL;
dbus_error_init(&error);
reply = dbus_connection_send_with_reply_and_block(connection,
message, -1, &error);
if (!reply) {
if (dbus_error_is_set(&error)) {
LOG("%s", error.message);
dbus_error_free(&error);
} else {
LOG("Failed to get properties");
}
dbus_message_unref(message);
return NULL;
}
dbus_message_unref(message);
return reply;
}