From: Daniel Wagner <[email protected]>
---
src/service.c | 139 ++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 103 insertions(+), 36 deletions(-)
diff --git a/src/service.c b/src/service.c
index 904fac3..4c2fe78 100644
--- a/src/service.c
+++ b/src/service.c
@@ -106,6 +106,7 @@ struct connman_service {
char **excludes;
char *pac;
connman_bool_t wps;
+ GQueue *ipconfig_state_queue;
};
static void append_path(gpointer value, gpointer user_data)
@@ -2924,6 +2925,9 @@ static void service_free(gpointer user_data)
g_hash_table_destroy(service->counter_table);
+ if (service->ipconfig_state_queue != NULL)
+ g_queue_free(service->ipconfig_state_queue);
+
if (service->network != NULL) {
if (service->network_created == TRUE)
connman_network_unref(service->network);
@@ -3083,6 +3087,12 @@ struct connman_service *connman_service_create(void)
counters);
}
+ service->ipconfig_state_queue = g_queue_new();
+ if (service->ipconfig_state_queue == NULL) {
+ service_free(service);
+ return NULL;
+ }
+
service_initialize(service);
service->location = __connman_location_create(service);
@@ -3666,13 +3676,102 @@ int __connman_service_indicate_default(struct
connman_service *service)
return 0;
}
+static int process_ipconfig_indicate_state(struct connman_service *service,
+ enum connman_service_state state,
+ enum connman_ipconfig_type type)
+{
+ enum connman_service_state current_state;
+ int err;
+
+ DBG("service %p (%s) state %d (%s) type %d (%s)",
+ service, service ? service->identifier : NULL,
+ state, state2string(state),
+ type, __connman_ipconfig_type2string(type));
+
+ current_state = combine_state(service->state_ipv4, service->state_ipv6);
+
+ switch (current_state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ break;
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ if (state == CONNMAN_SERVICE_STATE_READY ||
+ state == CONNMAN_SERVICE_STATE_ONLINE)
+ return -EALREADY;
+ break;
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ break;
+ }
+
+ if (current_state == state)
+ return -EALREADY;
+
+ err = indicate_state(service, state, type);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+struct ipconfig_queue_state_data {
+ enum connman_service_state state;
+ enum connman_ipconfig_type type;
+};
+
+static gboolean ipconfig_queue_process(gpointer user_data)
+{
+ struct connman_service *service = user_data;
+ struct ipconfig_queue_state_data *data;
+
+ DBG("service %p", service);
+
+ if (g_queue_get_length(service->ipconfig_state_queue) == 0)
+ return FALSE;
+
+ data = g_queue_pop_head(service->ipconfig_state_queue);
+ process_ipconfig_indicate_state(service, data->state, data->type);
+
+ g_free(data);
+
+ return FALSE;
+}
+
+static int ipconfig_queue_state_add(struct connman_service *service,
+ enum connman_service_state state,
+ enum connman_ipconfig_type type)
+{
+ struct ipconfig_queue_state_data *data;
+
+ DBG("service %p (%s) state %d (%s) type %d (%s)",
+ service, service ? service->identifier : NULL,
+ state, state2string(state),
+ type, __connman_ipconfig_type2string(type));
+
+ data = g_try_new0(struct ipconfig_queue_state_data, 1);
+ if (data == NULL)
+ return -ENOMEM;
+
+ data->state = state;
+ data->type = type;
+
+ g_queue_push_tail(service->ipconfig_state_queue, data);
+
+ /* XXX This is just a stupid idea: Let's defer everything by 1 second.
*/
+ g_timeout_add_seconds(1, ipconfig_queue_process, service);
+
+ return 0;
+}
+
int __connman_service_ipconfig_indicate_state(struct connman_service *service,
enum connman_service_state state,
enum connman_ipconfig_type type)
{
enum connman_service_state current_state;
enum connman_ipconfig_method ipv4_method, ipv6_method;
- int err = 0;
DBG("service %p (%s) state %d (%s) type %d (%s)",
service, service ? service->identifier : NULL,
@@ -3711,16 +3810,8 @@ int __connman_service_ipconfig_indicate_state(struct
connman_service *service,
case CONNMAN_IPCONFIG_METHOD_MANUAL:
break;
case CONNMAN_IPCONFIG_METHOD_DHCP:
- if (current_state ==
CONNMAN_SERVICE_STATE_IDLE) {
- /*
- * XXX Let's defer the IPv6
- * setting the service to
- * READY with a simple
- * hack.
- */
- return 0;
- }
-
+ if (current_state == CONNMAN_SERVICE_STATE_IDLE)
+ return
ipconfig_queue_state_add(service, state, type);
break;
}
case CONNMAN_IPCONFIG_METHOD_FIXED:
@@ -3731,31 +3822,7 @@ int __connman_service_ipconfig_indicate_state(struct
connman_service *service,
}
}
- switch (current_state) {
- case CONNMAN_SERVICE_STATE_UNKNOWN:
- case CONNMAN_SERVICE_STATE_IDLE:
- break;
- case CONNMAN_SERVICE_STATE_READY:
- case CONNMAN_SERVICE_STATE_ONLINE:
- if (state == CONNMAN_SERVICE_STATE_READY ||
- state == CONNMAN_SERVICE_STATE_ONLINE)
- return -EALREADY;
- break;
- case CONNMAN_SERVICE_STATE_FAILURE:
- case CONNMAN_SERVICE_STATE_DISCONNECT:
- case CONNMAN_SERVICE_STATE_ASSOCIATION:
- case CONNMAN_SERVICE_STATE_CONFIGURATION:
- break;
- }
-
- if (current_state == state)
- return -EALREADY;
-
- err = indicate_state(service, state, type);
- if (err < 0)
- return err;
-
- return 0;
+ return process_ipconfig_indicate_state(service, state, type);
}
int __connman_service_request_login(struct connman_service *service)
--
1.7.5.4
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman