summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@nokia.com>2011-02-10 17:52:13 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2011-02-11 12:25:46 +0100
commit84c2a9510cb6606dcdceea55b8250e96954bfe96 (patch)
treec1b1564cba2058cfef4587fedde07461b23f7a80 /src
parent007958cb11632a70bdd974dd53aa497f35eea531 (diff)
downloadconnman-84c2a9510cb6606dcdceea55b8250e96954bfe96.tar.gz
connman-84c2a9510cb6606dcdceea55b8250e96954bfe96.tar.bz2
connman-84c2a9510cb6606dcdceea55b8250e96954bfe96.zip
service: Split service state to IPv4 and IPv6 parts
Diffstat (limited to 'src')
-rw-r--r--src/connection.c6
-rw-r--r--src/connman.h3
-rw-r--r--src/location.c3
-rw-r--r--src/network.c24
-rw-r--r--src/provider.c27
-rw-r--r--src/service.c312
6 files changed, 303 insertions, 72 deletions
diff --git a/src/connection.c b/src/connection.c
index 789a242f..7e517fa7 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -332,7 +332,8 @@ static int connection_probe(struct connman_element *element)
new_gateway->ipv4_gateway);
__connman_service_set_domainname(service, domainname);
- __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
+ __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
if (service == NULL) {
new_gateway->vpn = TRUE;
@@ -376,7 +377,8 @@ static void connection_remove(struct connman_element *element)
service = __connman_element_get_service(element);
__connman_service_nameserver_del_routes(service);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_DISCONNECT);
+ CONNMAN_SERVICE_STATE_DISCONNECT,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
connman_element_set_enabled(element, FALSE);
diff --git a/src/connman.h b/src/connman.h
index 7f18ff4f..6202db31 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -478,7 +478,8 @@ int __connman_service_set_immutable(struct connman_service *service,
void __connman_service_set_string(struct connman_service *service,
const char *key, const char *value);
int __connman_service_indicate_state(struct connman_service *service,
- enum connman_service_state state);
+ enum connman_service_state new_state,
+ enum connman_ipconfig_type type);
int __connman_service_indicate_error(struct connman_service *service,
enum connman_service_error error);
int __connman_service_clear_error(struct connman_service *service);
diff --git a/src/location.c b/src/location.c
index 820011f2..ccfb2ed3 100644
--- a/src/location.c
+++ b/src/location.c
@@ -191,7 +191,8 @@ void connman_location_report_result(struct connman_location *location,
break;
case CONNMAN_LOCATION_RESULT_ONLINE:
__connman_service_indicate_state(location->service,
- CONNMAN_SERVICE_STATE_ONLINE);
+ CONNMAN_SERVICE_STATE_ONLINE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
break;
}
}
diff --git a/src/network.c b/src/network.c
index 09d4d2b9..c3febd3d 100644
--- a/src/network.c
+++ b/src/network.c
@@ -501,7 +501,8 @@ int connman_network_set_associating(struct connman_network *network,
service = __connman_service_lookup_from_network(network);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_ASSOCIATION);
+ CONNMAN_SERVICE_STATE_ASSOCIATION,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
return 0;
@@ -519,7 +520,8 @@ static void set_associate_error(struct connman_network *network)
service = __connman_service_lookup_from_network(network);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_FAILURE);
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
static void set_configure_error(struct connman_network *network)
@@ -531,7 +533,8 @@ static void set_configure_error(struct connman_network *network)
service = __connman_service_lookup_from_network(network);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_FAILURE);
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
static void set_invalid_key_error(struct connman_network *network)
@@ -634,7 +637,8 @@ static void set_configuration(struct connman_network *network)
service = __connman_service_lookup_from_network(network);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_CONFIGURATION);
+ CONNMAN_SERVICE_STATE_CONFIGURATION,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
static int set_connected_fixed(struct connman_network *network)
@@ -710,7 +714,8 @@ static void set_connected_manual(struct connman_network *network)
connman_network_set_associating(network, FALSE);
- __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
+ __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
static int set_connected_dhcp(struct connman_network *network)
@@ -839,7 +844,8 @@ static gboolean set_connected(gpointer user_data)
service = __connman_service_lookup_from_network(network);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_IDLE);
+ CONNMAN_SERVICE_STATE_IDLE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
network->connecting = FALSE;
@@ -1040,7 +1046,8 @@ static int manual_ipv4_set(struct connman_network *network,
__connman_ipconfig_set_gateway(ipconfig, &network->element);
- __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
+ __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
return 0;
}
@@ -1074,7 +1081,8 @@ int __connman_network_clear_ipconfig(struct connman_network *network,
}
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_CONFIGURATION);
+ CONNMAN_SERVICE_STATE_CONFIGURATION,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
return 0;
}
diff --git a/src/provider.c b/src/provider.c
index 6bd2df52..150a7ca3 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -179,7 +179,8 @@ int __connman_provider_disconnect(struct connman_provider *provider)
if (provider->vpn_service != NULL)
__connman_service_indicate_state(provider->vpn_service,
- CONNMAN_SERVICE_STATE_DISCONNECT);
+ CONNMAN_SERVICE_STATE_DISCONNECT,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
if (err < 0) {
if (err != -EINPROGRESS)
return err;
@@ -220,7 +221,8 @@ int __connman_provider_connect(struct connman_provider *provider)
return err;
__connman_service_indicate_state(provider->vpn_service,
- CONNMAN_SERVICE_STATE_ASSOCIATION);
+ CONNMAN_SERVICE_STATE_ASSOCIATION,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
return -EINPROGRESS;
}
@@ -327,7 +329,8 @@ static int set_connected(struct connman_provider *provider,
int err;
__connman_service_indicate_state(provider->vpn_service,
- CONNMAN_SERVICE_STATE_CONFIGURATION);
+ CONNMAN_SERVICE_STATE_CONFIGURATION,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
type = CONNMAN_ELEMENT_TYPE_IPV4;
@@ -343,13 +346,15 @@ static int set_connected(struct connman_provider *provider,
connman_element_unref(element);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_FAILURE);
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
return err;
}
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_READY);
+ CONNMAN_SERVICE_STATE_READY,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
__connman_service_set_domainname(service, provider->domain);
@@ -360,7 +365,8 @@ static int set_connected(struct connman_provider *provider,
} else {
connman_element_unregister_children(&provider->element);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_IDLE);
+ CONNMAN_SERVICE_STATE_IDLE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
return 0;
@@ -379,15 +385,18 @@ int connman_provider_set_state(struct connman_provider *provider,
return set_connected(provider, FALSE);
case CONNMAN_PROVIDER_STATE_CONNECT:
return __connman_service_indicate_state(provider->vpn_service,
- CONNMAN_SERVICE_STATE_ASSOCIATION);
+ CONNMAN_SERVICE_STATE_ASSOCIATION,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
case CONNMAN_PROVIDER_STATE_READY:
return set_connected(provider, TRUE);
case CONNMAN_PROVIDER_STATE_DISCONNECT:
return __connman_service_indicate_state(provider->vpn_service,
- CONNMAN_SERVICE_STATE_DISCONNECT);
+ CONNMAN_SERVICE_STATE_DISCONNECT,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
case CONNMAN_PROVIDER_STATE_FAILURE:
return __connman_service_indicate_state(provider->vpn_service,
- CONNMAN_SERVICE_STATE_FAILURE);
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
return -EINVAL;
diff --git a/src/service.c b/src/service.c
index 4c9fad96..5db3baee 100644
--- a/src/service.c
+++ b/src/service.c
@@ -58,7 +58,8 @@ struct connman_service {
enum connman_service_type type;
enum connman_service_mode mode;
enum connman_service_security security;
- enum connman_service_state state;
+ enum connman_service_state state_ipv4;
+ enum connman_service_state state_ipv6;
enum connman_service_error error;
connman_uint8_t strength;
connman_bool_t favorite;
@@ -312,9 +313,121 @@ static enum connman_service_proxy_method string2proxymethod(const char *method)
return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
}
-static connman_bool_t is_connecting(struct connman_service *service)
+static enum connman_service_state combine_state(
+ enum connman_service_state state_a,
+ enum connman_service_state state_b)
{
- switch (service->state) {
+ enum connman_service_state result;
+
+ if (state_a == state_b) {
+ result = state_a;
+ goto done;
+ }
+
+ if (state_a == CONNMAN_SERVICE_STATE_UNKNOWN) {
+ result = state_b;
+ goto done;
+ }
+
+ if (state_b == CONNMAN_SERVICE_STATE_UNKNOWN) {
+ result = state_a;
+ goto done;
+ }
+
+ if (state_a == CONNMAN_SERVICE_STATE_IDLE) {
+ result = state_b;
+ goto done;
+ }
+
+ if (state_b == CONNMAN_SERVICE_STATE_IDLE) {
+ result = state_a;
+ goto done;
+ }
+
+ if (state_a == CONNMAN_SERVICE_STATE_ASSOCIATION) {
+ if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION ||
+ state_b == CONNMAN_SERVICE_STATE_ONLINE ||
+ state_b == CONNMAN_SERVICE_STATE_READY)
+ result = state_b;
+ else
+ result = state_a;
+ goto done;
+ }
+
+ if (state_b == CONNMAN_SERVICE_STATE_ASSOCIATION) {
+ if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION ||
+ state_a == CONNMAN_SERVICE_STATE_ONLINE ||
+ state_a == CONNMAN_SERVICE_STATE_READY)
+ result = state_a;
+ else
+ result = state_b;
+ goto done;
+ }
+
+ if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION) {
+ if (state_b == CONNMAN_SERVICE_STATE_ONLINE ||
+ state_b == CONNMAN_SERVICE_STATE_READY)
+ result = state_b;
+ else
+ result = state_a;
+ goto done;
+ }
+
+ if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION) {
+ if (state_a == CONNMAN_SERVICE_STATE_ONLINE ||
+ state_a == CONNMAN_SERVICE_STATE_READY)
+ result = state_a;
+ else
+ result = state_b;
+ goto done;
+ }
+
+ if (state_a == CONNMAN_SERVICE_STATE_READY) {
+ if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
+ result = state_b;
+ else
+ result = state_a;
+ goto done;
+ }
+
+ if (state_b == CONNMAN_SERVICE_STATE_READY) {
+ if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
+ result = state_a;
+ else
+ result = state_b;
+ goto done;
+ }
+
+ if (state_a == CONNMAN_SERVICE_STATE_ONLINE) {
+ result = state_a;
+ goto done;
+ }
+
+ if (state_b == CONNMAN_SERVICE_STATE_ONLINE) {
+ result = state_b;
+ goto done;
+ }
+
+ if (state_a == CONNMAN_SERVICE_STATE_DISCONNECT) {
+ result = state_b;
+ goto done;
+ }
+
+ if (state_b == CONNMAN_SERVICE_STATE_DISCONNECT) {
+ result = state_a;
+ goto done;
+ }
+
+ result = CONNMAN_SERVICE_STATE_FAILURE;
+
+done:
+ return result;
+}
+
+static connman_bool_t is_connecting_state(struct connman_service *service,
+ enum connman_service_state state)
+{
+ switch (state) {
case CONNMAN_SERVICE_STATE_UNKNOWN:
case CONNMAN_SERVICE_STATE_IDLE:
case CONNMAN_SERVICE_STATE_FAILURE:
@@ -333,9 +446,10 @@ static connman_bool_t is_connecting(struct connman_service *service)
return FALSE;
}
-static connman_bool_t is_connected(const struct connman_service *service)
+static connman_bool_t is_connected_state(const struct connman_service *service,
+ enum connman_service_state state)
{
- switch (service->state) {
+ switch (state) {
case CONNMAN_SERVICE_STATE_UNKNOWN:
case CONNMAN_SERVICE_STATE_IDLE:
case CONNMAN_SERVICE_STATE_ASSOCIATION:
@@ -351,6 +465,24 @@ static connman_bool_t is_connected(const struct connman_service *service)
return FALSE;
}
+static connman_bool_t is_connecting(struct connman_service *service)
+{
+ enum connman_service_state state;
+
+ state = combine_state(service->state_ipv4, service->state_ipv6);
+
+ return is_connecting_state(service, state);
+}
+
+static connman_bool_t is_connected(struct connman_service *service)
+{
+ enum connman_service_state state;
+
+ state = combine_state(service->state_ipv4, service->state_ipv6);
+
+ return is_connected_state(service, state);
+}
+
static void update_nameservers(struct connman_service *service)
{
const char *ifname;
@@ -365,7 +497,7 @@ static void update_nameservers(struct connman_service *service)
if (ifname == NULL)
return;
- switch (service->state) {
+ switch (combine_state(service->state_ipv4, service->state_ipv6)) {
case CONNMAN_SERVICE_STATE_UNKNOWN:
case CONNMAN_SERVICE_STATE_IDLE:
case CONNMAN_SERVICE_STATE_ASSOCIATION:
@@ -628,7 +760,8 @@ static void state_changed(struct connman_service *service)
{
const char *str;
- str = state2string(service->state);
+ str = state2string(combine_state(service->state_ipv4,
+ service->state_ipv6));
if (str == NULL)
return;
@@ -797,7 +930,10 @@ static void append_ipv4(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (is_connected(service) == FALSE)
+ DBG("ipv4 %p state %s", service->ipconfig_ipv4,
+ state2string(service->state_ipv4));
+
+ if (is_connected_state(service, service->state_ipv4) == FALSE)
return;
if (service->ipconfig_ipv4 != NULL)
@@ -808,7 +944,10 @@ static void append_ipv6(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (is_connected(service) == FALSE)
+ DBG("ipv6 %p state %s", service->ipconfig_ipv6,
+ state2string(service->state_ipv6));
+
+ if (is_connected_state(service, service->state_ipv6) == FALSE)
return;
if (service->ipconfig_ipv6 != NULL)
@@ -874,7 +1013,8 @@ static void append_domain(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (is_connected(service) == FALSE && is_connecting(service) == FALSE)
+ if (is_connected(service) == FALSE &&
+ is_connecting(service) == FALSE)
return;
if (service->domainname == NULL)
@@ -1369,7 +1509,8 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
connman_dbus_dict_append_array(dict, "Security",
DBUS_TYPE_STRING, append_security, service);
- str = state2string(service->state);
+ str = state2string(combine_state(service->state_ipv4,
+ service->state_ipv6));
if (str != NULL)
connman_dbus_dict_append_basic(dict, "State",
DBUS_TYPE_STRING, &str);
@@ -2090,6 +2231,8 @@ static DBusMessage *set_property(DBusConnection *conn,
g_str_equal(name, "IPv6.Configuration")) {
struct connman_ipconfig *ipv4 = NULL, *ipv6 = NULL;
+ enum connman_service_state state =
+ CONNMAN_SERVICE_STATE_UNKNOWN;
int err = 0;
DBG("%s", name);
@@ -2099,7 +2242,9 @@ static DBusMessage *set_property(DBusConnection *conn,
return __connman_error_invalid_property(msg);
if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
- if (is_connecting(service) || is_connected(service))
+ state = service->state_ipv4;
+ if (is_connecting_state(service, state) ||
+ is_connected_state(service, state))
__connman_network_clear_ipconfig(
service->network,
service->ipconfig_ipv4);
@@ -2108,7 +2253,9 @@ static DBusMessage *set_property(DBusConnection *conn,
err = __connman_ipconfig_set_config(ipv4, &value);
} else if (g_str_equal(name, "IPv6.Configuration") == TRUE) {
- if (is_connecting(service) || is_connected(service))
+ state = service->state_ipv6;
+ if (is_connecting_state(service, state) ||
+ is_connected_state(service, state))
__connman_network_clear_ipconfig(
service->network,
service->ipconfig_ipv6);
@@ -2118,7 +2265,8 @@ static DBusMessage *set_property(DBusConnection *conn,
}
if (err < 0) {
- if (is_connected(service) || is_connecting(service))
+ if (is_connected_state(service, state) ||
+ is_connecting_state(service, state))
__connman_network_set_ipconfig(service->network,
ipv4, ipv6);
return __connman_error_failed(msg, -err);
@@ -2142,7 +2290,7 @@ static DBusMessage *set_property(DBusConnection *conn,
static void set_idle(struct connman_service *service)
{
- service->state = CONNMAN_SERVICE_STATE_IDLE;
+ service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
state_changed(service);
}
@@ -2190,7 +2338,8 @@ static connman_bool_t is_ignore(struct connman_service *service)
if (service->ignore == TRUE)
return TRUE;
- if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
+ if (combine_state(service->state_ipv4, service->state_ipv6) ==
+ CONNMAN_SERVICE_STATE_FAILURE)
return TRUE;
return FALSE;
@@ -2221,7 +2370,9 @@ void __connman_service_auto_connect(void)
return;
if (is_ignore(service) == FALSE &&
- service->state == CONNMAN_SERVICE_STATE_IDLE)
+ combine_state(service->state_ipv4,
+ service->state_ipv6) ==
+ CONNMAN_SERVICE_STATE_IDLE)
break;
service = NULL;
@@ -2294,7 +2445,11 @@ static gboolean connect_timeout(gpointer user_data)
autoconnect = TRUE;
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_FAILURE);
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+ __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
if (autoconnect == TRUE && service->userconnect == FALSE)
__connman_service_auto_connect();
@@ -2423,8 +2578,7 @@ static DBusMessage *connect_service(DBusConnection *conn,
while (g_sequence_iter_is_end(iter) == FALSE) {
struct connman_service *temp = g_sequence_get(iter);
- if (service->type == temp->type &&
- is_connecting(temp) == TRUE)
+ if (service->type == temp->type && is_connecting(temp) == TRUE)
return __connman_error_in_progress(msg);
iter = g_sequence_iter_next(iter);
@@ -2502,7 +2656,8 @@ static DBusMessage *remove_service(DBusConnection *conn,
return __connman_error_not_supported(msg);
if (service->favorite == FALSE &&
- service->state != CONNMAN_SERVICE_STATE_FAILURE)
+ combine_state(service->state_ipv4, service->state_ipv6) !=
+ CONNMAN_SERVICE_STATE_FAILURE)
return __connman_error_not_supported(msg);
if (service->network != NULL) {
@@ -2560,7 +2715,8 @@ static DBusMessage *move_service(DBusConnection *conn,
DBG("target %s", target->identifier);
- if (target->state != service->state)
+ if (target->state_ipv4 != service->state_ipv4 &&
+ target->state_ipv6 != service->state_ipv6)
return __connman_error_invalid_service(msg);
g_get_current_time(&service->modified);
@@ -2740,7 +2896,9 @@ static void service_initialize(struct connman_service *service)
service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
- service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
+
+ service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
+ service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
service->favorite = FALSE;
service->immutable = FALSE;
@@ -2843,7 +3001,9 @@ static gint service_compare(gconstpointer a, gconstpointer b,
struct connman_service *service_a = (void *) a;
struct connman_service *service_b = (void *) b;
- if (service_a->state != service_b->state) {
+ if (service_a->state_ipv4 != service_b->state_ipv4 &&
+ service_a->state_ipv6 != service_b->state_ipv6) {
+
if (is_connected(service_a) == TRUE)
return -1;
if (is_connected(service_b) == TRUE)
@@ -3079,29 +3239,49 @@ static void report_error_cb(struct connman_service *service,
}
int __connman_service_indicate_state(struct connman_service *service,
- enum connman_service_state state)
+ enum connman_service_state new_state,
+ enum connman_ipconfig_type type)
{
+ enum connman_service_state service_state,
+ state = CONNMAN_SERVICE_STATE_IDLE;
GSequenceIter *iter;
- DBG("service %p state %d", service, state);
-
if (service == NULL)
return -EINVAL;
- if (service->state == state)
- return -EALREADY;
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+ if (service->state_ipv4 == new_state)
+ return -EALREADY;
+ state = combine_state(new_state, service->state_ipv6);
+ } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
+ if (service->state_ipv6 == new_state)
+ return -EALREADY;
+ state = combine_state(new_state, service->state_ipv4);
+ } else
+ return -EINVAL;
+
+ service_state = combine_state(service->state_ipv4,
+ service->state_ipv6);
- if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
+ DBG("service %p state %s/%s => %s new %s/%d => %s",
+ service,
+ state2string(service->state_ipv4),
+ state2string(service->state_ipv6),
+ state2string(service_state),
+ state2string(new_state),
+ type,
+ state2string(state));
+
+ if (service_state == CONNMAN_SERVICE_STATE_FAILURE &&
state == CONNMAN_SERVICE_STATE_IDLE)
return -EINVAL;
- if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
+ if (service_state == CONNMAN_SERVICE_STATE_IDLE &&
state == CONNMAN_SERVICE_STATE_DISCONNECT)
return -EINVAL;
if (state == CONNMAN_SERVICE_STATE_IDLE &&
- service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
- service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
+ service_state != CONNMAN_SERVICE_STATE_DISCONNECT) {
state_changed(service);
reply_pending(service, ECONNABORTED);
@@ -3109,7 +3289,7 @@ int __connman_service_indicate_state(struct connman_service *service,
__connman_service_disconnect(service);
}
- if (state == CONNMAN_SERVICE_STATE_CONFIGURATION) {
+ if (new_state == CONNMAN_SERVICE_STATE_CONFIGURATION) {
if (__connman_stats_service_register(service) == 0) {
__connman_stats_get(service, FALSE,
&service->stats.data);
@@ -3117,13 +3297,22 @@ int __connman_service_indicate_state(struct connman_service *service,
&service->stats_roaming.data);
}
- if (service->ipconfig_ipv4)
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
+ new_state == CONNMAN_SERVICE_STATE_CONFIGURATION)
__connman_ipconfig_enable(service->ipconfig_ipv4);
- if (service->ipconfig_ipv6)
+ else if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
+ new_state == CONNMAN_SERVICE_STATE_CONFIGURATION)
__connman_ipconfig_enable(service->ipconfig_ipv6);
}
- service->state = state;
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ service->state_ipv4 = new_state;
+ else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ service->state_ipv6 = new_state;
+
+ if (state == service_state)
+ return -EALREADY;
+
state_changed(service);
if (state == CONNMAN_SERVICE_STATE_ONLINE) {
@@ -3227,10 +3416,12 @@ int __connman_service_indicate_state(struct connman_service *service,
__connman_profile_changed(FALSE);
- if (service->state == CONNMAN_SERVICE_STATE_ONLINE)
+ service_state = combine_state(service->state_ipv4,
+ service->state_ipv6);
+ if (service_state == CONNMAN_SERVICE_STATE_ONLINE)
default_changed();
- if (service->state == CONNMAN_SERVICE_STATE_DISCONNECT) {
+ if (service_state == CONNMAN_SERVICE_STATE_DISCONNECT) {
struct connman_service *def_service = get_default();
if (__connman_notifier_count_connected() == 0 &&
@@ -3239,8 +3430,8 @@ int __connman_service_indicate_state(struct connman_service *service,
__connman_provider_disconnect(def_service->provider);
}
- if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
- service->state == CONNMAN_SERVICE_STATE_FAILURE)
+ if (service_state == CONNMAN_SERVICE_STATE_IDLE ||
+ service_state == CONNMAN_SERVICE_STATE_FAILURE)
__connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
return 0;
@@ -3260,27 +3451,37 @@ int __connman_service_indicate_error(struct connman_service *service,
__connman_service_set_passphrase(service, NULL);
return __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_FAILURE);
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
int __connman_service_clear_error(struct connman_service *service)
{
+ enum connman_service_state state;
+
DBG("service %p", service);
if (service == NULL)
return -EINVAL;
- if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
+ state = combine_state(service->state_ipv4, service->state_ipv6);
+
+ if (state != CONNMAN_SERVICE_STATE_FAILURE)
return -EINVAL;
- service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
+ service->state_ipv4 = service->state_ipv6 =
+ CONNMAN_SERVICE_STATE_UNKNOWN;
service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;;
if (service->favorite == TRUE)
set_reconnect_state(service, TRUE);
+ __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+
return __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_IDLE);
+ CONNMAN_SERVICE_STATE_IDLE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
}
int __connman_service_indicate_default(struct connman_service *service)
@@ -3475,9 +3676,12 @@ static int service_connect(struct connman_service *service)
int __connman_service_connect(struct connman_service *service)
{
+ enum connman_service_state state;
int err;
- DBG("service %p", service);
+ state = combine_state(service->state_ipv4, service->state_ipv6);
+
+ DBG("service %p state %s", service, state2string(state));
if (is_connected(service) == TRUE)
return -EISCONN;
@@ -3512,7 +3716,11 @@ int __connman_service_connect(struct connman_service *service)
reply_pending(service, err);
__connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_FAILURE);
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+ __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
return err;
}
@@ -4323,7 +4531,7 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
break;
}
- service->state = CONNMAN_SERVICE_STATE_IDLE;
+ service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
update_from_network(service, network);
@@ -4464,7 +4672,7 @@ __connman_service_create_from_provider(struct connman_provider *provider)
service->provider = connman_provider_ref(provider);
service->autoconnect = FALSE;
- service->state = CONNMAN_SERVICE_STATE_IDLE;
+ service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
str = connman_provider_get_string(provider, "Name");
if (str != NULL) {
@@ -4627,7 +4835,8 @@ static int service_load(struct connman_service *service)
service->identifier, "Failure", NULL);
if (str != NULL) {
if (service->favorite == FALSE)
- service->state = CONNMAN_SERVICE_STATE_FAILURE;
+ service->state_ipv4 = service->state_ipv6 =
+ CONNMAN_SERVICE_STATE_FAILURE;
service->error = string2error(str);
}
break;
@@ -4801,7 +5010,8 @@ update:
g_key_file_set_boolean(keyfile, service->identifier,
"AutoConnect", service->autoconnect);
- if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
+ if (service->state_ipv4 == CONNMAN_SERVICE_STATE_FAILURE ||
+ service->state_ipv6 == CONNMAN_SERVICE_STATE_FAILURE) {
const char *failure = error2string(service->error);
if (failure != NULL)
g_key_file_set_string(keyfile,