X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fservice.c;h=14f14c5089caf6631ecb3d0bb5bb014d17541f16;hb=016c1490e180fa737815bf65f96cc60b1761ed89;hp=a7087be4f6447e731f0913bf9dac5552fe76f840;hpb=9344d99693c02b44732883ee1e4451552f6ab4b9;p=platform%2Fupstream%2Fconnman.git diff --git a/src/service.c b/src/service.c index a7087be..14f14c5 100644 --- a/src/service.c +++ b/src/service.c @@ -23,6 +23,8 @@ #include #endif +#include +#include #include #include "connman.h" @@ -44,6 +46,7 @@ struct connman_service { connman_uint8_t strength; connman_bool_t favorite; connman_bool_t hidden; + connman_bool_t ignore; GTimeVal modified; unsigned int order; char *name; @@ -184,10 +187,12 @@ static const char *error2string(enum connman_service_error error) switch (error) { case CONNMAN_SERVICE_ERROR_UNKNOWN: break; - case CONNMAN_SERVICE_ERROR_DHCP_FAILED: - return "dhcp-failed"; case CONNMAN_SERVICE_ERROR_PIN_MISSING: return "pin-missing"; + case CONNMAN_SERVICE_ERROR_DHCP_FAILED: + return "dhcp-failed"; + case CONNMAN_SERVICE_ERROR_CONNECT_FAILED: + return "connect-failed"; } return NULL; @@ -417,16 +422,122 @@ static DBusMessage *clear_property(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } +static connman_bool_t is_connecting(struct connman_service *service) +{ + switch (service->state) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + case CONNMAN_SERVICE_STATE_IDLE: + case CONNMAN_SERVICE_STATE_CARRIER: + case CONNMAN_SERVICE_STATE_FAILURE: + case CONNMAN_SERVICE_STATE_DISCONNECT: + case CONNMAN_SERVICE_STATE_READY: + break; + case CONNMAN_SERVICE_STATE_ASSOCIATION: + case CONNMAN_SERVICE_STATE_CONFIGURATION: + return TRUE; + } + + return FALSE; +} + +static struct connman_service *find_pending_service(void) +{ + struct connman_service *service; + GSequenceIter *iter; + + iter = g_sequence_get_begin_iter(service_list); + + while (g_sequence_iter_is_end(iter) == FALSE) { + service = g_sequence_get(iter); + if (service->pending != NULL) + return service; + + iter = g_sequence_iter_next(iter); + } + + return NULL; +} + +static connman_bool_t is_ignore(struct connman_service *service) +{ + if (service->ignore == TRUE) + return TRUE; + + if (service->state == CONNMAN_SERVICE_STATE_FAILURE) + return TRUE; + + return FALSE; +} + +static void __connman_service_auto_connect(void) +{ + struct connman_service *service; + GSequenceIter *iter; + + DBG(""); + + service = find_pending_service(); + if (service != NULL) + return; + + iter = g_sequence_get_begin_iter(service_list); + if (g_sequence_iter_is_end(iter) == TRUE) + return; + + service = g_sequence_get(iter); + + while (is_ignore(service) == TRUE) { + iter = g_sequence_iter_next(iter); + if (g_sequence_iter_is_end(iter)) + return; + service = g_sequence_get(iter); + } + + if (service->favorite == FALSE) + return; + + if (service->state == CONNMAN_SERVICE_STATE_READY) + return; + + if (is_connecting(service) == TRUE) + return; + + if (service->state == CONNMAN_SERVICE_STATE_IDLE) + __connman_service_connect(service); +} + static gboolean connect_timeout(gpointer user_data) { struct connman_service *service = user_data; + connman_bool_t auto_connect = FALSE; DBG("service %p", service); service->timeout = 0; - if (service->network != NULL) + if (service->network != NULL) { + connman_bool_t connected; + + connected = connman_network_get_connected(service->network); + if (connected == TRUE) { + __connman_service_indicate_state(service, + CONNMAN_SERVICE_STATE_READY); + return FALSE; + } + __connman_network_disconnect(service->network); + } else if (service->device != NULL) { + connman_bool_t disconnected; + + disconnected = connman_device_get_disconnected(service->device); + if (disconnected == FALSE) { + __connman_service_indicate_state(service, + CONNMAN_SERVICE_STATE_READY); + return FALSE; + } + + __connman_device_disconnect(service->device); + } if (service->pending != NULL) { DBusMessage *reply; @@ -437,10 +548,14 @@ static gboolean connect_timeout(gpointer user_data) dbus_message_unref(service->pending); service->pending = NULL; + } else + auto_connect = TRUE; - __connman_service_indicate_state(service, + __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_FAILURE); - } + + if (auto_connect == TRUE) + __connman_service_auto_connect(); return FALSE; } @@ -456,6 +571,8 @@ static DBusMessage *connect_service(DBusConnection *conn, if (service->pending != NULL) return __connman_error_in_progress(msg); + service->ignore = FALSE; + service->pending = dbus_message_ref(msg); err = __connman_service_connect(service); @@ -497,6 +614,8 @@ static DBusMessage *disconnect_service(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } + service->ignore = TRUE; + err = __connman_service_disconnect(service); if (err < 0) { if (err != -EINPROGRESS) @@ -561,14 +680,11 @@ static DBusMessage *move_before(DBusConnection *conn, src = g_hash_table_lookup(service_hash, service->identifier); dst = g_hash_table_lookup(service_hash, target->identifier); -#if 0 g_sequence_move(src, dst); __connman_profile_changed(); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -#endif - return __connman_error_not_implemented(msg); } static DBusMessage *move_after(DBusConnection *conn, @@ -692,6 +808,8 @@ static void __connman_service_initialize(struct connman_service *service) service->favorite = FALSE; service->hidden = FALSE; + service->ignore = FALSE; + service->order = 0; } @@ -950,9 +1068,11 @@ int __connman_service_connect(struct connman_service *service) return -EISCONN; if (service->network != NULL) { - if (service->hidden == TRUE) - return -EINVAL; + unsigned int ssid_len; + if (connman_network_get_blob(service->network, "WiFi.SSID", + &ssid_len) == NULL) + return -EINVAL; connman_network_set_string(service->network, "WiFi.Passphrase", service->passphrase); @@ -1174,6 +1294,9 @@ struct connman_service *__connman_service_create_from_device(struct connman_devi service_register(service); + if (service->favorite == TRUE) + __connman_service_auto_connect(); + done: g_free(name); @@ -1196,7 +1319,7 @@ struct connman_service *__connman_service_lookup_from_network(struct connman_net if (ident == NULL) return NULL; - group = __connman_network_get_group(network); + group = connman_network_get_group(network); if (group == NULL) return NULL; @@ -1212,6 +1335,20 @@ struct connman_service *__connman_service_lookup_from_network(struct connman_net unsigned int __connman_service_get_order(struct connman_service *service) { + GSequenceIter *iter; + + if (service == NULL) + return 0; + + if (service->favorite == FALSE) + return 0; + + iter = g_hash_table_lookup(service_hash, service->identifier); + if (iter != NULL) { + if (g_sequence_iter_get_position(iter) == 0) + return 1; + } + return service->order; } @@ -1224,8 +1361,10 @@ static enum connman_service_type convert_network_type(struct connman_network *ne case CONNMAN_NETWORK_TYPE_VENDOR: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_HSO: break; + case CONNMAN_NETWORK_TYPE_MBM: + case CONNMAN_NETWORK_TYPE_HSO: + return CONNMAN_SERVICE_TYPE_CELLULAR; case CONNMAN_NETWORK_TYPE_WIFI: return CONNMAN_SERVICE_TYPE_WIFI; case CONNMAN_NETWORK_TYPE_WIMAX: @@ -1270,6 +1409,12 @@ static void update_from_network(struct connman_service *service, GSequenceIter *iter; const char *str; + if (service->state == CONNMAN_SERVICE_STATE_READY) + return; + + if (is_connecting(service) == TRUE) + return; + str = connman_network_get_string(network, "Name"); if (str != NULL) { g_free(service->name); @@ -1333,7 +1478,7 @@ struct connman_service *__connman_service_create_from_network(struct connman_net if (ident == NULL) return NULL; - group = __connman_network_get_group(network); + group = connman_network_get_group(network); if (group == NULL) return NULL; @@ -1362,6 +1507,9 @@ struct connman_service *__connman_service_create_from_network(struct connman_net service_register(service); + if (service->favorite == TRUE) + __connman_service_auto_connect(); + done: g_free(name); @@ -1374,6 +1522,8 @@ static int service_load(struct connman_service *service) gchar *pathname, *data = NULL; gsize length; gchar *str; + unsigned int ssid_len; + int err = 0; DBG("service %p", service); @@ -1406,6 +1556,55 @@ static int service_load(struct connman_service *service) case CONNMAN_SERVICE_TYPE_ETHERNET: break; case CONNMAN_SERVICE_TYPE_WIFI: + if (service->name == NULL) { + gchar *name; + + name = g_key_file_get_string(keyfile, + service->identifier, "Name", NULL); + if (name != NULL) { + g_free(service->name); + service->name = name; + } + + if (service->network != NULL) + connman_network_set_name(service->network, + name); + } + + if (service->network && + connman_network_get_blob(service->network, + "WiFi.SSID", &ssid_len) == NULL) { + gchar *hex_ssid; + + hex_ssid = g_key_file_get_string(keyfile, + service->identifier, + "SSID", NULL); + + if (hex_ssid != NULL) { + gchar *ssid; + unsigned int i, j = 0, hex; + size_t hex_ssid_len = strlen(hex_ssid); + + ssid = g_try_malloc0(hex_ssid_len / 2); + if (ssid == NULL) { + g_free(hex_ssid); + err = -ENOMEM; + goto done; + } + + for (i = 0; i < hex_ssid_len; i += 2) { + sscanf(hex_ssid + i, "%02x", &hex); + ssid[j++] = hex; + } + + connman_network_set_blob(service->network, + "WiFi.SSID", ssid, hex_ssid_len / 2); + } + + g_free(hex_ssid); + } + /* fall through */ + case CONNMAN_SERVICE_TYPE_WIMAX: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: @@ -1438,9 +1637,10 @@ static int service_load(struct connman_service *service) __connman_ipconfig_load(service->ipconfig, keyfile, service->identifier, "IPv4."); +done: g_key_file_free(keyfile); - return 0; + return err; } static int service_save(struct connman_service *service) @@ -1449,6 +1649,7 @@ static int service_save(struct connman_service *service) gchar *pathname, *data = NULL; gsize length; gchar *str; + int err = 0; DBG("service %p", service); @@ -1482,6 +1683,36 @@ update: case CONNMAN_SERVICE_TYPE_ETHERNET: break; case CONNMAN_SERVICE_TYPE_WIFI: + if (service->network) { + const unsigned char *ssid; + unsigned int ssid_len = 0; + + ssid = connman_network_get_blob(service->network, + "WiFi.SSID", &ssid_len); + + if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') { + char *identifier = service->identifier; + GString *str; + unsigned int i; + + str = g_string_sized_new(ssid_len * 2); + if (str == NULL) { + err = -ENOMEM; + goto done; + } + + for (i = 0; i < ssid_len; i++) + g_string_append_printf(str, + "%02x", ssid[i]); + + g_key_file_set_string(keyfile, identifier, + "SSID", str->str); + + g_string_free(str, TRUE); + } + } + /* fall through */ + case CONNMAN_SERVICE_TYPE_WIMAX: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: @@ -1530,7 +1761,7 @@ done: g_free(pathname); - return 0; + return err; } static struct connman_storage service_storage = {