enum connman_service_state state;
connman_uint8_t strength;
connman_bool_t favorite;
+ connman_bool_t hidden;
+ GTimeVal modified;
unsigned int order;
char *name;
char *passphrase;
g_sequence_foreach(service_list, append_path, iter);
}
+struct find_data {
+ const char *path;
+ struct connman_service *service;
+};
+
+static void compare_path(gpointer value, gpointer user_data)
+{
+ struct connman_service *service = value;
+ struct find_data *data = user_data;
+
+ if (data->service != NULL)
+ return;
+
+ if (g_strcmp0(service->path, data->path) == 0)
+ data->service = service;
+}
+
+static struct connman_service *find_service(const char *path)
+{
+ struct find_data data = { .path = path, .service = NULL };
+
+ DBG("path %s", path);
+
+ g_sequence_foreach(service_list, compare_path, &data);
+
+ return data.service;
+}
+
static const char *type2string(enum connman_service_type type)
{
switch (type) {
return "wep";
case CONNMAN_SERVICE_SECURITY_WPA:
return "wpa";
- case CONNMAN_SERVICE_SECURITY_WPA2:
- return "wpa2";
+ case CONNMAN_SERVICE_SECURITY_RSN:
+ return "rsn";
}
return NULL;
g_dbus_send_message(connection, signal);
}
+static void strength_changed(struct connman_service *service)
+{
+ DBusMessage *signal;
+ DBusMessageIter entry, value;
+ const char *key = "Strength";
+
+ if (service->path == NULL)
+ return;
+
+ if (service->strength == 0)
+ return;
+
+ signal = dbus_message_new_signal(service->path,
+ CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
+ if (signal == NULL)
+ return;
+
+ dbus_message_iter_init_append(signal, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_STRING_AS_STRING, &value);
+ dbus_message_iter_append_basic(&value, DBUS_TYPE_BYTE,
+ &service->strength);
+ dbus_message_iter_close_container(&entry, &value);
+
+ g_dbus_send_message(connection, signal);
+}
+
static DBusMessage *get_properties(DBusConnection *conn,
- DBusMessage *msg, void *data)
+ DBusMessage *msg, void *user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
DBusMessage *reply;
DBusMessageIter array, dict;
const char *str;
- DBG("conn %p", conn);
+ DBG("service %p", service);
reply = dbus_message_new_method_return(msg);
if (reply == NULL)
}
static DBusMessage *set_property(DBusConnection *conn,
- DBusMessage *msg, void *data)
+ DBusMessage *msg, void *user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
DBusMessageIter iter, value;
const char *name;
int type;
- DBG("conn %p", conn);
+ DBG("service %p", service);
if (dbus_message_iter_init(msg, &iter) == FALSE)
return __connman_error_invalid_arguments(msg);
service->timeout = 0;
+ if (service->network != NULL)
+ __connman_network_disconnect(service->network);
+
if (service->pending != NULL) {
DBusMessage *reply;
dbus_message_unref(service->pending);
service->pending = NULL;
+
+ __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_FAILURE);
}
return FALSE;
}
static DBusMessage *connect_service(DBusConnection *conn,
- DBusMessage *msg, void *data)
+ DBusMessage *msg, void *user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
+
+ DBG("service %p", service);
if (service->pending != NULL)
return __connman_error_in_progress(msg);
if (service->network != NULL) {
int err;
+ if (service->hidden == TRUE)
+ return __connman_error_invalid_service(msg);
+
connman_network_set_string(service->network,
"WiFi.Passphrase", service->passphrase);
- err = connman_network_connect(service->network);
+ err = __connman_network_connect(service->network);
if (err < 0 && err != -EINPROGRESS)
return __connman_error_failed(msg, -err);
}
static DBusMessage *disconnect_service(DBusConnection *conn,
- DBusMessage *msg, void *data)
+ DBusMessage *msg, void *user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
+
+ DBG("service %p", service);
if (service->pending != NULL) {
DBusMessage *reply;
}
static DBusMessage *remove_service(DBusConnection *conn,
- DBusMessage *msg, void *data)
+ DBusMessage *msg, void *user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
+
+ DBG("service %p", service);
if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
return __connman_error_not_supported(msg);
- if (service->network != NULL) {
- int err;
+ if (service->favorite == FALSE)
+ return __connman_error_not_supported(msg);
- err = __connman_network_disconnect(service->network);
- if (err < 0 && err != -EINPROGRESS)
- return __connman_error_failed(msg, -err);
- }
+ if (service->network != NULL)
+ __connman_network_disconnect(service->network);
connman_service_set_favorite(service, FALSE);
__connman_storage_save_service(service);
}
static DBusMessage *move_before(DBusConnection *conn,
- DBusMessage *msg, void *data)
+ DBusMessage *msg, void *user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
+ struct connman_service *target;
+ const char *path;
+ GSequenceIter *src, *dst;
+
+ DBG("service %p", service);
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
if (service->favorite == FALSE)
return __connman_error_not_supported(msg);
+ target = find_service(path);
+ if (target == NULL || target->favorite == FALSE || target == service)
+ return __connman_error_invalid_service(msg);
+
+ DBG("target %s", target->identifier);
+
+ g_get_current_time(&service->modified);
+ __connman_storage_save_service(service);
+
+ src = g_hash_table_lookup(service_hash, service->identifier);
+ dst = g_hash_table_lookup(service_hash, target->identifier);
+
+#if 0
+ g_sequence_move(src, dst);
+
+ __connman_profile_changed();
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+#endif
return __connman_error_not_implemented(msg);
}
static DBusMessage *move_after(DBusConnection *conn,
- DBusMessage *msg, void *data)
+ DBusMessage *msg, void *user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
+ struct connman_service *target;
+ const char *path;
+
+ DBG("service %p", service);
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
if (service->favorite == FALSE)
return __connman_error_not_supported(msg);
+ target = find_service(path);
+ if (target == NULL || target->favorite == FALSE || target == service)
+ return __connman_error_invalid_service(msg);
+
+ DBG("target %s", target->identifier);
+
+ g_get_current_time(&service->modified);
+ __connman_storage_save_service(service);
+
return __connman_error_not_implemented(msg);
}
{ },
};
-static void service_free(gpointer data)
+static void service_free(gpointer user_data)
{
- struct connman_service *service = data;
+ struct connman_service *service = user_data;
char *path = service->path;
DBG("service %p", service);
service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
service->favorite = FALSE;
+ service->hidden = FALSE;
service->order = 0;
}
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;
if (iter == NULL)
return -ENOENT;
- if (service->favorite)
+ if (service->favorite == favorite)
return -EALREADY;
service->favorite = favorite;
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)
service->pending = NULL;
}
+ g_get_current_time(&service->modified);
+ __connman_storage_save_service(service);
}
if (state == CONNMAN_SERVICE_STATE_FAILURE) {
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;
+}
+
+int __connman_service_indicate_default(struct connman_service *service)
+{
+ DBG("service %p", service);
+
return 0;
}
static int service_register(struct connman_service *service)
{
const char *path = __connman_profile_active_path();
+ GSequenceIter *iter;
DBG("service %p", service);
service_methods, service_signals,
NULL, service, NULL);
+ __connman_storage_load_service(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;
return CONNMAN_SERVICE_SECURITY_WEP;
else if (g_str_equal(security, "wpa") == TRUE)
return CONNMAN_SERVICE_SECURITY_WPA;
- else if (g_str_equal(security, "wpa2") == TRUE)
- return CONNMAN_SERVICE_SECURITY_WPA2;
+ else if (g_str_equal(security, "rsn") == TRUE)
+ return CONNMAN_SERVICE_SECURITY_RSN;
else
return CONNMAN_SERVICE_SECURITY_UNKNOWN;
}
if (str != NULL) {
g_free(service->name);
service->name = g_strdup(str);
+ service->hidden = FALSE;
+ } else {
+ g_free(service->name);
+ service->name = NULL;
+ service->hidden = TRUE;
}
service->strength = connman_network_get_uint8(network, "Strength");
if (service->strength > strength && service->network != NULL) {
connman_network_unref(service->network);
service->network = NULL;
+
+ strength_changed(service);
}
if (service->network == NULL) {
service->type = convert_network_type(network);
+ service->state = CONNMAN_SERVICE_STATE_IDLE;
+
update_from_network(service, network);
service_register(service);
GKeyFile *keyfile;
gchar *pathname, *data = NULL;
gsize length;
- char *str;
+ gchar *str;
DBG("service %p", service);
}
str = g_key_file_get_string(keyfile,
+ service->identifier, "Modified", NULL);
+ if (str != NULL) {
+ g_time_val_from_iso8601(str, &service->modified);
+ g_free(str);
+ }
+
+ str = g_key_file_get_string(keyfile,
service->identifier, "Passphrase", NULL);
if (str != NULL) {
g_free(service->passphrase);
GKeyFile *keyfile;
gchar *pathname, *data = NULL;
gsize length;
+ gchar *str;
DBG("service %p", service);
g_free(data);
update:
+ if (service->name != NULL)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Name", service->name);
+
switch (service->type) {
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_ETHERNET:
break;
}
+ str = g_time_val_to_iso8601(&service->modified);
+ if (str != NULL) {
+ g_key_file_set_string(keyfile, service->identifier,
+ "Modified", str);
+ g_free(str);
+ }
+
if (service->passphrase != NULL)
g_key_file_set_string(keyfile, service->identifier,
"Passphrase", service->passphrase);