X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Felement.c;h=873a5f5fc51652ee956c2a201ceccbc815a0f085;hb=4f9a0637340e17790ad3c29546adc34ab6ce0362;hp=6ad75b1be31ecaf94ef54e5acbf9bed4c1235e27;hpb=4b9a69f1d6b579679be9a8190f60eb28fceaf547;p=connman diff --git a/src/element.c b/src/element.c index 6ad75b1..873a5f5 100644 --- a/src/element.c +++ b/src/element.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2009 Intel Corporation. All rights reserved. * * 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 @@ -34,13 +34,12 @@ static DBusConnection *connection; -static GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT; static GNode *element_root = NULL; - static GSList *driver_list = NULL; - static gchar *device_filter = NULL; +static gboolean started = FALSE; + static struct { enum connman_property_id id; int type; @@ -55,6 +54,8 @@ static struct { DBUS_TYPE_STRING, "IPv4.Netmask" }, { CONNMAN_PROPERTY_ID_IPV4_GATEWAY, DBUS_TYPE_STRING, "IPv4.Gateway" }, + { CONNMAN_PROPERTY_ID_IPV4_BROADCAST, + DBUS_TYPE_STRING, "IPv4.Broadcast" }, { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, DBUS_TYPE_STRING, "IPv4.Nameserver" }, @@ -105,6 +106,8 @@ static const char *type2string(enum connman_element_type type) return "network"; case CONNMAN_ELEMENT_TYPE_SERVICE: return "service"; + case CONNMAN_ELEMENT_TYPE_PPP: + return "ppp"; case CONNMAN_ELEMENT_TYPE_IPV4: return "ipv4"; case CONNMAN_ELEMENT_TYPE_IPV6: @@ -115,10 +118,10 @@ static const char *type2string(enum connman_element_type type) return "bootp"; case CONNMAN_ELEMENT_TYPE_ZEROCONF: return "zeroconf"; - case CONNMAN_ELEMENT_TYPE_RESOLVER: - return "resolver"; case CONNMAN_ELEMENT_TYPE_CONNECTION: return "connection"; + case CONNMAN_ELEMENT_TYPE_VENDOR: + return "vendor"; } return NULL; @@ -131,16 +134,14 @@ static const char *subtype2string(enum connman_element_subtype type) return "unknown"; case CONNMAN_ELEMENT_SUBTYPE_FAKE: return "fake"; - case CONNMAN_ELEMENT_SUBTYPE_NETWORK: - return "network"; case CONNMAN_ELEMENT_SUBTYPE_ETHERNET: return "ethernet"; case CONNMAN_ELEMENT_SUBTYPE_WIFI: return "wifi"; case CONNMAN_ELEMENT_SUBTYPE_WIMAX: return "wimax"; - case CONNMAN_ELEMENT_SUBTYPE_MODEM: - return "modem"; + case CONNMAN_ELEMENT_SUBTYPE_CELLULAR: + return "cellular"; case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH: return "bluetooth"; } @@ -153,12 +154,10 @@ const char *__connman_element_policy2string(enum connman_element_policy policy) switch (policy) { case CONNMAN_ELEMENT_POLICY_UNKNOWN: return "unknown"; - case CONNMAN_ELEMENT_POLICY_OFF: - return "off"; - case CONNMAN_ELEMENT_POLICY_AUTO: - return "auto"; case CONNMAN_ELEMENT_POLICY_IGNORE: return "ignore"; + case CONNMAN_ELEMENT_POLICY_AUTO: + return "auto"; case CONNMAN_ELEMENT_POLICY_ASK: return "ask"; } @@ -168,9 +167,7 @@ const char *__connman_element_policy2string(enum connman_element_policy policy) enum connman_element_policy __connman_element_string2policy(const char *policy) { - if (strcasecmp(policy, "off") == 0) - return CONNMAN_ELEMENT_POLICY_OFF; - else if (strcasecmp(policy, "ignore") == 0) + if (strcasecmp(policy, "ignore") == 0) return CONNMAN_ELEMENT_POLICY_IGNORE; else if (strcasecmp(policy, "auto") == 0) return CONNMAN_ELEMENT_POLICY_AUTO; @@ -180,6 +177,34 @@ enum connman_element_policy __connman_element_string2policy(const char *policy) return CONNMAN_ELEMENT_POLICY_UNKNOWN; } +const char *__connman_ipv4_method2string(enum connman_ipv4_method method) +{ + switch (method) { + case CONNMAN_IPV4_METHOD_UNKNOWN: + return "unknown"; + case CONNMAN_IPV4_METHOD_OFF: + return "off"; + case CONNMAN_IPV4_METHOD_STATIC: + return "static"; + case CONNMAN_IPV4_METHOD_DHCP: + return "dhcp"; + } + + return "unknown"; +} + +enum connman_ipv4_method __connman_ipv4_string2method(const char *method) +{ + if (strcasecmp(method, "off") == 0) + return CONNMAN_IPV4_METHOD_OFF; + else if (strcasecmp(method, "static") == 0) + return CONNMAN_IPV4_METHOD_STATIC; + else if (strcasecmp(method, "dhcp") == 0) + return CONNMAN_IPV4_METHOD_DHCP; + else + return CONNMAN_IPV4_METHOD_UNKNOWN; +} + static void append_property(DBusMessageIter *dict, struct connman_property *property) { @@ -253,6 +278,7 @@ static void add_common_properties(struct connman_element *element, __connman_element_unlock(element); } +#if 0 static void set_common_property(struct connman_element *element, const char *name, DBusMessageIter *value) { @@ -287,25 +313,66 @@ static void set_common_property(struct connman_element *element, __connman_element_unlock(element); } +#endif -static DBusMessage *do_update(DBusConnection *conn, - DBusMessage *msg, void *data) +static void emit_element_signal(DBusConnection *conn, const char *member, + struct connman_element *element) { - struct connman_element *element = data; + DBusMessage *signal; - DBG("conn %p", conn); + if (__connman_debug_enabled() == FALSE) + return; - if (element->enabled == FALSE) - return __connman_error_failed(msg); + DBG("conn %p member %s", conn, member); - if (element->driver && element->driver->update) { - DBG("Calling update callback"); - if (element->driver->update(element) < 0) - return __connman_error_failed(msg); + if (element == NULL) + return; + + signal = dbus_message_new_signal(element->path, + CONNMAN_DEBUG_INTERFACE, member); + if (signal == NULL) + return; + + g_dbus_send_message(conn, signal); +} + +static void emit_enabled_signal(DBusConnection *conn, + struct connman_element *element) +{ + DBusMessage *signal; + DBusMessageIter entry, value; + const char *iface, *key; + + DBG("conn %p", conn); + if (element == NULL) + return; + + switch (element->type) { + case CONNMAN_ELEMENT_TYPE_CONNECTION: + iface = CONNMAN_CONNECTION_INTERFACE; + key = "Default"; + break; + default: + return; } - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + signal = dbus_message_new_signal(element->path, + iface, "PropertyChanged"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_BOOLEAN_AS_STRING, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, + &element->enabled); + dbus_message_iter_close_container(&entry, &value); + + g_dbus_send_message(conn, signal); } static DBusMessage *do_enable(DBusConnection *conn, @@ -326,12 +393,7 @@ static DBusMessage *do_enable(DBusConnection *conn, element->enabled = TRUE; -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif + emit_enabled_signal(connection, element); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } @@ -354,48 +416,12 @@ static DBusMessage *do_disable(DBusConnection *conn, element->enabled = FALSE; -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif + emit_enabled_signal(connection, element); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -static void append_networks(struct connman_element *element, - DBusMessageIter *dict) -{ - DBusMessageIter entry, value, iter; - const char *key = "Networks"; - - if (element->subtype != CONNMAN_ELEMENT_SUBTYPE_WIFI && - element->subtype != CONNMAN_ELEMENT_SUBTYPE_WIMAX) - return; - - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, - NULL, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING, - &value); - - dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, - DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - - __connman_element_list(element, CONNMAN_ELEMENT_TYPE_NETWORK, &iter); - - dbus_message_iter_close_container(&value, &iter); - - dbus_message_iter_close_container(&entry, &value); - - dbus_message_iter_close_container(dict, &entry); -} - -static DBusMessage *device_get_properties(DBusConnection *conn, +static DBusMessage *connection_get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; @@ -421,15 +447,17 @@ static DBusMessage *device_get_properties(DBusConnection *conn, connman_dbus_dict_append_variant(&dict, "Type", DBUS_TYPE_STRING, &str); - str = __connman_element_policy2string(element->policy); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Policy", - DBUS_TYPE_STRING, &str); + if (element->devname != NULL) + connman_dbus_dict_append_variant(&dict, "Interface", + DBUS_TYPE_STRING, &element->devname); - connman_dbus_dict_append_variant(&dict, "Powered", - DBUS_TYPE_BOOLEAN, &element->enabled); + if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI || + element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIMAX) + connman_dbus_dict_append_variant(&dict, "Strength", + DBUS_TYPE_BYTE, &element->strength); - append_networks(element, &dict); + connman_dbus_dict_append_variant(&dict, "Default", + DBUS_TYPE_BOOLEAN, &element->enabled); add_common_properties(element, &dict); @@ -438,7 +466,7 @@ static DBusMessage *device_get_properties(DBusConnection *conn, return reply; } -static DBusMessage *device_set_property(DBusConnection *conn, +static DBusMessage *connection_set_property(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; @@ -457,349 +485,78 @@ static DBusMessage *device_set_property(DBusConnection *conn, if (__connman_security_check_privileges(msg) < 0) return __connman_error_permission_denied(msg); - if (g_str_equal(name, "Powered") == TRUE) { - dbus_bool_t powered; + if (g_str_equal(name, "Default") == TRUE) { + dbus_bool_t enabled; - dbus_message_iter_get_basic(&value, &powered); + dbus_message_iter_get_basic(&value, &enabled); - if (powered == TRUE) - do_enable(conn, msg, data); + if (enabled == TRUE) + return do_enable(conn, msg, element); else - do_disable(conn, msg, data); - } else - set_common_property(element, name, &value); - - __connman_element_store(element); - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static int parse_network_dict(DBusMessageIter *iter, const char **ssid, - const char **security, const char **passphrase) -{ - while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter entry, value; - const char *key; - - dbus_message_iter_recurse(iter, &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_STRING: - if (g_str_equal(key, "WiFi.SSID") == TRUE) - dbus_message_iter_get_basic(&value, ssid); - else if (g_str_equal(key, "WiFi.Security") == TRUE) - dbus_message_iter_get_basic(&value, security); - else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) - dbus_message_iter_get_basic(&value, passphrase); - break; - } - - dbus_message_iter_next(iter); + return do_disable(conn, msg, element); } - return 0; -} - -static DBusMessage *device_create_network(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - struct connman_element *network; - DBusMessageIter iter, array; - const char *ssid = NULL, *security = NULL, *passphrase = NULL; - - DBG("conn %p", conn); - - if (dbus_message_iter_init(msg, &iter) == FALSE) - return __connman_error_invalid_arguments(msg); - - dbus_message_iter_recurse(&iter, &array); - parse_network_dict(&array, &ssid, &security, &passphrase); - if (ssid == NULL) - return __connman_error_invalid_arguments(msg); - - DBG("ssid %s security %s passphrase %s", ssid, security, passphrase); - - network = connman_element_create(ssid); - - network->type = CONNMAN_ELEMENT_TYPE_NETWORK; - network->index = element->index; - - connman_element_add_static_property(network, "Name", - DBUS_TYPE_STRING, &ssid); - - connman_element_add_static_array_property(element, "WiFi.SSID", - DBUS_TYPE_BYTE, &ssid, strlen(ssid)); - - network->wifi.security = g_strdup(security); - network->wifi.passphrase = g_strdup(passphrase); - - connman_element_register(network, element); - - return g_dbus_create_reply(msg, DBUS_TYPE_OBJECT_PATH, &network->path, - DBUS_TYPE_INVALID); -} - -static DBusMessage *device_remove_network(DBusConnection *conn, - DBusMessage *msg, void *data) -{ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -static DBusMessage *get_network_properties(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - DBusMessage *reply; - DBusMessageIter array, dict; - const char *str; - - DBG("conn %p", conn); - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &array); - - dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - str = __connman_element_policy2string(element->policy); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Policy", - DBUS_TYPE_STRING, &str); - - connman_dbus_dict_append_variant(&dict, "Connected", - DBUS_TYPE_BOOLEAN, &element->enabled); - - add_common_properties(element, &dict); - - dbus_message_iter_close_container(&array, &dict); - - return reply; -} - -static DBusMessage *set_network_property(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - DBusMessageIter iter; - DBusMessageIter value; - const char *name; - - DBG("conn %p", conn); - - if (dbus_message_iter_init(msg, &iter) == FALSE) - return __connman_error_invalid_arguments(msg); - - dbus_message_iter_get_basic(&iter, &name); - dbus_message_iter_next(&iter); - dbus_message_iter_recurse(&iter, &value); - - if (__connman_security_check_privileges(msg) < 0) - return __connman_error_permission_denied(msg); - - if (g_str_equal(name, "WiFi.Passphrase") == TRUE) { - const char *str; - - dbus_message_iter_get_basic(&value, &str); - g_free(element->wifi.passphrase); - element->wifi.passphrase = g_strdup(str); - } else - set_common_property(element, name, &value); - - __connman_element_store(element); - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static DBusMessage *get_connection_properties(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - DBusMessage *reply; - DBusMessageIter array, dict; - - DBG("conn %p", conn); - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &array); - - dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - add_common_properties(element, &dict); - - dbus_message_iter_close_container(&array, &dict); - - return reply; -} - -#if 0 -static DBusMessage *get_properties(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - DBusMessage *reply; - DBusMessageIter array, dict; - const char *str; - - DBG("conn %p", conn); - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &array); - - dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - if (element->parent != NULL && - element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) { - connman_dbus_dict_append_variant(&dict, "Parent", - DBUS_TYPE_OBJECT_PATH, &element->parent->path); - } - - str = type2string(element->type); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Type", - DBUS_TYPE_STRING, &str); - str = subtype2string(element->subtype); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Subtype", - DBUS_TYPE_STRING, &str); - - connman_dbus_dict_append_variant(&dict, "Enabled", - DBUS_TYPE_BOOLEAN, &element->enabled); - - add_common_properties(element, &dict); +static GDBusMethodTable connection_methods[] = { + { "GetProperties", "", "a{sv}", connection_get_properties }, + { "SetProperty", "sv", "", connection_set_property }, + { }, +}; - dbus_message_iter_close_container(&array, &dict); +static GDBusSignalTable element_signals[] = { + { "PropertyChanged", "sv" }, + { }, +}; - return reply; -} +struct foreach_data { + enum connman_element_type type; + element_cb_t callback; + gpointer user_data; +}; -static DBusMessage *set_property(DBusConnection *conn, - DBusMessage *msg, void *data) +static gboolean foreach_callback(GNode *node, gpointer user_data) { - struct connman_element *element = data; - DBusMessageIter iter; - DBusMessageIter value; - const char *name; - - DBG("conn %p", conn); + struct connman_element *element = node->data; + struct foreach_data *data = user_data; - if (dbus_message_iter_init(msg, &iter) == FALSE) - return __connman_error_invalid_arguments(msg); + DBG("element %p name %s", element, element->name); - dbus_message_iter_get_basic(&iter, &name); - dbus_message_iter_next(&iter); - dbus_message_iter_recurse(&iter, &value); + if (element->type == CONNMAN_ELEMENT_TYPE_ROOT) + return FALSE; - if (__connman_security_check_privileges(msg) < 0) - return __connman_error_permission_denied(msg); + if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN && + data->type != element->type) + return FALSE; - set_common_property(element, name, &value); + if (data->callback) + data->callback(element, data->user_data); - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + return FALSE; } -static DBusMessage *clear_property(DBusConnection *conn, - DBusMessage *msg, void *data) +void __connman_element_foreach(struct connman_element *element, + enum connman_element_type type, + element_cb_t callback, gpointer user_data) { - struct connman_element *element = data; - const char *name; - GSList *list; - - DBG("conn %p", conn); - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID) == FALSE) - return __connman_error_invalid_arguments(msg); - - if (__connman_security_check_privileges(msg) < 0) - return __connman_error_permission_denied(msg); - - __connman_element_lock(element); - - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (g_str_equal(property->name, name) == FALSE) - continue; - - if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC) - continue; - - if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE) - continue; - - property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE; - - if (property->type == DBUS_TYPE_STRING) - g_free(property->value); + struct foreach_data data = { type, callback, user_data }; + GNode *node; - property->value = NULL; - } + DBG(""); - __connman_element_unlock(element); + if (element != NULL) { + node = g_node_find(element_root, G_PRE_ORDER, + G_TRAVERSE_ALL, element); + if (node == NULL) + return; + } else + node = element_root; - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, + foreach_callback, &data); } -static GDBusMethodTable element_methods[] = { - { "GetProperties", "", "a{sv}", get_properties }, - { "SetProperty", "sv", "", set_property }, - { "ClearProperty", "s", "", clear_property }, - { "Update", "", "", do_update }, - { "Enable", "", "", do_enable }, - { "Disable", "", "", do_disable }, - { }, -}; -#endif - -static GDBusSignalTable element_signals[] = { - { "PropertyChanged", "sv" }, - { }, -}; - -static GDBusMethodTable device_methods[] = { - { "GetProperties", "", "a{sv}", device_get_properties }, - { "SetProperty", "sv", "", device_set_property }, - { "CreateNetwork", "a{sv}", "o", device_create_network }, - { "RemoveNetwork", "o", "", device_remove_network }, - { "ProposeScan", "", "", do_update }, - { }, -}; - -static GDBusMethodTable network_methods[] = { - { "GetProperties", "", "a{sv}", get_network_properties }, - { "SetProperty", "sv", "", set_network_property }, - { "Connect", "", "", do_enable }, - { "Disconnect", "", "", do_disable }, - { }, -}; - -static GDBusMethodTable connection_methods[] = { - { "GetProperties", "", "a{sv}", get_connection_properties }, - { }, -}; - struct append_filter { enum connman_element_type type; DBusMessageIter *iter; @@ -820,7 +577,11 @@ static gboolean append_path(GNode *node, gpointer user_data) return FALSE; if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE && - element->subtype == CONNMAN_ELEMENT_SUBTYPE_NETWORK) + __connman_device_has_driver(element->device) == FALSE) + return FALSE; + + if (filter->type == CONNMAN_ELEMENT_TYPE_NETWORK && + __connman_network_has_driver(element->network) == FALSE) return FALSE; dbus_message_iter_append_basic(filter->iter, @@ -846,10 +607,8 @@ void __connman_element_list(struct connman_element *element, } else node = element_root; - g_static_rw_lock_reader_lock(&element_lock); g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, append_path, &filter); - g_static_rw_lock_reader_unlock(&element_lock); } struct count_data { @@ -892,10 +651,8 @@ int __connman_element_count(struct connman_element *element, } else node = element_root; - g_static_rw_lock_reader_lock(&element_lock); g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, count_element, &data); - g_static_rw_lock_reader_unlock(&element_lock); return data.count; } @@ -934,8 +691,10 @@ static void enable_element(struct connman_element *element) return; if (element->driver && element->driver->enable) { - if (element->driver->enable(element) == 0) + if (element->driver->enable(element) == 0) { element->enabled = TRUE; + emit_enabled_signal(connection, element); + } } } @@ -967,13 +726,9 @@ void __connman_driver_rescan(struct connman_driver *driver) if (!driver->probe) return; - g_static_rw_lock_writer_lock(&element_lock); - if (element_root != NULL) g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, probe_driver, driver); - - g_static_rw_lock_writer_unlock(&element_lock); } /** @@ -994,17 +749,16 @@ int connman_driver_register(struct connman_driver *driver) if (!driver->probe) return -EINVAL; - g_static_rw_lock_writer_lock(&element_lock); - driver_list = g_slist_insert_sorted(driver_list, driver, compare_priority); + if (started == FALSE) + return 0; + if (element_root != NULL) g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, probe_driver, driver); - g_static_rw_lock_writer_unlock(&element_lock); - return 0; } @@ -1017,8 +771,10 @@ static void disable_element(struct connman_element *element) return; if (element->driver && element->driver->disable) { - if (element->driver->disable(element) == 0) + if (element->driver->disable(element) == 0) { element->enabled = FALSE; + emit_enabled_signal(connection, element); + } } } @@ -1053,15 +809,11 @@ void connman_driver_unregister(struct connman_driver *driver) { DBG("driver %p name %s", driver, driver->name); - g_static_rw_lock_writer_lock(&element_lock); - driver_list = g_slist_remove(driver_list, driver); if (element_root != NULL) g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, remove_driver, driver); - - g_static_rw_lock_writer_unlock(&element_lock); } /** @@ -1137,6 +889,8 @@ void connman_element_unref(struct connman_element *element) g_atomic_int_get(&element->refcount) - 1); if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) { + if (element->destruct) + element->destruct(element); free_properties(element); g_free(element->ipv4.address); g_free(element->ipv4.netmask); @@ -1144,6 +898,8 @@ void connman_element_unref(struct connman_element *element) g_free(element->ipv4.network); g_free(element->ipv4.broadcast); g_free(element->ipv4.nameserver); + g_free(element->devname); + g_free(element->devpath); g_free(element->path); g_free(element->name); g_free(element); @@ -1189,6 +945,96 @@ int connman_element_add_static_property(struct connman_element *element, return 0; } +static void emit_property_changed(DBusConnection *conn, + struct connman_element *element, + const char *name, int type, const void *data) +{ + DBusMessage *signal; + DBusMessageIter entry, value; + const char *iface, *sig; + + DBG("conn %p", conn); + + switch (element->type) { + case CONNMAN_ELEMENT_TYPE_CONNECTION: + iface = CONNMAN_CONNECTION_INTERFACE; + break; + default: + return; + } + + signal = dbus_message_new_signal(element->path, + iface, "PropertyChanged"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name); + + switch (type) { + case DBUS_TYPE_STRING: + sig = DBUS_TYPE_STRING_AS_STRING; + break; + case DBUS_TYPE_BYTE: + sig = DBUS_TYPE_BYTE_AS_STRING; + break; + default: + sig = DBUS_TYPE_VARIANT_AS_STRING; + break; + } + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + sig, &value); + dbus_message_iter_append_basic(&value, type, data); + dbus_message_iter_close_container(&entry, &value); + + g_dbus_send_message(conn, signal); +} + +int connman_element_set_static_property(struct connman_element *element, + const char *name, int type, const void *value) +{ + GSList *list; + + DBG("element %p name %s", element, element->name); + + if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE) + return -EINVAL; + + __connman_element_lock(element); + + for (list = element->properties; list; list = list->next) { + struct connman_property *property = list->data; + + if (g_str_equal(property->name, name) == FALSE) + continue; + + if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC)) + continue; + + property->type = type; + g_free(property->value); + + switch (type) { + case DBUS_TYPE_STRING: + property->value = g_strdup(*((const char **) value)); + break; + case DBUS_TYPE_BYTE: + property->value = g_try_malloc(1); + if (property->value != NULL) + memcpy(property->value, value, 1); + break; + } + } + + __connman_element_unlock(element); + + emit_property_changed(connection, element, name, type, value); + + return 0; +} + int connman_element_add_static_array_property(struct connman_element *element, const char *name, int type, const void *value, int len) { @@ -1407,6 +1253,12 @@ int connman_element_set_property(struct connman_element *element, element->ipv4.gateway = g_strdup(*((const char **) value)); __connman_element_unlock(element); break; + case CONNMAN_PROPERTY_ID_IPV4_BROADCAST: + __connman_element_lock(element); + g_free(element->ipv4.broadcast); + element->ipv4.broadcast = g_strdup(*((const char **) value)); + __connman_element_unlock(element); + break; case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER: __connman_element_lock(element); g_free(element->ipv4.nameserver); @@ -1429,13 +1281,6 @@ int connman_element_set_property(struct connman_element *element, return -EINVAL; } -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif - return 0; } @@ -1470,6 +1315,14 @@ int connman_element_get_value(struct connman_element *element, *((char **) value) = element->ipv4.gateway; __connman_element_unlock(element); break; + case CONNMAN_PROPERTY_ID_IPV4_BROADCAST: + if (element->ipv4.broadcast == NULL) + return connman_element_get_value(element->parent, + id, value); + __connman_element_lock(element); + *((char **) value) = element->ipv4.broadcast; + __connman_element_unlock(element); + break; case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER: if (element->ipv4.nameserver == NULL) return connman_element_get_value(element->parent, @@ -1594,10 +1447,10 @@ gboolean connman_element_match_static_property(struct connman_element *element, return result; } -static void append_devices(DBusMessageIter *entry) +static void append_connections(DBusMessageIter *entry) { DBusMessageIter value, iter; - const char *key = "Devices"; + const char *key = "Connections"; dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key); @@ -1607,15 +1460,13 @@ static void append_devices(DBusMessageIter *entry) dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - - __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter); - + __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter); dbus_message_iter_close_container(&value, &iter); dbus_message_iter_close_container(entry, &value); } -static void emit_devices_signal(DBusConnection *conn) +static void emit_connections_signal(DBusConnection *conn) { DBusMessage *signal; DBusMessageIter entry; @@ -1629,33 +1480,25 @@ static void emit_devices_signal(DBusConnection *conn) dbus_message_iter_init_append(signal, &entry); - append_devices(&entry); + append_connections(&entry); g_dbus_send_message(conn, signal); } -static void append_connections(DBusMessageIter *entry) +static void append_state(DBusMessageIter *entry, const char *state) { - DBusMessageIter value, iter; - const char *key = "Connections"; + DBusMessageIter value; + const char *key = "State"; dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key); dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING, - &value); - - dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, - DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - - __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter); - - dbus_message_iter_close_container(&value, &iter); - + DBUS_TYPE_STRING_AS_STRING, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state); dbus_message_iter_close_container(entry, &value); } -static void emit_connections_signal(DBusConnection *conn) +static void emit_state_change(DBusConnection *conn, const char *state) { DBusMessage *signal; DBusMessageIter entry; @@ -1669,54 +1512,56 @@ static void emit_connections_signal(DBusConnection *conn) dbus_message_iter_init_append(signal, &entry); - append_connections(&entry); + append_state(&entry, state); g_dbus_send_message(conn, signal); } -static void append_state(DBusMessageIter *entry, const char *state) +static void set_signal_strength(struct connman_element *connection) { - DBusMessageIter value; - const char *key = "State"; - - dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key); - - dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, - DBUS_TYPE_STRING_AS_STRING, &value); + struct connman_element *element = connection; - dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state); + while (element != NULL) { + if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) { + connection->strength = element->strength; + break; + } - dbus_message_iter_close_container(entry, &value); + element = element->parent; + } } -static void emit_state_change(DBusConnection *conn, const char *state) +static void probe_element(struct connman_element *element) { - DBusMessage *signal; - DBusMessageIter entry; + GSList *list; - DBG("conn %p", conn); + DBG("element %p name %s", element, element->name); - signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "PropertyChanged"); - if (signal == NULL) - return; + for (list = driver_list; list; list = list->next) { + struct connman_driver *driver = list->data; - dbus_message_iter_init_append(signal, &entry); + if (match_driver(element, driver) == FALSE) + continue; - append_state(&entry, state); + DBG("driver %p name %s", driver, driver->name); - g_dbus_send_message(conn, signal); + if (driver->probe(element) == 0) { + __connman_element_lock(element); + element->driver = driver; + __connman_element_unlock(element); + + enable_element(element); + break; + } + } } static void register_element(gpointer data, gpointer user_data) { struct connman_element *element = data; const gchar *basepath; - GSList *list; GNode *node; - g_static_rw_lock_writer_lock(&element_lock); - __connman_element_lock(element); if (element->parent) { @@ -1741,39 +1586,8 @@ static void register_element(gpointer data, gpointer user_data) DBG("element %p path %s", element, element->path); - __connman_element_load(element); - g_node_append_data(node, element); -#if 0 - if (g_dbus_register_interface(connection, element->path, - CONNMAN_ELEMENT_INTERFACE, - element_methods, element_signals, - NULL, element, NULL) == FALSE) - connman_error("Failed to register %s element", element->path); -#endif - - if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE && - element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) { - if (g_dbus_register_interface(connection, element->path, - CONNMAN_DEVICE_INTERFACE, - device_methods, element_signals, - NULL, element, NULL) == FALSE) - connman_error("Failed to register %s device", - element->path); - else - emit_devices_signal(connection); - } - - if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) { - if (g_dbus_register_interface(connection, element->path, - CONNMAN_NETWORK_INTERFACE, - network_methods, element_signals, - NULL, element, NULL) == FALSE) - connman_error("Failed to register %s network", - element->path); - } - if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) { if (g_dbus_register_interface(connection, element->path, CONNMAN_CONNECTION_INTERFACE, @@ -1782,43 +1596,18 @@ static void register_element(gpointer data, gpointer user_data) connman_error("Failed to register %s connection", element->path); else { + set_signal_strength(element); emit_connections_signal(connection); emit_state_change(connection, "online"); } } -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementAdded", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif - - g_static_rw_lock_writer_unlock(&element_lock); - - __connman_element_store(element); - - g_static_rw_lock_writer_lock(&element_lock); + emit_element_signal(connection, "ElementAdded", element); - for (list = driver_list; list; list = list->next) { - struct connman_driver *driver = list->data; - - if (match_driver(element, driver) == FALSE) - continue; - - DBG("driver %p name %s", driver, driver->name); - - if (driver->probe(element) == 0) { - __connman_element_lock(element); - element->driver = driver; - __connman_element_unlock(element); - - enable_element(element); - break; - } - } + if (started == FALSE) + return; - g_static_rw_lock_writer_unlock(&element_lock); + probe_element(element); } /** @@ -1836,10 +1625,14 @@ int connman_element_register(struct connman_element *element, { DBG("element %p name %s parent %p", element, element->name, parent); + if (element->devname == NULL) + element->devname = g_strdup(element->name); + if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) { if (g_pattern_match_simple(device_filter, - element->name) == FALSE) { - DBG("ignoring %s device", element->name); + element->devname) == FALSE) { + DBG("ignoring %s [%s] device", element->name, + element->devname); return -EPERM; } } @@ -1876,7 +1669,12 @@ static gboolean remove_element(GNode *node, gpointer user_data) if (element == root) return FALSE; + if (node != NULL) + g_node_unlink(node); + if (element->driver) { + disable_element(element); + if (element->driver->remove) element->driver->remove(element); @@ -1885,42 +1683,20 @@ static gboolean remove_element(GNode *node, gpointer user_data) __connman_element_unlock(element); } - if (node != NULL) { - g_node_unlink(node); + if (node != NULL) g_node_destroy(node); - } - -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementRemoved", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) { - emit_state_change(connection, "offline"); + if (__connman_element_count(NULL, + CONNMAN_ELEMENT_TYPE_CONNECTION) == 0) + emit_state_change(connection, "offline"); emit_connections_signal(connection); g_dbus_unregister_interface(connection, element->path, CONNMAN_CONNECTION_INTERFACE); } - if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) - g_dbus_unregister_interface(connection, element->path, - CONNMAN_NETWORK_INTERFACE); - - if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE && - element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) { - emit_devices_signal(connection); - - g_dbus_unregister_interface(connection, element->path, - CONNMAN_DEVICE_INTERFACE); - } - -#if 0 - g_dbus_unregister_interface(connection, element->path, - CONNMAN_ELEMENT_INTERFACE); -#endif + emit_element_signal(connection, "ElementRemoved", element); connman_element_unref(element); @@ -1933,15 +1709,11 @@ void connman_element_unregister(struct connman_element *element) DBG("element %p name %s", element, element->name); - g_static_rw_lock_writer_lock(&element_lock); - node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element); if (node != NULL) g_node_traverse(node, G_POST_ORDER, G_TRAVERSE_ALL, -1, remove_element, NULL); - - g_static_rw_lock_writer_unlock(&element_lock); } void connman_element_unregister_children(struct connman_element *element) @@ -1950,32 +1722,33 @@ void connman_element_unregister_children(struct connman_element *element) DBG("element %p name %s", element, element->name); - g_static_rw_lock_writer_lock(&element_lock); - node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element); if (node != NULL) g_node_traverse(node, G_POST_ORDER, G_TRAVERSE_ALL, -1, remove_element, element); - - g_static_rw_lock_writer_unlock(&element_lock); } static gboolean update_element(GNode *node, gpointer user_data) { struct connman_element *element = node->data; + struct connman_element *root = user_data; DBG("element %p name %s", element, element->name); if (element->driver && element->driver->update) element->driver->update(element); -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif + if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION && + root->type == CONNMAN_ELEMENT_TYPE_NETWORK) { + if (element->strength != root->strength) { + element->strength = root->strength; + emit_property_changed(connection, element, "Strength", + DBUS_TYPE_BYTE, &element->strength); + } + } + + emit_element_signal(connection, "ElementUpdated", element); return FALSE; } @@ -1986,15 +1759,11 @@ void connman_element_update(struct connman_element *element) DBG("element %p name %s", element, element->name); - g_static_rw_lock_reader_lock(&element_lock); - node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element); if (node != NULL) g_node_traverse(node, G_PRE_ORDER, - G_TRAVERSE_ALL, -1, update_element, NULL); - - g_static_rw_lock_reader_unlock(&element_lock); + G_TRAVERSE_ALL, -1, update_element, element); } int connman_element_set_enabled(struct connman_element *element, @@ -2005,7 +1774,7 @@ int connman_element_set_enabled(struct connman_element *element, element->enabled = enabled; - connman_element_update(element); + emit_enabled_signal(connection, element); return 0; } @@ -2022,8 +1791,6 @@ int __connman_element_init(DBusConnection *conn, const char *device) device_filter = g_strdup(device); - g_static_rw_lock_writer_lock(&element_lock); - element = connman_element_create("root"); element->path = g_strdup("/"); @@ -2033,13 +1800,49 @@ int __connman_element_init(DBusConnection *conn, const char *device) element_root = g_node_new(element); - g_static_rw_lock_writer_unlock(&element_lock); - __connman_device_init(); + __connman_network_init(); + __connman_connection_init(); return 0; } +static gboolean probe_node(GNode *node, gpointer data) +{ + struct connman_element *element = node->data; + + DBG("element %p name %s", element, element->name); + + if (element->type == CONNMAN_ELEMENT_TYPE_ROOT) + return FALSE; + + if (element->driver) + return FALSE; + + probe_element(element); + + return FALSE; +} + +void __connman_element_start(void) +{ + DBG(""); + + g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, + probe_node, NULL); + + started = TRUE; + + __connman_detect_init(); +} + +void __connman_element_stop(void) +{ + DBG(""); + + __connman_detect_cleanup(); +} + static gboolean free_driver(GNode *node, gpointer data) { struct connman_element *element = node->data; @@ -2047,6 +1850,8 @@ static gboolean free_driver(GNode *node, gpointer data) DBG("element %p name %s", element, element->name); if (element->driver) { + disable_element(element); + if (element->driver->remove) element->driver->remove(element); @@ -2074,22 +1879,18 @@ void __connman_element_cleanup(void) { DBG(""); + __connman_connection_cleanup(); + __connman_network_cleanup(); __connman_device_cleanup(); - g_static_rw_lock_writer_lock(&element_lock); g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, free_driver, NULL); - g_static_rw_lock_writer_unlock(&element_lock); - g_static_rw_lock_writer_lock(&element_lock); g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, free_node, NULL); - g_static_rw_lock_writer_unlock(&element_lock); - g_static_rw_lock_writer_lock(&element_lock); g_node_destroy(element_root); element_root = NULL; - g_static_rw_lock_writer_unlock(&element_lock); g_free(device_filter);