diff options
-rw-r--r-- | include/element.h | 2 | ||||
-rw-r--r-- | include/network.h | 3 | ||||
-rw-r--r-- | plugins/bluetooth.c | 3 | ||||
-rw-r--r-- | plugins/ethernet.c | 3 | ||||
-rw-r--r-- | plugins/fake.c | 2 | ||||
-rw-r--r-- | plugins/iwmx.c | 3 | ||||
-rw-r--r-- | plugins/ofono.c | 5 | ||||
-rw-r--r-- | plugins/wifi.c | 10 | ||||
-rw-r--r-- | src/device.c | 14 | ||||
-rw-r--r-- | src/element.c | 6 | ||||
-rw-r--r-- | src/network.c | 375 | ||||
-rw-r--r-- | src/service.c | 17 |
12 files changed, 252 insertions, 191 deletions
diff --git a/include/element.h b/include/element.h index 57a76320..3499cdf8 100644 --- a/include/element.h +++ b/include/element.h @@ -42,7 +42,6 @@ extern "C" { enum connman_element_type { CONNMAN_ELEMENT_TYPE_UNKNOWN = 0, CONNMAN_ELEMENT_TYPE_ROOT = 1, - CONNMAN_ELEMENT_TYPE_NETWORK = 4, }; enum connman_element_state { @@ -80,7 +79,6 @@ struct connman_element { union { void *private; - struct connman_network *network; }; GHashTable *properties; diff --git a/include/network.h b/include/network.h index 624e2874..54e71fc2 100644 --- a/include/network.h +++ b/include/network.h @@ -140,6 +140,9 @@ void connman_network_set_data(struct connman_network *network, void *data); void connman_network_update(struct connman_network *network); +int connman_network_register(struct connman_network *network); +void connman_network_unregister(struct connman_network *network); + struct connman_network_driver { const char *name; enum connman_network_type type; diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index ccc5e9bb..d112f876 100644 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -215,6 +215,7 @@ done: dbus_pending_call_unref(call); + connman_network_unregister(network); connman_network_unref(network); } @@ -438,6 +439,8 @@ static void network_properties_reply(DBusPendingCall *call, void *user_data) if (network == NULL) goto done; + connman_network_register(network); + connman_network_set_string(network, "Path", path); connman_network_set_name(network, name); diff --git a/plugins/ethernet.c b/plugins/ethernet.c index 2ccd4989..4829a33b 100644 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c @@ -92,12 +92,15 @@ static void add_network(struct connman_device *device) if (network == NULL) return; + connman_network_register(network); + index = connman_device_get_index(device); connman_network_set_index(network, index); connman_network_set_name(network, "Wired"); if (connman_device_add_network(device, network) < 0) { + connman_network_unregister(network); connman_network_unref(network); return; } diff --git a/plugins/fake.c b/plugins/fake.c index a3aed229..6ec4ba56 100644 --- a/plugins/fake.c +++ b/plugins/fake.c @@ -38,6 +38,8 @@ static void create_network(struct connman_device *device, const char *name) if (network == NULL) return; + connman_network_register(network); + connman_device_add_network(device, network); connman_network_unref(network); } diff --git a/plugins/iwmx.c b/plugins/iwmx.c index 419b3c98..e79c1af9 100644 --- a/plugins/iwmx.c +++ b/plugins/iwmx.c @@ -132,6 +132,7 @@ struct connman_network *__iwmx_cm_network_available( DBG("new network %s", station_name); nw = connman_network_create(station_name, CONNMAN_NETWORK_TYPE_WIMAX); + connman_network_register(nw); connman_network_set_index(nw, connman_device_get_index(dev)); connman_network_set_name(nw, station_name); connman_network_set_blob(nw, "WiMAX.NSP.name", @@ -148,6 +149,7 @@ struct connman_network *__iwmx_cm_network_available( group[3 * cnt + 1] = 0; connman_network_set_group(nw, station_name); if (connman_device_add_network(dev, nw) < 0) { + connman_network_unregister(nw); connman_network_unref(nw); goto error_add; } @@ -255,6 +257,7 @@ static void __iwmx_cm_dev_disconnected(struct wmxsdk *wmxsdk) DBG("disconnected from network %s\n", connman_network_get_identifier(nw)); connman_network_set_connected(nw, FALSE); + connman_network_unregister(nw); connman_network_unref(nw); wmxsdk->nw = NULL; } else diff --git a/plugins/ofono.c b/plugins/ofono.c index 0c234623..1b9264ac 100644 --- a/plugins/ofono.c +++ b/plugins/ofono.c @@ -366,6 +366,7 @@ static void remove_network(gpointer data) { struct network_info *info = data; + connman_network_unregister(info->network); connman_network_unref(info->network); g_free(info); @@ -831,8 +832,11 @@ static int add_network(struct connman_device *device, if (network == NULL) return -ENOMEM; + connman_network_register(network); + info = g_try_new0(struct network_info, 1); if (info == NULL) { + connman_network_unregister(network); connman_network_unref(network); return -ENOMEM; } @@ -903,6 +907,7 @@ static int add_network(struct connman_device *device, return 0; error: + connman_network_unregister(network); connman_network_unref(network); g_hash_table_remove(network_hash, hash_path); return -EIO; diff --git a/plugins/wifi.c b/plugins/wifi.c index e3849ce4..b30af226 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -783,6 +783,8 @@ static void network_added(GSupplicantNetwork *supplicant_network) if (network == NULL) return; + connman_network_register(network); + connman_network_set_index(network, wifi->index); if (connman_device_add_network(wifi->device, network) < 0) { @@ -812,6 +814,7 @@ static void network_removed(GSupplicantNetwork *network) GSupplicantInterface *interface; struct wifi_data *wifi; const char *name, *identifier; + struct connman_network *connman_network; interface = g_supplicant_network_get_interface(network); wifi = g_supplicant_interface_get_data(interface); @@ -820,8 +823,13 @@ static void network_removed(GSupplicantNetwork *network) DBG("name %s", name); - if (wifi != NULL) + if (wifi != NULL) { + connman_network = connman_device_get_network(wifi->device, identifier); + if (connman_network != NULL) + connman_network_unregister(connman_network); + connman_device_remove_network(wifi->device, identifier); + } } static void debug(const char *str) diff --git a/src/device.c b/src/device.c index 48be10fa..a3401dac 100644 --- a/src/device.c +++ b/src/device.c @@ -424,10 +424,9 @@ static void unregister_network(gpointer data) DBG("network %p", network); - connman_element_unregister((struct connman_element *) network); - __connman_network_set_device(network, NULL); + connman_network_unregister(network); connman_network_unref(network); } @@ -1067,7 +1066,6 @@ int connman_device_add_network(struct connman_device *device, struct connman_network *network) { const char *identifier = connman_network_get_identifier(network); - int err; DBG("device %p network %p", device, network); @@ -1076,13 +1074,6 @@ int connman_device_add_network(struct connman_device *device, __connman_network_set_device(network, device); - err = connman_element_register((struct connman_element *) network, - NULL); - if (err < 0) { - __connman_network_set_device(network, NULL); - return err; - } - g_hash_table_insert(device->networks, g_strdup(identifier), network); @@ -1122,7 +1113,8 @@ int connman_device_remove_network(struct connman_device *device, if (network == NULL) return 0; - connman_element_unregister((struct connman_element *) network); + __connman_network_set_device(network, NULL); + g_hash_table_remove(device->networks, identifier); return 0; diff --git a/src/element.c b/src/element.c index a9a643bb..75d51263 100644 --- a/src/element.c +++ b/src/element.c @@ -46,8 +46,6 @@ static const char *type2string(enum connman_element_type type) return "unknown"; case CONNMAN_ELEMENT_TYPE_ROOT: return "root"; - case CONNMAN_ELEMENT_TYPE_NETWORK: - return "network"; } return NULL; @@ -119,10 +117,6 @@ static gboolean append_path(GNode *node, gpointer user_data) filter->type != element->type) 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, DBUS_TYPE_OBJECT_PATH, &element->path); diff --git a/src/network.c b/src/network.c index cafacd3e..88b8ad82 100644 --- a/src/network.c +++ b/src/network.c @@ -28,10 +28,12 @@ #include "connman.h" +static GSList *network_list = NULL; +static GSList *driver_list = NULL; static unsigned int hidden_counter = 0; struct connman_network { - struct connman_element element; + gint refcount; enum connman_network_type type; connman_bool_t available; connman_bool_t connected; @@ -44,6 +46,7 @@ struct connman_network { char *node; char *group; char *path; + int index; struct connman_network_driver *driver; void *driver_data; @@ -71,6 +74,11 @@ struct connman_network { connman_bool_t use_wps; char *pin_wps; } wifi; + + struct { + char *nsp_name; + int nsp_name_len; + } wimax; }; static const char *type2string(enum connman_network_type type) @@ -103,7 +111,166 @@ connman_bool_t __connman_network_has_driver(struct connman_network *network) return TRUE; } -static GSList *driver_list = NULL; +static gboolean match_driver(struct connman_network *network, + struct connman_network_driver *driver) +{ + if (network->type == driver->type || + driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN) + return TRUE; + + return FALSE; +} + +static int network_probe(struct connman_network *network) +{ + GSList *list; + struct connman_network_driver *driver = NULL; + + DBG("network %p name %s", network, network->name); + + if (network->driver != NULL) + return -EALREADY; + + for (list = driver_list; list; list = list->next) { + driver = list->data; + + if (match_driver(network, driver) == FALSE) + continue; + + DBG("driver %p name %s", driver, driver->name); + + if (driver->probe(network) == 0) + break; + + driver = NULL; + } + + if (driver == NULL) + return -ENODEV; + + if (network->group == NULL) + return -EINVAL; + + switch (network->type) { + case CONNMAN_NETWORK_TYPE_UNKNOWN: + case CONNMAN_NETWORK_TYPE_VENDOR: + return 0; + case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: + case CONNMAN_NETWORK_TYPE_CELLULAR: + case CONNMAN_NETWORK_TYPE_WIFI: + case CONNMAN_NETWORK_TYPE_WIMAX: + if (__connman_service_create_from_network(network) == NULL) + return -EINVAL; + } + + network->driver = driver; + + return 0; +} + +static void network_remove(struct connman_network *network) +{ + DBG("network %p name %s", network, network->name); + + if (network->driver == NULL) + return; + + switch (network->type) { + case CONNMAN_NETWORK_TYPE_UNKNOWN: + case CONNMAN_NETWORK_TYPE_VENDOR: + break; + case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: + case CONNMAN_NETWORK_TYPE_CELLULAR: + case CONNMAN_NETWORK_TYPE_WIFI: + case CONNMAN_NETWORK_TYPE_WIMAX: + if (network->group != NULL) { + __connman_service_remove_from_network(network); + + g_free(network->group); + network->group = NULL; + } + break; + } + + if (network->driver->remove) + network->driver->remove(network); + + network->driver = NULL; +} + +static void network_change(struct connman_network *network) +{ + DBG("network %p name %s", network, network->name); + + if (network->connected == FALSE) + return; + + connman_network_unref(network); + + connman_device_set_disconnected(network->device, TRUE); + + if (network->driver && network->driver->disconnect) { + network->driver->disconnect(network); + return; + } + + network->connected = FALSE; +} + +static void probe_driver(struct connman_network_driver *driver) +{ + GSList *list; + + DBG("driver %p name %s", driver, driver->name); + + for (list = network_list; list != NULL; list = list->next) { + struct connman_network *network = list->data; + + if (network->driver != NULL) + continue; + + if (driver->type != network->type) + continue; + + if (driver->probe(network) < 0) + continue; + + network->driver = driver; + } +} + +int connman_network_register(struct connman_network *network) +{ + network_list = g_slist_append(network_list, network); + + return network_probe(network); +} + + +void connman_network_unregister(struct connman_network *network) +{ + network_list = g_slist_remove(network_list, network); + + network_remove(network); +} + +static void remove_driver(struct connman_network_driver *driver) +{ + GSList *list; + + DBG("driver %p name %s", driver, driver->name); + + for (list = network_list; list != NULL; list = list->next) { + struct connman_network *network = list->data; + + if (network->driver == driver) + network_remove(network); + } +} static gint compare_priority(gconstpointer a, gconstpointer b) { @@ -138,6 +305,8 @@ int connman_network_driver_register(struct connman_network_driver *driver) driver_list = g_slist_insert_sorted(driver_list, driver, compare_priority); + probe_driver(driver); + return 0; } @@ -152,13 +321,13 @@ void connman_network_driver_unregister(struct connman_network_driver *driver) DBG("driver %p name %s", driver, driver->name); driver_list = g_slist_remove(driver_list, driver); + + remove_driver(driver); } -static void network_destruct(struct connman_element *element) +static void network_destruct(struct connman_network *network) { - struct connman_network *network = element->network; - - DBG("element %p name %s", element, element->name); + DBG("network %p name %s", network, network->name); g_free(network->wifi.ssid); g_free(network->wifi.mode); @@ -178,8 +347,11 @@ static void network_destruct(struct connman_element *element) g_free(network->node); g_free(network->name); g_free(network->identifier); + g_free(network->path); network->device = NULL; + + g_free(network); } /** @@ -194,7 +366,6 @@ struct connman_network *connman_network_create(const char *identifier, enum connman_network_type type) { struct connman_network *network; - connman_uint8_t strength = 0; char *temp; DBG("identifier %s type %d", identifier, type); @@ -205,7 +376,7 @@ struct connman_network *connman_network_create(const char *identifier, DBG("network %p", network); - __connman_element_initialize(&network->element); + network->refcount = 1; if (identifier == NULL) { temp = g_strdup_printf("hidden_%d", hidden_counter++); @@ -218,14 +389,6 @@ struct connman_network *connman_network_create(const char *identifier, return NULL; } - network->element.name = temp; - network->element.type = CONNMAN_ELEMENT_TYPE_NETWORK; - - network->element.network = network; - network->element.destruct = network_destruct; - - connman_element_set_uint8(&network->element, "Strength", strength); - network->type = type; network->identifier = g_strdup(temp); @@ -240,8 +403,10 @@ struct connman_network *connman_network_create(const char *identifier, */ struct connman_network *connman_network_ref(struct connman_network *network) { - if (connman_element_ref(&network->element) == NULL) - return NULL; + DBG("network %p name %s refcount %d", network, network->name, + g_atomic_int_get(&network->refcount) + 1); + + g_atomic_int_inc(&network->refcount); return network; } @@ -254,7 +419,13 @@ struct connman_network *connman_network_ref(struct connman_network *network) */ void connman_network_unref(struct connman_network *network) { - connman_element_unref(&network->element); + DBG("network %p name %s refcount %d", network, network->name, + g_atomic_int_get(&network->refcount) - 1); + + if (g_atomic_int_dec_and_test(&network->refcount) == FALSE) + return; + + network_destruct(network); } const char *__connman_network_get_type(struct connman_network *network) @@ -302,10 +473,10 @@ void connman_network_set_index(struct connman_network *network, int index) ipconfig = __connman_service_get_ip4config(service); - DBG("index %d service %p ip4config %p", network->element.index, + DBG("index %d service %p ip4config %p", network->index, service, ipconfig); - if (network->element.index < 0 && ipconfig == NULL) { + if (network->index < 0 && ipconfig == NULL) { ipconfig = __connman_service_get_ip4config(service); if (ipconfig == NULL) @@ -327,7 +498,7 @@ void connman_network_set_index(struct connman_network *network, int index) } done: - network->element.index = index; + network->index = index; } /** @@ -338,19 +509,7 @@ done: */ int connman_network_get_index(struct connman_network *network) { - return network->element.index; -} - -/** - * connman_network_get_element: - * @network: network structure - * - * Get connman_element of network - */ -struct connman_element *connman_network_get_element( - struct connman_network *network) -{ - return &network->element; + return network->index; } /** @@ -391,7 +550,7 @@ void connman_network_set_group(struct connman_network *network, network->group = g_strdup(group); if (network->group != NULL) - __connman_service_create_from_network(network); + network_probe(network); } /** @@ -609,6 +768,8 @@ void connman_network_set_error(struct connman_network *network, set_connect_error(network); break; } + + network_change(network); } void connman_network_clear_error(struct connman_network *network) @@ -906,8 +1067,6 @@ static gboolean set_connected(gpointer user_data) } else { struct connman_service *service; - connman_element_unregister_children(&network->element); - __connman_device_set_network(network->device, NULL); network->hidden = FALSE; @@ -1289,7 +1448,7 @@ int connman_network_set_name(struct connman_network *network, g_free(network->name); network->name = g_strdup(name); - return connman_element_set_string(&network->element, "Name", name); + return 0; } /** @@ -1567,7 +1726,16 @@ const void *connman_network_get_blob(struct connman_network *network, void __connman_network_set_device(struct connman_network *network, struct connman_device *device) { + if (network->device == device) + return; + + if (network->device != NULL) + network_remove(network); + network->device = device; + + if (network->device != NULL) + network_probe(network); } /** @@ -1621,143 +1789,16 @@ void connman_network_update(struct connman_network *network) if (network->group != NULL) __connman_service_update_from_network(network); - - return; } -static gboolean match_driver(struct connman_network *network, - struct connman_network_driver *driver) -{ - if (network->type == driver->type || - driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN) - return TRUE; - - return FALSE; -} - -static int network_probe(struct connman_element *element) -{ - struct connman_network *network = element->network; - GSList *list; - - DBG("element %p name %s", element, element->name); - - if (network == NULL) - return -ENODEV; - - for (list = driver_list; list; list = list->next) { - struct connman_network_driver *driver = list->data; - - if (match_driver(network, driver) == FALSE) - continue; - - DBG("driver %p name %s", driver, driver->name); - - if (driver->probe(network) == 0) { - network->driver = driver; - break; - } - } - - if (network->driver == NULL) - return -ENODEV; - - switch (network->type) { - case CONNMAN_NETWORK_TYPE_UNKNOWN: - case CONNMAN_NETWORK_TYPE_VENDOR: - break; - case CONNMAN_NETWORK_TYPE_ETHERNET: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_CELLULAR: - case CONNMAN_NETWORK_TYPE_WIFI: - case CONNMAN_NETWORK_TYPE_WIMAX: - if (network->group != NULL && - __connman_service_create_from_network(network) == NULL) - return -EINVAL; - } - - return 0; -} - -static void network_remove(struct connman_element *element) -{ - struct connman_network *network = element->network; - - DBG("element %p name %s", element, element->name); - - if (network == NULL) - return; - - if (network->driver == NULL) - return; - - switch (network->type) { - case CONNMAN_NETWORK_TYPE_UNKNOWN: - case CONNMAN_NETWORK_TYPE_VENDOR: - break; - case CONNMAN_NETWORK_TYPE_ETHERNET: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_CELLULAR: - case CONNMAN_NETWORK_TYPE_WIFI: - case CONNMAN_NETWORK_TYPE_WIMAX: - if (network->group != NULL) { - __connman_service_remove_from_network(network); - - g_free(network->group); - network->group = NULL; - } - break; - } - - if (network->driver->remove) - network->driver->remove(network); -} - -static void network_change(struct connman_element *element) -{ - struct connman_network *network = element->network; - - DBG("element %p name %s", element, element->name); - - if (element->state != CONNMAN_ELEMENT_STATE_ERROR) - return; - - if (network->connected == FALSE) - return; - - connman_element_unregister_children(element); - - connman_device_set_disconnected(network->device, TRUE); - - if (network->driver && network->driver->disconnect) { - network->driver->disconnect(network); - return; - } - - network->connected = FALSE; -} - -static struct connman_driver network_driver = { - .name = "network", - .type = CONNMAN_ELEMENT_TYPE_NETWORK, - .priority = CONNMAN_DRIVER_PRIORITY_LOW, - .probe = network_probe, - .remove = network_remove, - .change = network_change, -}; - int __connman_network_init(void) { DBG(""); - return connman_driver_register(&network_driver); + return 0; } void __connman_network_cleanup(void) { DBG(""); - - connman_driver_unregister(&network_driver); } diff --git a/src/service.c b/src/service.c index 89c751a2..9a3d54ec 100644 --- a/src/service.c +++ b/src/service.c @@ -75,6 +75,7 @@ struct connman_service { char *profile; connman_bool_t roaming; connman_bool_t login_required; + connman_bool_t network_created; struct connman_ipconfig *ipconfig_ipv4; struct connman_ipconfig *ipconfig_ipv6; struct connman_network *network; @@ -2922,8 +2923,11 @@ static void service_free(gpointer user_data) g_hash_table_destroy(service->counter_table); - if (service->network != NULL) + if (service->network != NULL) { + if (service->network_created == TRUE) + connman_network_unregister(service->network); connman_network_unref(service->network); + } if (service->provider != NULL) connman_provider_unref(service->provider); @@ -3014,6 +3018,8 @@ static void service_initialize(struct connman_service *service) service->refcount = 1; service->session_usage_count = 0; + service->network_created = FALSE; + service->type = CONNMAN_SERVICE_TYPE_UNKNOWN; service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN; @@ -4041,6 +4047,8 @@ static struct connman_network *create_hidden_wifi(struct connman_device *device, if (network == NULL) return NULL; + connman_network_register(network); + connman_network_set_blob(network, "WiFi.SSID", (unsigned char *) ssid, ssid_len); @@ -4049,6 +4057,7 @@ static struct connman_network *create_hidden_wifi(struct connman_device *device, name = g_try_malloc0(ssid_len + 1); if (name == NULL) { + connman_network_unregister(network); connman_network_unref(network); return NULL; } @@ -4068,6 +4077,7 @@ static struct connman_network *create_hidden_wifi(struct connman_device *device, connman_network_set_index(network, index); if (connman_device_add_network(device, network) < 0) { + connman_network_unregister(network); connman_network_unref(network); return NULL; } @@ -4088,7 +4098,6 @@ int __connman_service_create_and_connect(DBusMessage *msg) unsigned int ssid_len = 0; const char *ident; char *name, *group; - gboolean created = FALSE; int err; dbus_message_iter_init(msg, &iter); @@ -4176,7 +4185,7 @@ int __connman_service_create_and_connect(DBusMessage *msg) network = create_hidden_wifi(device, ssid, mode, security); if (network != NULL) { connman_network_set_group(network, group); - created = TRUE; + service->network_created = TRUE; } service = lookup_by_identifier(name); @@ -4220,7 +4229,7 @@ done: return 0; failed: - if (service != NULL && created == TRUE) { + if (service != NULL && service->network_created == TRUE) { struct connman_network *network = service->network; if (network != NULL) { |