#include <string.h>
#include "gsksocketaddresssymbolic.h"
#include "gsknameresolver.h"
G_DEFINE_ABSTRACT_TYPE(GskSocketAddressSymbolic,
gsk_socket_address_symbolic,
GSK_TYPE_SOCKET_ADDRESS);
G_DEFINE_TYPE (GskSocketAddressSymbolicIpv4,
gsk_socket_address_symbolic_ipv4,
GSK_TYPE_SOCKET_ADDRESS_SYMBOLIC);
/* GskSocketAddressSymbolic */
enum
{
SYMBOLIC_PROP_0,
SYMBOLIC_PROP_NAME,
};
static gboolean
gsk_socket_address_symbolic_to_native(GskSocketAddress *address,
gpointer output)
{
return FALSE;
}
static gboolean
gsk_socket_address_symbolic_from_native (GskSocketAddress *address,
gconstpointer sockaddr_data,
gsize sockaddr_length)
{
return FALSE;
}
static char *
gsk_socket_address_symbolic_to_string (GskSocketAddress *address)
{
return g_strdup (GSK_SOCKET_ADDRESS_SYMBOLIC (address)->name);
}
static gboolean
gsk_socket_address_symbolic_equals (GskSocketAddress *addr1,
GskSocketAddress *addr2)
{
return strcmp (GSK_SOCKET_ADDRESS_SYMBOLIC (addr1)->name,
GSK_SOCKET_ADDRESS_SYMBOLIC (addr2)->name) == 0;
}
static guint
gsk_socket_address_symbolic_hash (GskSocketAddress *addr)
{
return g_str_hash (GSK_SOCKET_ADDRESS_SYMBOLIC (addr)->name) + 100000;
}
static void
gsk_socket_address_symbolic_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GskSocketAddressSymbolic *symbolic = GSK_SOCKET_ADDRESS_SYMBOLIC (object);
switch (property_id)
{
case SYMBOLIC_PROP_NAME:
g_free (symbolic->name);
symbolic->name = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gsk_socket_address_symbolic_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GskSocketAddressSymbolic *symbolic = GSK_SOCKET_ADDRESS_SYMBOLIC (object);
switch (property_id)
{
case SYMBOLIC_PROP_NAME:
g_value_set_string (value, symbolic->name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gsk_socket_address_symbolic_finalize (GObject *object)
{
GskSocketAddressSymbolic *symbolic = GSK_SOCKET_ADDRESS_SYMBOLIC (object);
g_free (symbolic->name);
G_OBJECT_CLASS (gsk_socket_address_symbolic_parent_class)->finalize (object);
}
static void
gsk_socket_address_symbolic_class_init (GskSocketAddressSymbolicClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GskSocketAddressClass *address_class = GSK_SOCKET_ADDRESS_CLASS (class);
address_class->to_native = gsk_socket_address_symbolic_to_native;
address_class->from_native = gsk_socket_address_symbolic_from_native;
address_class->to_string = gsk_socket_address_symbolic_to_string;
address_class->hash = gsk_socket_address_symbolic_hash;
address_class->equals = gsk_socket_address_symbolic_equals;
object_class->set_property = gsk_socket_address_symbolic_set_property;
object_class->get_property = gsk_socket_address_symbolic_get_property;
object_class->finalize = gsk_socket_address_symbolic_finalize;
g_object_class_install_property (object_class, SYMBOLIC_PROP_NAME,
g_param_spec_string ("name", "Name", "name (of host)",
NULL, G_PARAM_READWRITE));
}
static void
gsk_socket_address_symbolic_init (GskSocketAddressSymbolic *symbolic)
{
}
/* Public API */
gpointer
gsk_socket_address_symbolic_create_name_resolver (GskSocketAddressSymbolic *symbolic)
{
GskSocketAddressSymbolicClass *class = GSK_SOCKET_ADDRESS_SYMBOLIC_GET_CLASS (symbolic);
return class->create_name_resolver (symbolic);
}
void
gsk_socket_address_symbolic_start_resolution (GskSocketAddressSymbolic *symbolic,
gpointer name_resolver,
GskSocketAddressSymbolicResolveFunc r,
GskSocketAddressSymbolicErrorFunc e,
gpointer user_data,
GDestroyNotify destroy)
{
GskSocketAddressSymbolicClass *class = GSK_SOCKET_ADDRESS_SYMBOLIC_GET_CLASS (symbolic);
class->start_resolution (symbolic, name_resolver, r, e, user_data, destroy);
}
void
gsk_socket_address_symbolic_cancel_resolution (GskSocketAddressSymbolic *symbolic,
gpointer name_resolver)
{
GskSocketAddressSymbolicClass *class = GSK_SOCKET_ADDRESS_SYMBOLIC_GET_CLASS (symbolic);
class->cancel_resolution (symbolic, name_resolver);
}
/* GskSocketAddressSymbolicIpv4 */
enum
{
SYMBOLIC_IPV4_PROP_0,
SYMBOLIC_IPV4_PROP_PORT,
};
typedef struct _Ipv4NameResolver Ipv4NameResolver;
struct _Ipv4NameResolver
{
GskSocketAddressSymbolicIpv4 *ipv4;
GskSocketAddressSymbolicResolveFunc resolve_func;
GskSocketAddressSymbolicErrorFunc error_func;
gpointer data;
GDestroyNotify destroy;
GskNameResolverTask *task;
gboolean resolved;
};
static gpointer
gsk_socket_address_symbolic_ipv4_create_name_resolver (GskSocketAddressSymbolic *symbolic)
{
Ipv4NameResolver *resolver = g_new0 (Ipv4NameResolver, 1);
resolver->ipv4 = GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (g_object_ref (symbolic));
return resolver;
}
static void
ipv4_handle_success (GskSocketAddress *address,
gpointer func_data)
{
Ipv4NameResolver *resolver = func_data;
GskSocketAddressIpv4 *host_only = GSK_SOCKET_ADDRESS_IPV4 (address);
GskSocketAddress *real;
resolver->resolved = 1;
/* prepare new socket address */
real = gsk_socket_address_ipv4_new (host_only->ip_address,
resolver->ipv4->port);
/* invoke user's callback */
(*resolver->resolve_func) (GSK_SOCKET_ADDRESS_SYMBOLIC (resolver->ipv4),
real,
resolver->data);
/* cleanup */
g_object_unref (real);
}
static void
ipv4_handle_failure (GError *error,
gpointer func_data)
{
Ipv4NameResolver *resolver = func_data;
resolver->resolved = 1;
/* invoke user's callback */
if (resolver->error_func != NULL)
(*resolver->error_func) (GSK_SOCKET_ADDRESS_SYMBOLIC (resolver->ipv4),
error,
resolver->data);
}
static void
ipv4_handle_destroy (gpointer func_data)
{
Ipv4NameResolver *resolver = func_data;
g_assert (resolver->resolved);
if (resolver->destroy != NULL)
resolver->destroy (resolver->data);
g_object_unref (resolver->ipv4);
g_free (resolver);
}
static void
gsk_socket_address_symbolic_ipv4_start_resolution (GskSocketAddressSymbolic *symbolic,
gpointer name_resolver,
GskSocketAddressSymbolicResolveFunc r,
GskSocketAddressSymbolicErrorFunc e,
gpointer user_data,
GDestroyNotify destroy)
{
Ipv4NameResolver *resolver = name_resolver;
resolver->resolve_func = r;
resolver->error_func = e;
resolver->data = user_data;
resolver->destroy = destroy;
resolver->resolved = 0;
resolver->task = gsk_name_resolver_task_new (GSK_NAME_RESOLVER_FAMILY_IPV4,
symbolic->name,
ipv4_handle_success,
ipv4_handle_failure,
resolver,
ipv4_handle_destroy);
/* note: may destroy resolver! */
gsk_name_resolver_task_unref (resolver->task);
}
static void
gsk_socket_address_symbolic_ipv4_cancel_resolution (GskSocketAddressSymbolic *symbolic,
gpointer name_resolver)
{
Ipv4NameResolver *resolver = name_resolver;
/* if this triggers, i guess that we are in
the start_resolution() callback,
and name resolution hasn't blocked,
so that either "success" or "failure"
callback is being invoked. but then,
how did the user get the pointer "resolver"?
it's impossible. */
g_return_if_fail (resolver->task != NULL);
if (resolver->resolved)
return;
if (resolver->task != NULL)
{
GskNameResolverTask *task = resolver->task;
resolver->task = NULL;
gsk_name_resolver_task_cancel (task);
}
}
static char *
gsk_socket_address_symbolic_ipv4_to_string (GskSocketAddress *address)
{
return g_strdup_printf ("%s:%u",
GSK_SOCKET_ADDRESS_SYMBOLIC (address)->name,
(guint) GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (address)->port);
}
static gboolean
gsk_socket_address_symbolic_ipv4_equals(GskSocketAddress *addr1,
GskSocketAddress *addr2)
{
return strcmp (GSK_SOCKET_ADDRESS_SYMBOLIC (addr1)->name,
GSK_SOCKET_ADDRESS_SYMBOLIC (addr2)->name) == 0
&& GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (addr1)->port
== GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (addr2)->port;
}
static guint
gsk_socket_address_symbolic_ipv4_hash (GskSocketAddress *addr)
{
return g_str_hash (GSK_SOCKET_ADDRESS_SYMBOLIC (addr)->name) + 200000
+ GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (addr)->port;
}
static void
gsk_socket_address_symbolic_ipv4_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GskSocketAddressSymbolicIpv4 *symbolic_ipv4 = GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (object);
switch (property_id)
{
case SYMBOLIC_IPV4_PROP_PORT:
symbolic_ipv4->port = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gsk_socket_address_symbolic_ipv4_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GskSocketAddressSymbolicIpv4 *symbolic_ipv4 = GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (object);
switch (property_id)
{
case SYMBOLIC_IPV4_PROP_PORT:
g_value_set_uint (value, symbolic_ipv4->port);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gsk_socket_address_symbolic_ipv4_finalize (GObject *object)
{
//GskSocketAddressSymbolicIpv4 *symbolic_ipv4 = GSK_SOCKET_ADDRESS_SYMBOLIC_IPV4 (object);
G_OBJECT_CLASS (gsk_socket_address_symbolic_ipv4_parent_class)->finalize (object);
}
static void
gsk_socket_address_symbolic_ipv4_class_init (GskSocketAddressSymbolicIpv4Class *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GskSocketAddressClass *address_class = GSK_SOCKET_ADDRESS_CLASS (class);
GskSocketAddressSymbolicClass *symbolic_class = GSK_SOCKET_ADDRESS_SYMBOLIC_CLASS (class);
object_class->set_property = gsk_socket_address_symbolic_ipv4_set_property;
object_class->get_property = gsk_socket_address_symbolic_ipv4_get_property;
object_class->finalize = gsk_socket_address_symbolic_ipv4_finalize;
address_class->to_string = gsk_socket_address_symbolic_ipv4_to_string;
address_class->hash = gsk_socket_address_symbolic_ipv4_hash;
address_class->equals = gsk_socket_address_symbolic_ipv4_equals;
symbolic_class->create_name_resolver = gsk_socket_address_symbolic_ipv4_create_name_resolver;
symbolic_class->start_resolution = gsk_socket_address_symbolic_ipv4_start_resolution;
symbolic_class->cancel_resolution = gsk_socket_address_symbolic_ipv4_cancel_resolution;
g_object_class_install_property (object_class, SYMBOLIC_IPV4_PROP_PORT,
g_param_spec_uint ("port", "Port", "TCP port",
0,65535,0, G_PARAM_READWRITE));
}
static void
gsk_socket_address_symbolic_ipv4_init (GskSocketAddressSymbolicIpv4 *symbolic_ipv4)
{
}
GskSocketAddress *
gsk_socket_address_symbolic_ipv4_new (const char *name,
guint16 port)
{
return g_object_new (GSK_TYPE_SOCKET_ADDRESS_SYMBOLIC_IPV4,
"name", name,
"port", port,
NULL);
}
syntax highlighted by Code2HTML, v. 0.9.1