summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrant Erickson <marathon96@gmail.com>2011-05-25 10:10:17 -0700
committerSamuel Ortiz <sameo@linux.intel.com>2011-05-31 21:30:04 +0200
commitb6480b70a2c9ededa0c49101d8a73f8bf45b3efa (patch)
tree03a01dbbf49fd848cc5e9544d45ae728981a03bf
parent8025a0a6c612c803eb676e143989575cd3045e03 (diff)
downloadconnman-b6480b70a2c9ededa0c49101d8a73f8bf45b3efa.tar.gz
connman-b6480b70a2c9ededa0c49101d8a73f8bf45b3efa.tar.bz2
connman-b6480b70a2c9ededa0c49101d8a73f8bf45b3efa.zip
service: Indicate IP Configuration Ready Event
In the Connection Manager, completion of a valid IP configuration excites the service state machine to move from the "configuration" to the "ready" state. However, the existing implementation of IP configuration completion explicitly attempts to directly manipulate service state, rather than hinting at an excitation event. As a consequence, a late IP configuration completion after the service state machine has transitioned from "ready" to "online" can lead to an incorrect transition back to the "ready" state. This causes the connection count for the technology associated with that service to increment again, unnecessarily. This patch avoids this issue by providing a service object interface that simply hints that an IP configuration is complete for a given IP type, allowing the service object and its state machine to either hold fast in the present state, returning an advisory error or advancing, as before. All prior invocations of __connman_service_indicate_state outside of the service module for the CONNMAN_SERVICE_STATE_READY are replaced with calls to this new interface. Thanks to Daniel Wagner and Marcel Holtmann for offline IRC discussion that helped motivate this fix. * v2: Incorporated feedback from Samuel Ortiz about combining IPv4 and IPv6 states before checking state readiness.
-rw-r--r--src/connection.c3
-rw-r--r--src/connman.h2
-rw-r--r--src/network.c18
-rw-r--r--src/service.c29
4 files changed, 36 insertions, 16 deletions
diff --git a/src/connection.c b/src/connection.c
index 8ca1f7a0..10ef04a3 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -304,8 +304,7 @@ int __connman_connection_gateway_add(struct connman_service *service,
__connman_service_nameserver_add_routes(service,
new_gateway->ipv4_gateway);
- __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
- CONNMAN_IPCONFIG_TYPE_IPV4);
+ __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV4);
if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_VPN) {
new_gateway->vpn = TRUE;
diff --git a/src/connman.h b/src/connman.h
index bf6e5380..883051f3 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -519,6 +519,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_set_ipconfig_ready(struct connman_service *service,
+ enum connman_ipconfig_type type);
int __connman_service_indicate_state(struct connman_service *service,
enum connman_service_state new_state,
enum connman_ipconfig_type type);
diff --git a/src/network.c b/src/network.c
index 02ee3c04..1fa62ee4 100644
--- a/src/network.c
+++ b/src/network.c
@@ -671,8 +671,7 @@ static void dhcp_success(struct connman_network *network)
if (err < 0)
goto err;
- __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
- CONNMAN_IPCONFIG_TYPE_IPV4);
+ __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV4);
return;
@@ -734,9 +733,8 @@ static int set_connected_fixed(struct connman_network *network)
if (err < 0)
goto err;
- __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_READY,
- CONNMAN_IPCONFIG_TYPE_IPV4);
+ __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV4);
+
return 0;
err:
@@ -772,8 +770,7 @@ 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_IPCONFIG_TYPE_IPV4);
+ __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV4);
return;
@@ -843,9 +840,7 @@ static void autoconf_ipv6_set(struct connman_network *network)
network->connecting = FALSE;
- __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_READY,
- CONNMAN_IPCONFIG_TYPE_IPV6);
+ __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV6);
}
static gboolean set_connected(gpointer user_data)
@@ -1106,8 +1101,7 @@ static int manual_ipv4_set(struct connman_network *network,
__connman_ipconfig_gateway_add(ipconfig);
- __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
- CONNMAN_IPCONFIG_TYPE_IPV4);
+ __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV4);
return 0;
}
diff --git a/src/service.c b/src/service.c
index 69e711a9..a7ebf05c 100644
--- a/src/service.c
+++ b/src/service.c
@@ -3428,6 +3428,32 @@ static void report_error_cb(struct connman_service *service,
}
}
+int __connman_service_set_ipconfig_ready(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ enum connman_service_state state;
+ int err = 0;
+
+ DBG("service %p (%s) type %d (%s)",
+ service, service ? service->identifier : NULL,
+ type, __connman_ipconfig_type2string(type));
+
+ if (service == NULL)
+ return -EINVAL;
+
+ state = combine_state(service->state_ipv4, service->state_ipv6);
+
+ if (state == CONNMAN_SERVICE_STATE_READY ||
+ state == CONNMAN_SERVICE_STATE_ONLINE) {
+ err = -EALREADY;
+ } else {
+ err = __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_READY, type);
+ }
+
+ return err;
+}
+
int __connman_service_indicate_state(struct connman_service *service,
enum connman_service_state new_state,
enum connman_ipconfig_type type)
@@ -4426,8 +4452,7 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig)
if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
method == CONNMAN_IPCONFIG_METHOD_AUTO)
- __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_READY,
+ __connman_service_set_ipconfig_ready(service,
CONNMAN_IPCONFIG_TYPE_IPV6);
settings_changed(service, ipconfig);