Add a simple object to handle the SPICE_PROXY values. It's not clear to me whether each GIO user needs to handle the proxy configuration, or if there is a more global mechanism (via g_network_address_parse_uri()) Also, the parsing is currently very limited and only support basic HTTP proxy URI. In the future, we really want to rely on GUri or similar instead... --- gtk/Makefile.am | 2 + gtk/spice-proxy.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gtk/spice-proxy.h | 59 ++++++++++++++ 3 files changed, 297 insertions(+) create mode 100644 gtk/spice-proxy.c create mode 100644 gtk/spice-proxy.h diff --git a/gtk/Makefile.am b/gtk/Makefile.am index dd3744d..9f3fb84 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -243,6 +243,8 @@ libspice_client_glib_2_0_la_SOURCES = \ channel-usbredir-priv.h \ smartcard-manager.c \ smartcard-manager-priv.h \ + spice-proxy.c \ + spice-proxy.h \ usb-device-manager.c \ usb-device-manager-priv.h \ usbutil.c \ diff --git a/gtk/spice-proxy.c b/gtk/spice-proxy.c new file mode 100644 index 0000000..97c3a6b --- /dev/null +++ b/gtk/spice-proxy.c @@ -0,0 +1,236 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <string.h> + +#include "spice-client.h" +#include "spice-proxy.h" + +struct _SpiceProxyPrivate { + gchar *protocol; + gchar *hostname; + guint port; +}; + +#define SPICE_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), SPICE_TYPE_PROXY, SpiceProxyPrivate)) + +G_DEFINE_TYPE(SpiceProxy, spice_proxy, G_TYPE_OBJECT); + +enum { + SPICE_PROXY_DUMMY_PROPERTY, + SPICE_PROXY_PROTOCOL, + SPICE_PROXY_HOSTNAME, + SPICE_PROXY_PORT +}; + +SpiceProxy* spice_proxy_new(void) +{ + SpiceProxy * self = NULL; + self = (SpiceProxy*)g_object_new(SPICE_TYPE_PROXY, NULL); + return self; +} + +gboolean spice_proxy_parse(SpiceProxy *self, const gchar *uri, GError **error) +{ + gboolean success = FALSE; + + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail(uri != NULL, FALSE); + + /* FIXME: use GUri when it is ready... only support http atm */ + /* the code is voluntarily not parsing thoroughly the uri */ + if (g_ascii_strncasecmp("http://", uri, 7) == 0) + uri += 7; + + spice_proxy_set_protocol(self, "http"); + spice_proxy_set_port(self, 3128); + + gchar **proxyv = g_strsplit(uri, ":", 0); + const gchar *proxy_port = NULL; + + if (proxyv[0] == NULL || strlen(proxyv[0]) == 0) { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Invalid hostname in proxy address"); + goto end; + } + + spice_proxy_set_hostname(self, proxyv[0]); + if (proxyv[0] != NULL) + proxy_port = proxyv[1]; + + if (proxy_port != NULL) { + char *endptr; + guint port = strtoul(proxy_port, &endptr, 10); + if (*endptr != '\0') { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Invalid proxy port: %s", proxy_port); + goto end; + } + spice_proxy_set_port(self, port); + } + + success = TRUE; + +end: + g_strfreev(proxyv); + return success; +} + +const gchar* spice_proxy_get_protocol(SpiceProxy *self) +{ + g_return_val_if_fail(SPICE_IS_PROXY(self), NULL); + return self->priv->protocol; +} + +void spice_proxy_set_protocol(SpiceProxy *self, const gchar *value) +{ + g_return_if_fail(SPICE_IS_PROXY(self)); + + g_free(self->priv->protocol); + self->priv->protocol = g_strdup(value); + g_object_notify((GObject *)self, "protocol"); +} + +const gchar* spice_proxy_get_hostname(SpiceProxy *self) +{ + g_return_val_if_fail(SPICE_IS_PROXY(self), NULL); + return self->priv->hostname; +} + + +void spice_proxy_set_hostname(SpiceProxy *self, const gchar *value) +{ + g_return_if_fail(SPICE_IS_PROXY(self)); + + g_free(self->priv->hostname); + self->priv->hostname = g_strdup(value); + g_object_notify((GObject *)self, "hostname"); +} + +guint spice_proxy_get_port(SpiceProxy *self) +{ + g_return_val_if_fail(SPICE_IS_PROXY(self), 0); + return self->priv->port; +} + +void spice_proxy_set_port(SpiceProxy *self, guint port) +{ + g_return_if_fail(SPICE_IS_PROXY(self)); + self->priv->port = port; + g_object_notify((GObject *)self, "port"); +} + +static void spice_proxy_get_property(GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + SpiceProxy *self; + self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_PROXY, SpiceProxy); + + switch (property_id) { + case SPICE_PROXY_PROTOCOL: + g_value_set_string(value, spice_proxy_get_protocol(self)); + break; + case SPICE_PROXY_HOSTNAME: + g_value_set_string(value, spice_proxy_get_hostname(self)); + break; + case SPICE_PROXY_PORT: + g_value_set_uint(value, spice_proxy_get_port(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + + +static void spice_proxy_set_property(GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + SpiceProxy * self; + self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_PROXY, SpiceProxy); + + switch (property_id) { + case SPICE_PROXY_PROTOCOL: + spice_proxy_set_protocol(self, g_value_get_string(value)); + break; + case SPICE_PROXY_HOSTNAME: + spice_proxy_set_hostname(self, g_value_get_string(value)); + break; + case SPICE_PROXY_PORT: + spice_proxy_set_port(self, g_value_get_uint(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void spice_proxy_finalize(GObject* obj) +{ + SpiceProxy *self; + + self = G_TYPE_CHECK_INSTANCE_CAST(obj, SPICE_TYPE_PROXY, SpiceProxy); + g_free(self->priv->protocol); + g_free(self->priv->hostname); + + G_OBJECT_CLASS (spice_proxy_parent_class)->finalize (obj); +} + +static void spice_proxy_init (SpiceProxy *self) +{ + self->priv = SPICE_PROXY_GET_PRIVATE(self); +} + + +static void spice_proxy_class_init(SpiceProxyClass *klass) +{ + spice_proxy_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private(klass, sizeof(SpiceProxyPrivate)); + + G_OBJECT_CLASS (klass)->get_property = spice_proxy_get_property; + G_OBJECT_CLASS (klass)->set_property = spice_proxy_set_property; + G_OBJECT_CLASS (klass)->finalize = spice_proxy_finalize; + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_PROXY_PROTOCOL, + g_param_spec_string ("protocol", + "protocol", + "protocol", + NULL, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_PROXY_HOSTNAME, + g_param_spec_string ("hostname", + "hostname", + "hostname", + NULL, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_PROXY_PORT, + g_param_spec_uint ("port", + "port", + "port", + 0, G_MAXUINT, 0, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); +} diff --git a/gtk/spice-proxy.h b/gtk/spice-proxy.h new file mode 100644 index 0000000..c780931 --- /dev/null +++ b/gtk/spice-proxy.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_PROXY_H__ +#define __SPICE_PROXY_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define SPICE_TYPE_PROXY (spice_proxy_get_type ()) +#define SPICE_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_PROXY, SpiceProxy)) +#define SPICE_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_PROXY, SpiceProxyClass)) +#define SPICE_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_PROXY)) +#define SPICE_IS_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_PROXY)) +#define SPICE_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_PROXY, SpiceProxyClass)) + +typedef struct _SpiceProxy SpiceProxy; +typedef struct _SpiceProxyClass SpiceProxyClass; +typedef struct _SpiceProxyPrivate SpiceProxyPrivate; + +struct _SpiceProxy { + GObject parent_instance; + SpiceProxyPrivate * priv; +}; + +struct _SpiceProxyClass { + GObjectClass parent_class; +}; + + +GType spice_proxy_get_type(void) G_GNUC_CONST; + +SpiceProxy* spice_proxy_new(void); +gboolean spice_proxy_parse(SpiceProxy* self, const gchar* uri, GError** error); +const gchar* spice_proxy_get_protocol(SpiceProxy* self); +void spice_proxy_set_protocol(SpiceProxy* self, const gchar* value); +const gchar* spice_proxy_get_hostname(SpiceProxy* self); +void spice_proxy_set_hostname(SpiceProxy* self, const gchar* value); +guint spice_proxy_get_port(SpiceProxy* self); +void spice_proxy_set_port(SpiceProxy* self, guint port); + +G_END_DECLS + +#endif /* __SPICE_PROXY_H__ */ -- 1.8.1.rc1.17.g75ed918 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel