From: Marcel Holtmann Date: Tue, 21 Apr 2009 03:03:05 +0000 (+0100) Subject: Create proper service interface abstraction X-Git-Tag: 0.16~60 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fb03c2b4bc0ab3e329ad797834131bea7cd15dc0;p=platform%2Fupstream%2Fconnman.git Create proper service interface abstraction --- diff --git a/include/service.h b/include/service.h index 17f46b8..f85c3b3 100644 --- a/include/service.h +++ b/include/service.h @@ -69,6 +69,10 @@ extern struct connman_service *connman_service_create(void); extern struct connman_service *connman_service_ref(struct connman_service *service); extern void connman_service_unref(struct connman_service *service); +extern int connman_service_set_favorite(struct connman_service *service, + connman_bool_t favorite); + +extern struct connman_service *connman_service_lookup(const char *identifier); extern struct connman_service *connman_service_get(const char *identifier); extern void connman_service_put(struct connman_service *service); diff --git a/src/connman.h b/src/connman.h index 67f7520..84bccaa 100644 --- a/src/connman.h +++ b/src/connman.h @@ -53,9 +53,10 @@ int __connman_profile_init(DBusConnection *conn); void __connman_profile_cleanup(void); void __connman_profile_list(DBusMessageIter *iter); -void __connman_profile_list_services(DBusMessageIter *iter); const char *__connman_profile_active(void); +void __connman_profile_changed(void); + #include int __connman_log_init(gboolean detach, gboolean debug); @@ -214,6 +215,14 @@ int __connman_profile_remove_network(struct connman_network *network); int __connman_service_init(void); void __connman_service_cleanup(void); +void __connman_service_list(DBusMessageIter *iter); + +struct connman_service *__connman_service_lookup_from_device(struct connman_device *device); +struct connman_service *__connman_service_create_from_device(struct connman_device *device); + +struct connman_service *__connman_service_lookup_from_network(struct connman_network *network); +struct connman_service *__connman_service_create_from_network(struct connman_network *network); + #include int __connman_notifier_init(void); diff --git a/src/manager.c b/src/manager.c index 4814f53..0a59057 100644 --- a/src/manager.c +++ b/src/manager.c @@ -105,7 +105,7 @@ static void append_services(DBusMessageIter *dict) dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - __connman_profile_list_services(&iter); + __connman_service_list(&iter); dbus_message_iter_close_container(&value, &iter); dbus_message_iter_close_container(&entry, &value); diff --git a/src/profile.c b/src/profile.c index 2afba3f..eeb777f 100644 --- a/src/profile.c +++ b/src/profile.c @@ -30,189 +30,8 @@ #define PROFILE_DEFAULT "/profile/default" -struct connman_group { - GSequenceIter *iter; - char *id; - char *path; - char *name; - char *mode; - char *security; - connman_uint8_t strength; - connman_bool_t favorite; - enum connman_service_type type; - enum connman_service_state state; - struct connman_network *network; -}; - -static GSequence *groups = NULL; - static DBusConnection *connection = NULL; -static const char *type2string(enum connman_service_type type) -{ - switch (type) { - case CONNMAN_SERVICE_TYPE_UNKNOWN: - break; - case CONNMAN_SERVICE_TYPE_ETHERNET: - return "ethernet"; - case CONNMAN_SERVICE_TYPE_WIFI: - return "wifi"; - case CONNMAN_SERVICE_TYPE_WIMAX: - return "wimax"; - } - - return NULL; -} - -static const char *state2string(enum connman_service_state state) -{ - switch (state) { - case CONNMAN_SERVICE_STATE_UNKNOWN: - break; - case CONNMAN_SERVICE_STATE_IDLE: - return "idle"; - case CONNMAN_SERVICE_STATE_ASSOCIATION: - return "association"; - case CONNMAN_SERVICE_STATE_CONFIGURATION: - return "configuration"; - case CONNMAN_SERVICE_STATE_READY: - return "ready"; - case CONNMAN_SERVICE_STATE_DISCONNECT: - return "disconnect"; - case CONNMAN_SERVICE_STATE_FAILURE: - return "failure"; - } - - return NULL; -} - -static DBusMessage *get_properties(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_group *group = data; - DBusMessage *reply; - DBusMessageIter array, dict; - const char *str; - - DBG("conn %p", conn); - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &array); - - dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - str = type2string(group->type); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Type", - DBUS_TYPE_STRING, &str); - - str = state2string(group->state); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "State", - DBUS_TYPE_STRING, &str); - - if (group->name != NULL) - connman_dbus_dict_append_variant(&dict, "Name", - DBUS_TYPE_STRING, &group->name); - - if (group->mode != NULL) - connman_dbus_dict_append_variant(&dict, "Mode", - DBUS_TYPE_STRING, &group->mode); - - if (group->security != NULL) - connman_dbus_dict_append_variant(&dict, "Security", - DBUS_TYPE_STRING, &group->security); - - if (group->strength > 0) - connman_dbus_dict_append_variant(&dict, "Strength", - DBUS_TYPE_BYTE, &group->strength); - - connman_dbus_dict_append_variant(&dict, "Favorite", - DBUS_TYPE_BOOLEAN, &group->favorite); - - dbus_message_iter_close_container(&array, &dict); - - return reply; -} - -static DBusMessage *connect_service(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_group *group = data; - - if (group->type == CONNMAN_SERVICE_TYPE_ETHERNET) - return __connman_error_not_supported(msg); - - return __connman_error_not_implemented(msg); -} - -static DBusMessage *disconnect_service(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_group *group = data; - - if (group->type == CONNMAN_SERVICE_TYPE_ETHERNET) - return __connman_error_not_supported(msg); - - return __connman_error_not_implemented(msg); -} - -static DBusMessage *remove_service(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_group *group = data; - - if (group->type == CONNMAN_SERVICE_TYPE_ETHERNET) - return __connman_error_not_supported(msg); - - group->favorite = FALSE; - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static DBusMessage *move_before(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_group *group = data; - - if (group->favorite == FALSE) - return __connman_error_not_supported(msg); - - return __connman_error_not_implemented(msg); -} - -static DBusMessage *move_after(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_group *group = data; - - if (group->favorite == FALSE) - return __connman_error_not_supported(msg); - - return __connman_error_not_implemented(msg); -} - -static GDBusMethodTable service_methods[] = { - { "GetProperties", "", "a{sv}", get_properties }, - { "Connect", "", "", connect_service }, - { "Disconnect", "", "", disconnect_service }, - { "Remove", "", "", remove_service }, - { "MoveBefore", "o", "", move_before }, - { "MoveAfter", "o", "", move_after }, - { }, -}; - -static GDBusSignalTable service_signals[] = { - { "PropertyChanged", "sv" }, - { }, -}; - const char *__connman_profile_active(void) { DBG(""); @@ -220,22 +39,6 @@ const char *__connman_profile_active(void) return PROFILE_DEFAULT; } -static void append_path(gpointer value, gpointer user_data) -{ - struct connman_group *group = value; - DBusMessageIter *iter = user_data; - - dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, - &group->path); -} - -void __connman_profile_list_services(DBusMessageIter *iter) -{ - DBG(""); - - g_sequence_foreach(groups, append_path, iter); -} - static void append_services(DBusMessageIter *entry) { DBusMessageIter value, iter; @@ -249,13 +52,13 @@ static void append_services(DBusMessageIter *entry) dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - __connman_profile_list_services(&iter); + __connman_service_list(&iter); dbus_message_iter_close_container(&value, &iter); dbus_message_iter_close_container(entry, &value); } -static void emit_services_signal(void) +void __connman_profile_changed(void) { const char *path = __connman_profile_active(); DBusMessage *signal; @@ -280,149 +83,30 @@ static void emit_services_signal(void) g_dbus_send_message(connection, signal); } -static void free_group(gpointer data) -{ - struct connman_group *group = data; - - DBG("group %p", group); - - g_dbus_unregister_interface(connection, group->path, - CONNMAN_SERVICE_INTERFACE); - - g_free(group->security); - g_free(group->mode); - g_free(group->name); - g_free(group->path); - g_free(group->id); - g_free(group); -} - -static gint compare_group(gconstpointer a, gconstpointer b, gpointer user_data) -{ - struct connman_group *group_a = (void *) a; - struct connman_group *group_b = (void *) b; - - if (group_a->favorite == TRUE && group_b->favorite == FALSE) - return -1; - - if (group_a->favorite == FALSE && group_b->favorite == TRUE) - return 1; - - return (gint) group_b->strength - (gint) group_a->strength; -} - -static struct connman_group *lookup_group(const char *name) -{ - GSequenceIter *iter; - struct connman_group *group; - - DBG("name %s", name); - - if (name == NULL) - return NULL; - - iter = g_sequence_get_begin_iter(groups); - while (g_sequence_iter_is_end(iter) == FALSE) { - group = g_sequence_get(iter); - - if (g_strcmp0(group->id, name) == 0) - goto done; - - iter = g_sequence_iter_next(iter); - } - - group = g_try_new0(struct connman_group, 1); - if (group == NULL) - return NULL; - - group->id = g_strdup(name); - - group->type = CONNMAN_SERVICE_TYPE_UNKNOWN; - group->path = g_strdup_printf("%s/%s", PROFILE_DEFAULT, name); - - group->favorite = FALSE; - - group->state = CONNMAN_SERVICE_STATE_IDLE; - - group->iter = g_sequence_insert_sorted(groups, group, - compare_group, NULL); - - g_dbus_register_interface(connection, group->path, - CONNMAN_SERVICE_INTERFACE, - service_methods, service_signals, - NULL, group, NULL); - -done: - DBG("group %p", group); - - return group; -} - -static enum connman_service_type convert_device_type(struct connman_device *device) -{ - enum connman_device_type type = connman_device_get_type(device); - - switch (type) { - case CONNMAN_DEVICE_TYPE_UNKNOWN: - case CONNMAN_DEVICE_TYPE_VENDOR: - case CONNMAN_DEVICE_TYPE_WIFI: - case CONNMAN_DEVICE_TYPE_WIMAX: - case CONNMAN_DEVICE_TYPE_BLUETOOTH: - case CONNMAN_DEVICE_TYPE_GPS: - case CONNMAN_DEVICE_TYPE_HSO: - case CONNMAN_DEVICE_TYPE_NOZOMI: - case CONNMAN_DEVICE_TYPE_HUAWEI: - case CONNMAN_DEVICE_TYPE_NOVATEL: - break; - case CONNMAN_DEVICE_TYPE_ETHERNET: - return CONNMAN_SERVICE_TYPE_ETHERNET; - } - - return CONNMAN_SERVICE_TYPE_UNKNOWN; -} - int __connman_profile_add_device(struct connman_device *device) { - struct connman_group *group; - char *name; + struct connman_service *service; DBG("device %p", device); - name = g_strdup_printf("%s_%d", __connman_device_get_type(device), - connman_device_get_index(device)); - group = lookup_group(name); - g_free(name); - - if (group == NULL) + service = __connman_service_create_from_device(device); + if (service == NULL) return -EINVAL; - group->type = convert_device_type(device); - - g_sequence_sort_changed(group->iter, compare_group, NULL); - emit_services_signal(); - return 0; } int __connman_profile_remove_device(struct connman_device *device) { - struct connman_group *group; - char *name; + struct connman_service *service; DBG("device %p", device); - name = g_strdup_printf("%s_%d", __connman_device_get_type(device), - connman_device_get_index(device)); - group = lookup_group(name); - g_free(name); - - if (group == NULL) + service = __connman_service_lookup_from_device(device); + if (service == NULL) return -EINVAL; - group->type = CONNMAN_SERVICE_TYPE_UNKNOWN; - - g_sequence_sort_changed(group->iter, compare_group, NULL); - emit_services_signal(); + connman_service_put(service); return 0; } @@ -430,122 +114,41 @@ int __connman_profile_remove_device(struct connman_device *device) int __connman_profile_set_carrier(struct connman_device *device, connman_bool_t carrier) { - struct connman_group *group; - char *name; + struct connman_service *service; DBG("device %p carrier %d", device, carrier); - name = g_strdup_printf("%s_%d", __connman_device_get_type(device), - connman_device_get_index(device)); - group = lookup_group(name); - g_free(name); - - if (group == NULL) + service = __connman_service_lookup_from_device(device); + if (service == NULL) return -EINVAL; - if (group->favorite == carrier) - return -EALREADY; - - group->favorite = carrier; - - g_sequence_sort_changed(group->iter, compare_group, NULL); - emit_services_signal(); - - return 0; -} - -static enum connman_service_type convert_network_type(struct connman_network *network) -{ - enum connman_network_type type = connman_network_get_type(network); - - switch (type) { - case CONNMAN_NETWORK_TYPE_UNKNOWN: - case CONNMAN_NETWORK_TYPE_VENDOR: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_HSO: - break; - case CONNMAN_NETWORK_TYPE_WIFI: - return CONNMAN_SERVICE_TYPE_WIFI; - case CONNMAN_NETWORK_TYPE_WIMAX: - return CONNMAN_SERVICE_TYPE_WIMAX; - } - - return CONNMAN_SERVICE_TYPE_UNKNOWN; + return connman_service_set_favorite(service, carrier); } int __connman_profile_add_network(struct connman_network *network) { - struct connman_group *group; - char *name; + struct connman_service *service; DBG("network %p", network); - if (__connman_network_get_group(network) == NULL) + service = __connman_service_create_from_network(network); + if (service == NULL) return -EINVAL; - name = g_strdup_printf("%s_%s", __connman_network_get_type(network), - __connman_network_get_group(network)); - group = lookup_group(name); - g_free(name); - - if (group == NULL) - return -EINVAL; - - group->type = convert_network_type(network); - - g_free(group->name); - group->name = g_strdup(connman_network_get_string(network, "Name")); - - group->strength = connman_network_get_uint8(network, "Strength"); - - if (group->network == NULL) { - group->network = network; - - group->mode = g_strdup(connman_network_get_string(network, - "WiFi.Mode")); - group->security = g_strdup(connman_network_get_string(network, - "WiFi.Security")); - } - - g_sequence_sort_changed(group->iter, compare_group, NULL); - emit_services_signal(); - return 0; } int __connman_profile_remove_network(struct connman_network *network) { - struct connman_group *group; - char *name; + struct connman_service *service; DBG("network %p", network); - if (__connman_network_get_group(network) == NULL) + service = __connman_service_lookup_from_network(network); + if (service == NULL) return -EINVAL; - name = g_strdup_printf("%s_%s", __connman_network_get_type(network), - __connman_network_get_group(network)); - group = lookup_group(name); - g_free(name); - - if (group == NULL) - return -EINVAL; - - if (group->network == network) { - g_free(group->security); - group->security = NULL; - - g_free(group->mode); - group->mode = NULL; - - group->network = NULL; - } - - group->type = CONNMAN_SERVICE_TYPE_UNKNOWN; - - g_sequence_sort_changed(group->iter, compare_group, NULL); - emit_services_signal(); + connman_service_put(service); return 0; } @@ -559,7 +162,7 @@ void __connman_profile_list(DBusMessageIter *iter) dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); } -static DBusMessage *profile_properties(DBusConnection *conn, +static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { const char *name = "Default"; @@ -593,7 +196,7 @@ static DBusMessage *profile_properties(DBusConnection *conn, } static GDBusMethodTable profile_methods[] = { - { "GetProperties", "", "a{sv}", profile_properties }, + { "GetProperties", "", "a{sv}", get_properties }, { }, }; @@ -610,8 +213,6 @@ int __connman_profile_init(DBusConnection *conn) if (connection == NULL) return -1; - groups = g_sequence_new(free_group); - g_dbus_register_interface(connection, PROFILE_DEFAULT, CONNMAN_PROFILE_INTERFACE, profile_methods, profile_signals, @@ -627,9 +228,6 @@ void __connman_profile_cleanup(void) g_dbus_unregister_interface(connection, PROFILE_DEFAULT, CONNMAN_PROFILE_INTERFACE); - g_sequence_free(groups); - groups = NULL; - if (connection == NULL) return; diff --git a/src/service.c b/src/service.c index b921f5f..6ecff7d 100644 --- a/src/service.c +++ b/src/service.c @@ -23,6 +23,8 @@ #include #endif +#include + #include "connman.h" static DBusConnection *connection = NULL; @@ -40,23 +42,259 @@ struct connman_service { enum connman_service_state state; connman_uint8_t strength; connman_bool_t favorite; + unsigned int order; char *name; + struct connman_device *device; +}; + +static void append_path(gpointer value, gpointer user_data) +{ + struct connman_service *service = value; + DBusMessageIter *iter = user_data; + + if (service->path == NULL) + return; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, + &service->path); +} + +void __connman_service_list(DBusMessageIter *iter) +{ + DBG(""); + + g_sequence_foreach(service_list, append_path, iter); +} + +static const char *type2string(enum connman_service_type type) +{ + switch (type) { + case CONNMAN_SERVICE_TYPE_UNKNOWN: + break; + case CONNMAN_SERVICE_TYPE_ETHERNET: + return "ethernet"; + case CONNMAN_SERVICE_TYPE_WIFI: + return "wifi"; + case CONNMAN_SERVICE_TYPE_WIMAX: + return "wimax"; + } + + return NULL; +} + +static const char *mode2string(enum connman_service_mode mode) +{ + switch (mode) { + case CONNMAN_SERVICE_MODE_UNKNOWN: + break; + case CONNMAN_SERVICE_MODE_MANAGED: + return "managed"; + case CONNMAN_SERVICE_MODE_ADHOC: + return "adhoc"; + } + + return NULL; +} + +static const char *security2string(enum connman_service_security security) +{ + switch (security) { + case CONNMAN_SERVICE_SECURITY_UNKNOWN: + break; + case CONNMAN_SERVICE_SECURITY_NONE: + return "none"; + case CONNMAN_SERVICE_SECURITY_WEP: + return "wep"; + case CONNMAN_SERVICE_SECURITY_WPA: + return "wpa"; + case CONNMAN_SERVICE_SECURITY_WPA2: + return "wpa2"; + } + + return NULL; +} + +static const char *state2string(enum connman_service_state state) +{ + switch (state) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + break; + case CONNMAN_SERVICE_STATE_IDLE: + return "idle"; + case CONNMAN_SERVICE_STATE_ASSOCIATION: + return "association"; + case CONNMAN_SERVICE_STATE_CONFIGURATION: + return "configuration"; + case CONNMAN_SERVICE_STATE_READY: + return "ready"; + case CONNMAN_SERVICE_STATE_DISCONNECT: + return "disconnect"; + case CONNMAN_SERVICE_STATE_FAILURE: + return "failure"; + } + + return NULL; +} + +static DBusMessage *get_properties(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_service *service = data; + DBusMessage *reply; + DBusMessageIter array, dict; + const char *str; + + DBG("conn %p", conn); + + reply = dbus_message_new_method_return(msg); + if (reply == NULL) + return NULL; + + dbus_message_iter_init_append(reply, &array); + + dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + str = type2string(service->type); + if (str != NULL) + connman_dbus_dict_append_variant(&dict, "Type", + DBUS_TYPE_STRING, &str); + + str = mode2string(service->mode); + if (str != NULL) + connman_dbus_dict_append_variant(&dict, "Mode", + DBUS_TYPE_STRING, &str); + + str = security2string(service->security); + if (str != NULL) + connman_dbus_dict_append_variant(&dict, "Security", + DBUS_TYPE_STRING, &str); + + str = state2string(service->state); + if (str != NULL) + connman_dbus_dict_append_variant(&dict, "State", + DBUS_TYPE_STRING, &str); + + if (service->strength > 0) + connman_dbus_dict_append_variant(&dict, "Strength", + DBUS_TYPE_BYTE, &service->strength); + + connman_dbus_dict_append_variant(&dict, "Favorite", + DBUS_TYPE_BOOLEAN, &service->favorite); + + if (service->name != NULL) + connman_dbus_dict_append_variant(&dict, "Name", + DBUS_TYPE_STRING, &service->name); + + dbus_message_iter_close_container(&array, &dict); + + return reply; +} + +static DBusMessage *connect_service(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_service *service = data; + + if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET) + return __connman_error_not_supported(msg); + + return __connman_error_not_implemented(msg); +} + +static DBusMessage *disconnect_service(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_service *service = data; + + if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET) + return __connman_error_not_supported(msg); + + return __connman_error_not_implemented(msg); +} + +static DBusMessage *remove_service(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_service *service = data; + + if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET) + return __connman_error_not_supported(msg); + + service->favorite = FALSE; + + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); +} + +static DBusMessage *move_before(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_service *service = data; + + if (service->favorite == FALSE) + return __connman_error_not_supported(msg); + + return __connman_error_not_implemented(msg); +} + +static DBusMessage *move_after(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_service *service = data; + + if (service->favorite == FALSE) + return __connman_error_not_supported(msg); + + return __connman_error_not_implemented(msg); +} + +static GDBusMethodTable service_methods[] = { + { "GetProperties", "", "a{sv}", get_properties }, + { "Connect", "", "", connect_service }, + { "Disconnect", "", "", disconnect_service }, + { "Remove", "", "", remove_service }, + { "MoveBefore", "o", "", move_before }, + { "MoveAfter", "o", "", move_after }, + { }, +}; + +static GDBusSignalTable service_signals[] = { + { "PropertyChanged", "sv" }, + { }, }; static void service_free(gpointer data) { struct connman_service *service = data; + char *path = service->path; DBG("service %p", service); g_hash_table_remove(service_hash, service->identifier); + service->path = NULL; + + if (path != NULL) { + __connman_profile_changed(); + + g_dbus_unregister_interface(connection, path, + CONNMAN_SERVICE_INTERFACE); + g_free(path); + } + g_free(service->name); - g_free(service->path); g_free(service->identifier); g_free(service); } +/** + * connman_service_put: + * @service: service structure + * + * Release service if no longer needed + */ void connman_service_put(struct connman_service *service) { DBG("service %p", service); @@ -84,6 +322,8 @@ static void __connman_service_initialize(struct connman_service *service) service->state = CONNMAN_SERVICE_STATE_UNKNOWN; service->favorite = FALSE; + + service->order = 0; } /** @@ -138,6 +378,12 @@ 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->order > service_b->order) + return -1; + + if (service_a->order < service_b->order) + return 1; + if (service_a->favorite == TRUE && service_b->favorite == FALSE) return -1; @@ -147,6 +393,57 @@ static gint service_compare(gconstpointer a, gconstpointer b, return (gint) service_b->strength - (gint) service_a->strength; } +/** + * connman_service_set_favorite: + * @service: service structure + * @favorite: favorite value + * + * Change the favorite setting of service + */ +int connman_service_set_favorite(struct connman_service *service, + connman_bool_t favorite) +{ + GSequenceIter *iter; + + iter = g_hash_table_lookup(service_hash, service->identifier); + if (iter == NULL) + return -ENOENT; + + if (service->favorite) + return -EALREADY; + + service->favorite = favorite; + + g_sequence_sort_changed(iter, service_compare, NULL); + + __connman_profile_changed(); + + return 0; +} + +/** + * connman_service_lookup: + * @identifier: service identifier + * + * Look up a service by identifier (reference count will not be increased) + */ +struct connman_service *connman_service_lookup(const char *identifier) +{ + GSequenceIter *iter; + + iter = g_hash_table_lookup(service_hash, identifier); + if (iter != NULL) + return g_sequence_get(iter); + + return NULL; +} + +/** + * connman_service_get: + * @identifier: service identifier + * + * Look up a service by identifier or create a new one if not found + */ struct connman_service *connman_service_get(const char *identifier) { struct connman_service *service; @@ -178,6 +475,180 @@ struct connman_service *connman_service_get(const char *identifier) return service; } +static int service_register(struct connman_service *service) +{ + const char *path = __connman_profile_active(); + + if (service->path != NULL) + return -EALREADY; + + service->path = g_strdup_printf("%s/%s", path, service->identifier); + + g_dbus_register_interface(connection, service->path, + CONNMAN_SERVICE_INTERFACE, + service_methods, service_signals, + NULL, service, NULL); + + __connman_profile_changed(); + + return 0; +} + +/** + * connman_service_lookup_from_device: + * @device: device structure + * + * Look up a service by device (reference count will not be increased) + */ +struct connman_service *__connman_service_lookup_from_device(struct connman_device *device) +{ + struct connman_service *service; + char *name; + + name = g_strdup_printf("%s_%d", __connman_device_get_type(device), + connman_device_get_index(device)); + + service = connman_service_lookup(name); + + g_free(name); + + return service; +} + +static enum connman_service_type convert_device_type(struct connman_device *device) +{ + enum connman_device_type type = connman_device_get_type(device); + + switch (type) { + case CONNMAN_DEVICE_TYPE_UNKNOWN: + case CONNMAN_DEVICE_TYPE_VENDOR: + case CONNMAN_DEVICE_TYPE_WIFI: + case CONNMAN_DEVICE_TYPE_WIMAX: + case CONNMAN_DEVICE_TYPE_BLUETOOTH: + case CONNMAN_DEVICE_TYPE_GPS: + case CONNMAN_DEVICE_TYPE_HSO: + case CONNMAN_DEVICE_TYPE_NOZOMI: + case CONNMAN_DEVICE_TYPE_HUAWEI: + case CONNMAN_DEVICE_TYPE_NOVATEL: + break; + case CONNMAN_DEVICE_TYPE_ETHERNET: + return CONNMAN_SERVICE_TYPE_ETHERNET; + } + + return CONNMAN_SERVICE_TYPE_UNKNOWN; +} + +/** + * connman_service_create_from_device: + * @device: device structure + * + * Look up service by device and if not found, create one + */ +struct connman_service *__connman_service_create_from_device(struct connman_device *device) +{ + struct connman_service *service; + char *name; + + name = g_strdup_printf("%s_%d", __connman_device_get_type(device), + connman_device_get_index(device)); + + service = connman_service_get(name); + if (service == NULL) + goto done; + + if (service->path != NULL) { + connman_service_put(service); + service = NULL; + goto done; + } + + service->type = convert_device_type(device); + + service->device = device; + + service_register(service); + +done: + g_free(name); + + return service; +} + +/** + * connman_service_lookup_from_network: + * @device: device structure + * + * Look up a service by network (reference count will not be increased) + */ +struct connman_service *__connman_service_lookup_from_network(struct connman_network *network) +{ + struct connman_service *service; + char *name; + + name = g_strdup_printf("%s_%s", __connman_network_get_type(network), + __connman_network_get_group(network)); + + service = connman_service_lookup(name); + + g_free(name); + + return service; +} + +static enum connman_service_type convert_network_type(struct connman_network *network) +{ + enum connman_network_type type = connman_network_get_type(network); + + switch (type) { + case CONNMAN_NETWORK_TYPE_UNKNOWN: + case CONNMAN_NETWORK_TYPE_VENDOR: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: + case CONNMAN_NETWORK_TYPE_HSO: + break; + case CONNMAN_NETWORK_TYPE_WIFI: + return CONNMAN_SERVICE_TYPE_WIFI; + case CONNMAN_NETWORK_TYPE_WIMAX: + return CONNMAN_SERVICE_TYPE_WIMAX; + } + + return CONNMAN_SERVICE_TYPE_UNKNOWN; +} + +/** + * connman_service_create_from_network: + * @device: device structure + * + * Look up service by network and if not found, create one + */ +struct connman_service *__connman_service_create_from_network(struct connman_network *network) +{ + struct connman_service *service; + char *name; + + name = g_strdup_printf("%s_%s", __connman_network_get_type(network), + __connman_network_get_group(network)); + + service = connman_service_get(name); + if (service == NULL) + goto done; + + if (service->path != NULL) { + connman_service_put(service); + service = NULL; + goto done; + } + + service->type = convert_network_type(network); + + service_register(service); + +done: + g_free(name); + + return service; +} + int __connman_service_init(void) { DBG("");