diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2008-01-07 13:01:02 +0100 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2008-01-07 13:01:02 +0100 |
commit | 9342ced42e836f1af023bca0a196bf97fc0db2ff (patch) | |
tree | 297324d81939c48f3e07cb3835126da9621d01fa | |
parent | 2ab94f9d3f5b40470b337044de77b37e6d84e098 (diff) | |
download | connman-gnome-9342ced42e836f1af023bca0a196bf97fc0db2ff.tar.gz |
Add common client implementation and example application
-rw-r--r-- | common/Makefile.am | 6 | ||||
-rw-r--r-- | common/client.c | 608 | ||||
-rw-r--r-- | common/client.h | 70 | ||||
-rw-r--r-- | common/test-client.c | 436 |
4 files changed, 1119 insertions, 1 deletions
diff --git a/common/Makefile.am b/common/Makefile.am index b15a480..57b99d8 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,7 +1,11 @@ noinst_LIBRARIES = libcommon.a -libcommon_a_SOURCES = +libcommon_a_SOURCES = client.h client.c + +noinst_PROGRAMS = test-client + +test_client_LDADD = libcommon.a @GTK_LIBS@ @DBUS_LIBS@ AM_CFLAGS = @DBUS_CFLAGS@ @GTK_CFLAGS@ diff --git a/common/client.c b/common/client.c new file mode 100644 index 0000000..772777e --- /dev/null +++ b/common/client.c @@ -0,0 +1,608 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> + +#include <dbus/dbus-glib.h> + +#include <gtk/gtk.h> + +#include "client.h" + +#ifndef DBYS_TYPE_G_OBJECT_PATH_ARRAY +#define DBUS_TYPE_G_OBJECT_PATH_ARRAY \ + (dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH)) +#endif + +#define CONNMAN_SERVICE "org.freedesktop.connman" +#define CONNMAN_MANAGER CONNMAN_SERVICE ".Manager" +#define CONNMAN_INTERFACE CONNMAN_SERVICE ".Interface" + +static GtkTreeStore *store = NULL; + +static guint string_to_type(const char *type) +{ + if (g_ascii_strcasecmp(type, "80203") == 0) + return CLIENT_TYPE_80203; + else if (g_ascii_strcasecmp(type, "80211") == 0) + return CLIENT_TYPE_80211; + else + return CLIENT_TYPE_UNKNOWN; +} + +static guint string_to_state(const char *state) +{ + if (g_ascii_strcasecmp(state, "offline") == 0) + return CLIENT_STATE_OFFLINE; + else if (g_ascii_strcasecmp(state, "ready") == 0) + return CLIENT_STATE_READY; + else + return CLIENT_STATE_UNKNOWN; +} + +static guint string_to_policy(const char *policy) +{ + if (g_ascii_strcasecmp(policy, "off") == 0) + return CLIENT_POLICY_OFF; + else if (g_ascii_strcasecmp(policy, "ignore") == 0) + return CLIENT_POLICY_IGNORE; + else if (g_ascii_strcasecmp(policy, "auto") == 0) + return CLIENT_POLICY_AUTO; + else + return CLIENT_POLICY_UNKNOWN; +} + +static const char *policy_to_string(guint policy) +{ + switch (policy) { + case CLIENT_POLICY_OFF: + return "off"; + case CLIENT_POLICY_IGNORE: + return "ignore"; + case CLIENT_POLICY_AUTO: + return "auto"; + default: + return "unknown"; + } +} + +static guint string_to_ipv4_method(const char *method) +{ + if (g_ascii_strcasecmp(method, "off") == 0) + return CLIENT_IPV4_METHOD_OFF; + else if (g_ascii_strcasecmp(method, "static") == 0) + return CLIENT_IPV4_METHOD_STATIC; + else if (g_ascii_strcasecmp(method, "dhcp") == 0) + return CLIENT_IPV4_METHOD_DHCP; + else + return CLIENT_IPV4_METHOD_UNKNOWN; +} + +static const char *ipv4_method_to_string(guint method) +{ + switch (method) { + case CLIENT_IPV4_METHOD_OFF: + return "off"; + case CLIENT_IPV4_METHOD_STATIC: + return "static"; + case CLIENT_IPV4_METHOD_DHCP: + return "dhcp"; + default: + return "unknown"; + } +} + +static void handle_ipv4(GHashTable *hash, GtkTreeIter *iter) +{ + GValue *value; + const char *str; + + value = g_hash_table_lookup(hash, "Method"); + if (value != NULL) { + str = g_value_get_string(value); + gtk_tree_store_set(store, iter, CLIENT_COLUMN_IPV4_METHOD, + string_to_ipv4_method(str), -1); + } + + value = g_hash_table_lookup(hash, "Address"); + if (value != NULL) { + str = g_value_get_string(value); + gtk_tree_store_set(store, iter, + CLIENT_COLUMN_IPV4_ADDRESS, str, -1); + } + + value = g_hash_table_lookup(hash, "Netmask"); + if (value != NULL) { + str = g_value_get_string(value); + gtk_tree_store_set(store, iter, + CLIENT_COLUMN_IPV4_NETMASK, str, -1); + } + + value = g_hash_table_lookup(hash, "Gateway"); + if (value != NULL) { + str = g_value_get_string(value); + gtk_tree_store_set(store, iter, + CLIENT_COLUMN_IPV4_GATEWAY, str, -1); + } +} + +static void ipv4_notify(DBusGProxy *object, + DBusGProxyCall *call, void *user_data) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + GError *error = NULL; + GHashTable *hash = NULL; + + dbus_g_proxy_end_call(object, call, &error, + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + + if (error != NULL) { + g_printerr("Getting interface address failed: %s\n", + error->message); + g_error_free(error); + return; + } + + if (hash == NULL) + return; + + if (gtk_tree_model_get_iter_from_string(model, &iter, + user_data) == FALSE) + return; + + handle_ipv4(hash, &iter); +} + +static void properties_notify(DBusGProxy *object, + DBusGProxyCall *call, void *user_data) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + GError *error = NULL; + GHashTable *hash = NULL; + GValue *value; + const char *str; + guint type = CLIENT_TYPE_UNKNOWN; + guint state = CLIENT_STATE_UNKNOWN; + guint signal = 0; + guint policy = CLIENT_POLICY_UNKNOWN; + const gchar *driver, *vendor, *product; + + dbus_g_proxy_end_call(object, call, &error, + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + + if (error != NULL) { + g_printerr("Getting interface properties failed: %s\n", + error->message); + g_error_free(error); + return; + } + + if (hash == NULL) + return; + + if (gtk_tree_model_get_iter_from_string(model, &iter, + user_data) == FALSE) + return; + + value = g_hash_table_lookup(hash, "Type"); + if (value != NULL) { + str = g_value_get_string(value); + type = string_to_type(str); + } + + value = g_hash_table_lookup(hash, "Driver"); + driver = value ? g_value_get_string(value) : NULL; + + value = g_hash_table_lookup(hash, "Vendor"); + vendor = value ? g_value_get_string(value) : NULL; + + value = g_hash_table_lookup(hash, "Product"); + product = value ? g_value_get_string(value) : NULL; + + value = g_hash_table_lookup(hash, "State"); + if (value != NULL) { + str = g_value_get_string(value); + state = string_to_state(str); + } + + value = g_hash_table_lookup(hash, "Signal"); + if (value != NULL) + signal = g_value_get_uint(value); + + value = g_hash_table_lookup(hash, "Policy"); + if (value != NULL) { + str = g_value_get_string(value); + policy = string_to_policy(str); + } + + gtk_tree_store_set(store, &iter, CLIENT_COLUMN_TYPE, type, + CLIENT_COLUMN_DRIVER, driver, + CLIENT_COLUMN_VENDOR, vendor, + CLIENT_COLUMN_PRODUCT, product, + CLIENT_COLUMN_STATE, state, + CLIENT_COLUMN_SIGNAL, signal, + CLIENT_COLUMN_POLICY, policy, -1); +} + +static void update_interface(DBusGProxy *proxy, + GtkTreeModel *model, GtkTreeIter *iter) +{ + DBusGProxyCall *call; + gchar *index; + + index = gtk_tree_model_get_string_from_iter(model, iter); + + call = dbus_g_proxy_begin_call_with_timeout(proxy, + "GetProperties", properties_notify, + index, g_free, 2000, G_TYPE_INVALID); + + index = gtk_tree_model_get_string_from_iter(model, iter); + + call = dbus_g_proxy_begin_call_with_timeout(proxy, + "GetIPv4", ipv4_notify, + index, g_free, 2000, G_TYPE_INVALID); +} + +static void state_changed(DBusGProxy *system, const char *state, + gpointer user_data) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter_from_string(model, &iter, + user_data) == FALSE) + return; + + gtk_tree_store_set(store, &iter, CLIENT_COLUMN_STATE, + string_to_state(state), -1); +} + +static void signal_changed(DBusGProxy *system, unsigned int signal, + gpointer user_data) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter_from_string(model, &iter, + user_data) == FALSE) + return; + + gtk_tree_store_set(store, &iter, CLIENT_COLUMN_SIGNAL, signal, -1); +} + +static void policy_changed(DBusGProxy *system, const char *policy, + gpointer user_data) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter_from_string(model, &iter, + user_data) == FALSE) + return; + + gtk_tree_store_set(store, &iter, CLIENT_COLUMN_POLICY, + string_to_policy(policy), -1); +} + +static void ipv4_changed(DBusGProxy *system, GHashTable *hash, + gpointer user_data) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter_from_string(model, &iter, + user_data) == FALSE) + return; + + handle_ipv4(hash, &iter); +} + +static void signal_closure(gpointer user_data, GClosure *closure) +{ + g_free(user_data); +} + +static void add_interface(DBusGProxy *manager, const char *path) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + DBusGProxy *proxy; + gchar *index; + gboolean cont; + + cont = gtk_tree_model_get_iter_first(model, &iter); + + while (cont == TRUE) { + const char *object_path; + + gtk_tree_model_get(model, &iter, + CLIENT_COLUMN_PROXY, &proxy, -1); + if (proxy == NULL) + continue; + + object_path = dbus_g_proxy_get_path(proxy); + + g_object_unref(proxy); + + if (strcmp(object_path, path) == 0) { + gtk_tree_store_set(store, &iter, + CLIENT_COLUMN_ACTIVE, TRUE, -1); + update_interface(proxy, model, &iter); + return; + } + + cont = gtk_tree_model_iter_next(model, &iter); + } + + proxy = dbus_g_proxy_new_from_proxy(manager, CONNMAN_INTERFACE, path); + + gtk_tree_store_insert_with_values(store, &iter, NULL, -1, + CLIENT_COLUMN_ACTIVE, TRUE, + CLIENT_COLUMN_PROXY, proxy, -1); + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + dbus_g_proxy_add_signal(proxy, "StateChanged", + G_TYPE_STRING, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(proxy, "StateChanged", + G_CALLBACK(state_changed), index, signal_closure); + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + dbus_g_proxy_add_signal(proxy, "SignalChanged", + G_TYPE_UINT, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(proxy, "SignalChanged", + G_CALLBACK(signal_changed), index, signal_closure); + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + dbus_g_proxy_add_signal(proxy, "PolicyChanged", + G_TYPE_STRING, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(proxy, "PolicyChanged", + G_CALLBACK(policy_changed), index, signal_closure); + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + dbus_g_proxy_add_signal(proxy, "IPv4Changed", + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(proxy, "IPv4Changed", + G_CALLBACK(ipv4_changed), index, signal_closure); + + update_interface(proxy, model, &iter); +} + +static void interface_added(DBusGProxy *manager, const char *path, + gpointer user_data) +{ + add_interface(manager, path); +} + +static gboolean disable_interface(GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, gpointer user_data) +{ + DBusGProxy *proxy; + const char *object_path; + + if (user_data == NULL) { + gtk_tree_store_set(GTK_TREE_STORE(model), iter, + CLIENT_COLUMN_ACTIVE, FALSE, -1); + return FALSE; + } + + gtk_tree_model_get(model, iter, CLIENT_COLUMN_PROXY, &proxy, -1); + if (proxy == NULL) + return FALSE; + + object_path = dbus_g_proxy_get_path(proxy); + + g_object_unref(proxy); + + if (strcmp(object_path, user_data) == 0) { + gtk_tree_store_set(GTK_TREE_STORE(model), iter, + CLIENT_COLUMN_ACTIVE, FALSE, -1); + return TRUE; + } + + return FALSE; +} + +static void interface_removed(DBusGProxy *manager, const char *path, + gpointer user_data) +{ + gtk_tree_model_foreach(GTK_TREE_MODEL(store), + disable_interface, (gpointer) path); +} + +static DBusGProxy *create_manager(DBusGConnection *conn) +{ + DBusGProxy *manager; + GError *error = NULL; + GPtrArray *array = NULL; + + manager = dbus_g_proxy_new_for_name(conn, CONNMAN_SERVICE, + "/", CONNMAN_MANAGER); + + dbus_g_proxy_call(manager, "ListInterfaces", &error, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH_ARRAY, &array, G_TYPE_INVALID); + + if (error == NULL) { + int i; + + for (i = 0; i < array->len; i++) { + gchar *path = g_ptr_array_index(array, i); + add_interface(manager, path); + g_free(path); + } + } else + g_error_free(error); + + dbus_g_proxy_add_signal(manager, "InterfaceAdded", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(manager, "InterfaceAdded", + G_CALLBACK(interface_added), NULL, NULL); + + dbus_g_proxy_add_signal(manager, "InterfaceRemoved", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(manager, "InterfaceRemoved", + G_CALLBACK(interface_removed), NULL, NULL); + + return manager; +} + +static void name_owner_changed(DBusGProxy *system, const char *name, + const char *prev, const char *new, gpointer user_data) +{ + if (strcmp(name, CONNMAN_SERVICE) == 0 && *new == '\0') + gtk_tree_model_foreach(GTK_TREE_MODEL(store), + disable_interface, NULL); +} + +static DBusGProxy *create_system(DBusGConnection *conn) +{ + DBusGProxy *system; + + system = dbus_g_proxy_new_for_name(conn, DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + + dbus_g_proxy_add_signal(system, "NameOwnerChanged", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(system, "NameOwnerChanged", + G_CALLBACK(name_owner_changed), NULL, NULL); + + return system; +} + +static DBusGConnection *connection; +static DBusGProxy *system, *manager; + +gboolean client_init(GError **error) +{ + GError *dbus_error = NULL; + + connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &dbus_error); + if (dbus_error != NULL) { + g_error_free(dbus_error); + return FALSE; + } + + store = gtk_tree_store_new(13, G_TYPE_BOOLEAN, DBUS_TYPE_G_PROXY, + G_TYPE_UINT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + system = create_system(connection); + + manager = create_manager(connection); + + return TRUE; +} + +void client_cleanup(void) +{ + g_object_unref(manager); + + g_object_unref(system); + + g_object_unref(store); + + dbus_g_connection_unref(connection); +} + +GtkTreeModel *client_get_model(void) +{ + return gtk_tree_model_filter_new(GTK_TREE_MODEL(store), NULL); +} + +void client_set_policy(const gchar *index, guint policy) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + DBusGProxy *proxy; + + if (gtk_tree_model_get_iter_from_string(model, &iter, index) == FALSE) + return; + + gtk_tree_model_get(model, &iter, CLIENT_COLUMN_PROXY, &proxy, -1); + if (proxy == NULL) + return; + + dbus_g_proxy_call_no_reply(proxy, "SetPolicy", G_TYPE_STRING, + policy_to_string(policy), G_TYPE_INVALID); + + g_object_unref(proxy); +} + +static void value_free(GValue *value) +{ + g_value_unset(value); + g_free(value); +} + +void client_set_ipv4(const gchar *index, guint method) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter iter; + DBusGProxy *proxy; + GHashTable *hash = NULL; + GValue *value; + + if (gtk_tree_model_get_iter_from_string(model, &iter, index) == FALSE) + return; + + gtk_tree_model_get(model, &iter, CLIENT_COLUMN_PROXY, &proxy, -1); + if (proxy == NULL) + return; + + hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, (GDestroyNotify) value_free); + + value = g_new0(GValue, 1); + g_value_init(value, G_TYPE_STRING); + g_value_set_string(value, ipv4_method_to_string(method)); + g_hash_table_insert(hash, g_strdup ("Method"), value); + + dbus_g_proxy_call_no_reply(proxy, "SetIPv4", + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + hash, G_TYPE_INVALID); + + g_object_unref(proxy); +} diff --git a/common/client.h b/common/client.h new file mode 100644 index 0000000..54d2bd0 --- /dev/null +++ b/common/client.h @@ -0,0 +1,70 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +enum { + CLIENT_COLUMN_ACTIVE, + CLIENT_COLUMN_PROXY, + CLIENT_COLUMN_TYPE, + CLIENT_COLUMN_DRIVER, + CLIENT_COLUMN_VENDOR, + CLIENT_COLUMN_PRODUCT, + CLIENT_COLUMN_STATE, + CLIENT_COLUMN_SIGNAL, + CLIENT_COLUMN_POLICY, + CLIENT_COLUMN_IPV4_METHOD, + CLIENT_COLUMN_IPV4_ADDRESS, + CLIENT_COLUMN_IPV4_NETMASK, + CLIENT_COLUMN_IPV4_GATEWAY, +}; + +enum { + CLIENT_TYPE_UNKNOWN, + CLIENT_TYPE_80203, + CLIENT_TYPE_80211, +}; + +enum { + CLIENT_STATE_UNKNOWN, + CLIENT_STATE_OFFLINE, + CLIENT_STATE_READY, +}; + +enum { + CLIENT_POLICY_UNKNOWN, + CLIENT_POLICY_OFF, + CLIENT_POLICY_IGNORE, + CLIENT_POLICY_AUTO, +}; + +enum { + CLIENT_IPV4_METHOD_UNKNOWN, + CLIENT_IPV4_METHOD_OFF, + CLIENT_IPV4_METHOD_STATIC, + CLIENT_IPV4_METHOD_DHCP, +}; + +gboolean client_init(GError **error); +void client_cleanup(void); + +GtkTreeModel *client_get_model(void); + +void client_set_policy(const gchar *index, guint policy); +void client_set_ipv4(const gchar *index, guint method); diff --git a/common/test-client.c b/common/test-client.c new file mode 100644 index 0000000..bdbfbad --- /dev/null +++ b/common/test-client.c @@ -0,0 +1,436 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <signal.h> + +#include <gtk/gtk.h> + +#include "client.h" + +static void state_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell, + GtkTreeModel *model, GtkTreeIter *iter, gpointer data) +{ + gboolean active; + guint state, signal; + gchar *markup; + const char *str; + + gtk_tree_model_get(model, iter, CLIENT_COLUMN_ACTIVE, &active, + CLIENT_COLUMN_STATE, &state, + CLIENT_COLUMN_SIGNAL, &signal, -1); + + switch (state) { + case CLIENT_STATE_OFFLINE: + str = "Offline"; + break; + case CLIENT_STATE_READY: + str = "Ready"; + break; + default: + str = "Unknown"; + break; + } + + markup = g_strdup_printf("%s\n<small>%d \%\n%s</small>", str, + signal, active == TRUE ? "ON" : "OFF"); + g_object_set(cell, "markup", markup, NULL); + g_free(markup); +} + +static void type_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell, + GtkTreeModel *model, GtkTreeIter *iter, gpointer data) +{ + guint type; + gchar *driver, *markup; + const char *str; + + gtk_tree_model_get(model, iter, CLIENT_COLUMN_TYPE, &type, + CLIENT_COLUMN_DRIVER, &driver, -1); + + switch (type) { + case CLIENT_TYPE_80203: + str = "IEEE 802.03"; + break; + case CLIENT_TYPE_80211: + str = "IEEE 802.11"; + break; + default: + str = "Unknown"; + break; + } + + markup = g_strdup_printf("%s\n<small>%s\n</small>", str, driver); + g_object_set(cell, "markup", markup, NULL); + g_free(markup); + + g_free(driver); +} + +static void policy_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell, + GtkTreeModel *model, GtkTreeIter *iter, gpointer data) +{ + guint policy; + gchar *markup; + const char *str; + + gtk_tree_model_get(model, iter, CLIENT_COLUMN_POLICY, &policy, -1); + + switch (policy) { + case CLIENT_POLICY_OFF: + str = "Off"; + break; + case CLIENT_POLICY_IGNORE: + str = "Ignore"; + break; + case CLIENT_POLICY_AUTO: + str = "Automatic"; + break; + default: + str = "Unknown"; + break; + } + + markup = g_strdup_printf("%s\n<small>\n</small>", str); + g_object_set(cell, "markup", markup, NULL); + g_free(markup); +} + +static void ipv4_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell, + GtkTreeModel *model, GtkTreeIter *iter, gpointer data) +{ + guint method; + gchar *address, *netmask, *gateway, *markup; + const char *str; + + gtk_tree_model_get(model, iter, CLIENT_COLUMN_IPV4_METHOD, &method, + CLIENT_COLUMN_IPV4_ADDRESS, &address, + CLIENT_COLUMN_IPV4_NETMASK, &netmask, + CLIENT_COLUMN_IPV4_GATEWAY, &gateway, -1); + + switch (method) { + case CLIENT_IPV4_METHOD_OFF: + str = "Off"; + break; + case CLIENT_IPV4_METHOD_STATIC: + str = "Manually"; + break; + case CLIENT_IPV4_METHOD_DHCP: + str = "DHCP"; + break; + default: + str = "Unknown"; + break; + } + + if (address != NULL) + markup = g_strdup_printf("%s\n<small>%s/%s\ngw %s</small>", + str, address, netmask, gateway); + else + markup = g_strdup_printf("%s\n<small>\n</small>", str); + g_object_set(cell, "markup", markup, NULL); + g_free(markup); + + g_free(address); + g_free(netmask); + g_free(gateway); +} + +static void select_callback(GtkTreeSelection *selection, gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean selected; + gchar *index; + + selected = gtk_tree_selection_get_selected(selection, &model, &iter); + if (selected == FALSE) + return; + + index = gtk_tree_model_get_string_from_iter(model, &iter); +} + +static GtkWidget *create_tree(void) +{ + GtkWidget *tree; + GtkTreeModel *model; + GtkTreeSelection *selection; + + tree = gtk_tree_view_new(); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), TRUE); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); + + gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(tree), -1, + "State", gtk_cell_renderer_text_new(), + state_to_text, NULL, NULL); + + gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(tree), -1, + "Type", gtk_cell_renderer_text_new(), + type_to_text, NULL, NULL); + +#if 0 + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree), -1, + "Driver", gtk_cell_renderer_text_new(), + "text", CLIENT_COLUMN_DRIVER, NULL); + + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree), -1, + "Vendor", gtk_cell_renderer_text_new(), + "text", CLIENT_COLUMN_VENDOR, NULL); + + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree), -1, + "Product", gtk_cell_renderer_text_new(), + "text", CLIENT_COLUMN_PRODUCT, NULL); +#endif + + gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(tree), -1, + "Policy", gtk_cell_renderer_text_new(), + policy_to_text, NULL, NULL); + + gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(tree), -1, + "IPv4", gtk_cell_renderer_text_new(), + ipv4_to_text, NULL, NULL); + + model = client_get_model(); + gtk_tree_view_set_model(GTK_TREE_VIEW(tree), model); + g_object_unref(model); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + + g_signal_connect(G_OBJECT(selection), "changed", + G_CALLBACK(select_callback), NULL); + + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree)); + + return tree; +} + +static void policy_off(GtkWidget *button, gpointer user_data) +{ + GtkTreeSelection *selection = user_data; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *index; + + if (gtk_tree_selection_get_selected(selection, + &model, &iter) == FALSE) + return; + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + client_set_policy(index, CLIENT_POLICY_OFF); +} + +static void policy_ignore(GtkWidget *button, gpointer user_data) +{ + GtkTreeSelection *selection = user_data; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *index; + + if (gtk_tree_selection_get_selected(selection, + &model, &iter) == FALSE) + return; + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + client_set_policy(index, CLIENT_POLICY_IGNORE); +} + +static void policy_auto(GtkWidget *button, gpointer user_data) +{ + GtkTreeSelection *selection = user_data; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *index; + + if (gtk_tree_selection_get_selected(selection, + &model, &iter) == FALSE) + return; + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + client_set_policy(index, CLIENT_POLICY_AUTO); +} + +static void dhcp_callback(GtkWidget *button, gpointer user_data) +{ + GtkTreeSelection *selection = user_data; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *index; + + if (gtk_tree_selection_get_selected(selection, + &model, &iter) == FALSE) + return; + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + client_set_ipv4(index, CLIENT_IPV4_METHOD_DHCP); +} + +static void static_callback(GtkWidget *button, gpointer user_data) +{ + GtkTreeSelection *selection = user_data; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *index; + + if (gtk_tree_selection_get_selected(selection, + &model, &iter) == FALSE) + return; + + index = gtk_tree_model_get_string_from_iter(model, &iter); + + client_set_ipv4(index, CLIENT_IPV4_METHOD_STATIC); +} + +static void delete_callback(GtkWidget *window, GdkEvent *event, + gpointer user_data) +{ + gtk_widget_destroy(GTK_WIDGET(window)); + + gtk_main_quit(); +} + +static void close_callback(GtkWidget *button, gpointer user_data) +{ + GtkWidget *window = user_data; + + gtk_widget_destroy(GTK_WIDGET(window)); + + gtk_main_quit(); +} + +static GtkWidget *create_window(void) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *tree; + GtkWidget *scrolled; + GtkWidget *buttonbox; + GtkWidget *button; + GtkTreeSelection *selection; + + tree = create_tree(); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "Client Test"); + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_window_set_default_size(GTK_WINDOW(window), 640, 320); + g_signal_connect(G_OBJECT(window), "delete-event", + G_CALLBACK(delete_callback), NULL); + + vbox = gtk_vbox_new(FALSE, 12); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 12); + gtk_container_add(GTK_CONTAINER(window), vbox); + + hbox = gtk_hbox_new(FALSE, 8); + gtk_container_add(GTK_CONTAINER(vbox), hbox); + + buttonbox = gtk_vbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonbox), + GTK_BUTTONBOX_START); + gtk_box_pack_start(GTK_BOX(hbox), buttonbox, FALSE, FALSE, 0); + + button = gtk_button_new_with_label("Policy Off"); + gtk_container_add(GTK_CONTAINER(buttonbox), button); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(policy_off), selection); + + button = gtk_button_new_with_label("Policy Ignore"); + gtk_container_add(GTK_CONTAINER(buttonbox), button); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(policy_ignore), selection); + + button = gtk_button_new_with_label("Policy Auto"); + gtk_container_add(GTK_CONTAINER(buttonbox), button); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(policy_auto), selection); + + button = gtk_button_new_with_label("DHCP"); + gtk_container_add(GTK_CONTAINER(buttonbox), button); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(dhcp_callback), selection); + + button = gtk_button_new_with_label("Static IP"); + gtk_container_add(GTK_CONTAINER(buttonbox), button); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(static_callback), selection); + + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), + GTK_SHADOW_OUT); + gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); + + buttonbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonbox), + GTK_BUTTONBOX_END); + gtk_box_pack_start(GTK_BOX(vbox), buttonbox, FALSE, FALSE, 0); + + button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); + gtk_container_add(GTK_CONTAINER(buttonbox), button); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(close_callback), window); + + gtk_container_add(GTK_CONTAINER(scrolled), tree); + + gtk_widget_show_all(window); + + return window; +} + +static void sig_term(int sig) +{ + gtk_main_quit(); +} + +int main(int argc, char *argv[]) +{ + struct sigaction sa; + + gtk_init(&argc, &argv); + + gtk_window_set_default_icon_name("stock_internet"); + + client_init(NULL); + + create_window(); + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_term; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + gtk_main(); + + client_cleanup(); + + return 0; +} |