Don't allow remove method calls on non-favorite services
[connman] / src / service.c
index 05e0be8..a6ee992 100644 (file)
@@ -292,6 +292,9 @@ static gboolean connect_timeout(gpointer user_data)
 
        service->timeout = 0;
 
+       if (service->network != NULL)
+               __connman_network_disconnect(service->network);
+
        if (service->pending != NULL) {
                DBusMessage *reply;
 
@@ -301,6 +304,9 @@ static gboolean connect_timeout(gpointer user_data)
 
                dbus_message_unref(service->pending);
                service->pending = NULL;
+
+               __connman_service_indicate_state(service,
+                                       CONNMAN_SERVICE_STATE_FAILURE);
        }
 
        return FALSE;
@@ -373,8 +379,13 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
        }
 
        if (service->network != NULL) {
+               struct connman_device *device;
                int err;
 
+               device = connman_network_get_device(service->network);
+               if (device != NULL)
+                       __connman_device_disconnect(device);
+
                err = __connman_network_disconnect(service->network);
                if (err < 0 && err != -EINPROGRESS)
                        return __connman_error_failed(msg, -err);
@@ -406,12 +417,17 @@ static DBusMessage *remove_service(DBusConnection *conn,
        if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
                return __connman_error_not_supported(msg);
 
+       if (service->favorite == FALSE)
+               return __connman_error_not_supported(msg);
+
        if (service->network != NULL) {
-               int err;
+               struct connman_device *device;
 
-               err = __connman_network_disconnect(service->network);
-               if (err < 0 && err != -EINPROGRESS)
-                       return __connman_error_failed(msg, -err);
+               device = connman_network_get_device(service->network);
+               if (device != NULL)
+                       __connman_device_disconnect(device);
+
+               __connman_network_disconnect(service->network);
        }
 
        connman_service_set_favorite(service, FALSE);
@@ -589,6 +605,13 @@ 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 == CONNMAN_SERVICE_STATE_READY)
+                       return -1;
+               if (service_b->state == CONNMAN_SERVICE_STATE_READY)
+                       return 1;
+       }
+
        if (service_a->order > service_b->order)
                return -1;
 
@@ -666,6 +689,8 @@ int __connman_service_set_carrier(struct connman_service *service,
 int __connman_service_indicate_state(struct connman_service *service,
                                        enum connman_service_state state)
 {
+       GSequenceIter *iter;
+
        DBG("service %p state %d", service, state);
 
        if (service == NULL)
@@ -704,7 +729,6 @@ int __connman_service_indicate_state(struct connman_service *service,
                        dbus_message_unref(service->pending);
                        service->pending = NULL;
                }
-
        }
 
        if (state == CONNMAN_SERVICE_STATE_FAILURE) {
@@ -721,8 +745,17 @@ int __connman_service_indicate_state(struct connman_service *service,
                        dbus_message_unref(service->pending);
                        service->pending = NULL;
                }
+
+               service->state = CONNMAN_SERVICE_STATE_IDLE;
+               state_changed(service);
        }
 
+       iter = g_hash_table_lookup(service_hash, service->identifier);
+       if (iter != NULL)
+               g_sequence_sort_changed(iter, service_compare, NULL);
+
+       __connman_profile_changed();
+
        return 0;
 }
 
@@ -1062,6 +1095,8 @@ struct connman_service *__connman_service_create_from_network(struct connman_net
 
        service->type = convert_network_type(network);
 
+       service->state = CONNMAN_SERVICE_STATE_IDLE;
+
        update_from_network(service, network);
 
        service_register(service);