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

Reply via email to