#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> /* ipv4 support */
#include <sys/un.h> /* local (aka unix) support */
#include <string.h>
#include "config.h"
#include "gsksocketaddress.h"
#include "gskipv4.h"
#include "gskerror.h"
#include "gskghelpers.h"
#include "gskmacros.h"
G_DEFINE_ABSTRACT_TYPE(GskSocketAddress, gsk_socket_address, G_TYPE_OBJECT);
G_DEFINE_TYPE(GskSocketAddressIpv4, gsk_socket_address_ipv4, GSK_TYPE_SOCKET_ADDRESS);
G_DEFINE_TYPE(GskSocketAddressIpv6, gsk_socket_address_ipv6, GSK_TYPE_SOCKET_ADDRESS);
G_DEFINE_TYPE(GskSocketAddressEthernet, gsk_socket_address_ethernet, GSK_TYPE_SOCKET_ADDRESS);
G_DEFINE_TYPE(GskSocketAddressLocal, gsk_socket_address_local, GSK_TYPE_SOCKET_ADDRESS);
/* Macro to initialize the sa_len-like member of
sockaddr, if it exists. */
#if HAS_SOCKADDR_SA_LEN
#define MAYBE_SET_LENGTH_MEMBER(addr_member, type) \
G_STMT_START{ addr_member = sizeof(type); }G_STMT_END
#else
#define MAYBE_SET_LENGTH_MEMBER(addr_member, type)
#endif
/* Define GSK_[AP]F_LOCAL as portible wrappers for [AP]F_LOCAL. */
#if HAS_PF_LOCAL
#define GSK_PF_LOCAL PF_LOCAL
#define GSK_AF_LOCAL AF_LOCAL
#elif HAS_PF_UNIX
#define GSK_PF_LOCAL PF_UNIX
#define GSK_AF_LOCAL AF_UNIX
#else
#warn "no PF_UNIX or PF_LOCAL macros (?)"
#endif
/* --- GskSocketAddress implementation --- */
static void
gsk_socket_address_init (GskSocketAddress *socket_address)
{
}
static void
gsk_socket_address_class_init (GskSocketAddressClass *class)
{
}
/* --- GskSocketAddressIpv4 implementation --- */
static gboolean
gsk_socket_address_ipv4_to_native (GskSocketAddress *address,
gpointer output)
{
GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (address);
struct sockaddr_in *addr = output;
memset (addr, 0, sizeof (struct sockaddr_in));
addr->sin_family = PF_INET;
MAYBE_SET_LENGTH_MEMBER (addr->sin_len, struct sockaddr_in);
addr->sin_port = GUINT16_TO_BE (ipv4->ip_port);
memcpy (&addr->sin_addr, ipv4->ip_address, 4);
return TRUE;
}
static gboolean
gsk_socket_address_ipv4_from_native (GskSocketAddress *address,
gconstpointer sockaddr_data,
gsize sockaddr_length)
{
GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (address);
const struct sockaddr_in *addr = sockaddr_data;
ipv4->ip_port = GUINT16_FROM_BE (addr->sin_port);
memcpy (ipv4->ip_address, &addr->sin_addr, 4);
return TRUE;
}
static char *
gsk_socket_address_ipv4_to_string (GskSocketAddress *address)
{
GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (address);
if (ipv4->ip_port != 0)
return g_strdup_printf ("%d.%d.%d.%d:%d",
ipv4->ip_address[0],
ipv4->ip_address[1],
ipv4->ip_address[2],
ipv4->ip_address[3],
ipv4->ip_port);
else
return g_strdup_printf ("%d.%d.%d.%d",
ipv4->ip_address[0],
ipv4->ip_address[1],
ipv4->ip_address[2],
ipv4->ip_address[3]);
}
static gboolean
gsk_socket_address_ipv4_equals (GskSocketAddress *a,
GskSocketAddress *b)
{
GskSocketAddressIpv4 *ipv4_a = GSK_SOCKET_ADDRESS_IPV4 (a);
GskSocketAddressIpv4 *ipv4_b = GSK_SOCKET_ADDRESS_IPV4 (b);
return ipv4_a->ip_address[0] == ipv4_b->ip_address[0]
&& ipv4_a->ip_address[1] == ipv4_b->ip_address[1]
&& ipv4_a->ip_address[2] == ipv4_b->ip_address[2]
&& ipv4_a->ip_address[3] == ipv4_b->ip_address[3]
&& ipv4_a->ip_port == ipv4_b->ip_port;
}
static guint
gsk_socket_address_ipv4_hash (GskSocketAddress *a)
{
GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (a);
guint hash = ipv4->ip_address[0];
hash *= 33;
hash += ipv4->ip_address[1];
hash *= 33;
hash += ipv4->ip_address[2];
hash *= 33;
hash += ipv4->ip_address[3];
hash *= 33;
hash += ipv4->ip_port;
return hash;
}
static void
gsk_socket_address_ipv4_init (GskSocketAddressIpv4 *socket_address_ipv4)
{
}
static void
gsk_socket_address_ipv4_class_init (GskSocketAddressIpv4Class *ipv4_class)
{
GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_CLASS (ipv4_class);
class->address_family = AF_INET;
class->protocol_family = PF_INET;
class->sizeof_native_address = sizeof (struct sockaddr_in);
class->from_native = gsk_socket_address_ipv4_from_native;
class->to_native = gsk_socket_address_ipv4_to_native;
class->to_string = gsk_socket_address_ipv4_to_string;
class->hash = gsk_socket_address_ipv4_hash;
class->equals = gsk_socket_address_ipv4_equals;
gsk_socket_address_register_subclass (class);
}
/* --- ipv6 implementation --- */
#if SUPPORTS_IPV6
static gboolean
gsk_socket_address_ipv6_to_native (GskSocketAddress *address,
gpointer output)
{
GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (address);
struct sockaddr_in6 *addr = output;
MAYBE_SET_LENGTH_MEMBER (addr->sin6_len, struct sockaddr_in6);
addr->sin6_family = AF_INET6;
addr->sin6_port = GUINT16_TO_BE (ipv6->port);
addr->sin6_flowinfo = GUINT32_TO_BE (ipv6->flow_info);
addr->sin6_scope_id = GUINT32_TO_BE (ipv6->scope_id);
g_assert (sizeof (addr->sin6_addr) == 16);
memcpy (&addr->sin6_addr, ipv6->address, 16);
return TRUE;
}
static gboolean
gsk_socket_address_ipv6_from_native (GskSocketAddress *address,
gconstpointer sockaddr_data,
gsize sockaddr_length)
{
GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (address);
const struct sockaddr_in6 *addr = sockaddr_data;
ipv6->port = GUINT16_FROM_BE (addr->sin6_port);
ipv6->flow_info = GUINT32_FROM_BE (addr->sin6_flowinfo);
ipv6->scope_id = GUINT32_FROM_BE (addr->sin6_scope_id);
memcpy (ipv6->address, &addr->sin6_addr, 16);
return TRUE;
}
#endif
static char *
gsk_socket_address_ipv6_to_string (GskSocketAddress *address)
{
GString *str = g_string_new ("");
GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (address);
guint8 *a = ipv6->address;
guint i;
g_string_printf (str, "%d@%x", ipv6->port, a[0]);
for (i = 1; i < 16; i++)
g_string_append_printf (str, ":%x", a[1]);
return g_string_free (str, FALSE);
}
static gboolean
gsk_socket_address_ipv6_equals (GskSocketAddress *a,
GskSocketAddress *b)
{
GskSocketAddressIpv6 *ipv6_a = GSK_SOCKET_ADDRESS_IPV6 (a);
GskSocketAddressIpv6 *ipv6_b = GSK_SOCKET_ADDRESS_IPV6 (b);
return ipv6_a->port == ipv6_b->port
&& memcmp (ipv6_a->address, ipv6_b->address, 16) == 0;
}
static guint
gsk_socket_address_ipv6_hash (GskSocketAddress *a)
{
GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (a);
guint hash = ipv6->port;
guint i;
for (i = 0; i < 16; i++)
{
hash *= 33;
hash += ipv6->address[i];
}
return hash;
}
static void
gsk_socket_address_ipv6_init (GskSocketAddressIpv6 *socket_address_ipv6)
{
}
static void
gsk_socket_address_ipv6_class_init (GskSocketAddressIpv6Class *ipv6_class)
{
GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_CLASS (ipv6_class);
#if SUPPORTS_IPV6
class->address_family = AF_INET6;
class->protocol_family = PF_INET6;
class->sizeof_native_address = sizeof (struct sockaddr_in6);
class->from_native = gsk_socket_address_ipv6_from_native;
class->to_native = gsk_socket_address_ipv6_to_native;
#endif
class->to_string = gsk_socket_address_ipv6_to_string;
class->hash = gsk_socket_address_ipv6_hash;
class->equals = gsk_socket_address_ipv6_equals;
gsk_socket_address_register_subclass (class);
}
/* --- local (aka unix) socket address implementation --- */
static gboolean
gsk_socket_address_local_to_native (GskSocketAddress *address,
gpointer output)
{
GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (address);
struct sockaddr_un *addr = output;
MAYBE_SET_LENGTH_MEMBER (addr->sun_len, struct sockaddr_un);
addr->sun_family = GSK_PF_LOCAL;
/* XXX: zero out other (a priori, unknown) arguments */
strncpy (addr->sun_path, local->path, sizeof (addr->sun_path));
return TRUE;
}
static gboolean
gsk_socket_address_local_from_native (GskSocketAddress *address,
gconstpointer sockaddr_data,
gsize sockaddr_length)
{
GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (address);
const struct sockaddr_un *native = sockaddr_data;
gint max_len;
guint len;
if (GSK_STRUCT_IS_LAST_MEMBER (struct sockaddr_un, sun_path))
max_len = sockaddr_length - G_STRUCT_OFFSET(struct sockaddr_un, sun_path);
else
max_len = sizeof (native->sun_path);
if (max_len <= 0)
return FALSE;
g_free (local->path);
len = gsk_strnlen (native->sun_path, max_len);
local->path = g_new (char, len + 1);
memcpy (local->path, native->sun_path, len);
local->path[len] = '\0';
return TRUE;
}
static char *
gsk_socket_address_local_to_string (GskSocketAddress *address)
{
GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (address);
return g_strdup (local->path);
}
static gboolean
gsk_socket_address_local_equals (GskSocketAddress *a,
GskSocketAddress *b)
{
GskSocketAddressLocal *local_a = GSK_SOCKET_ADDRESS_LOCAL (a);
GskSocketAddressLocal *local_b = GSK_SOCKET_ADDRESS_LOCAL (b);
return strcmp (local_a->path, local_b->path) == 0;
}
static guint
gsk_socket_address_local_hash (GskSocketAddress *a)
{
GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (a);
return g_str_hash (local->path);
}
static void
gsk_socket_address_local_init (GskSocketAddressLocal *socket_address_local)
{
}
static void
gsk_socket_address_local_class_init (GskSocketAddressLocalClass *class)
{
GskSocketAddressClass *address_class = GSK_SOCKET_ADDRESS_CLASS (class);
class->max_path_length = GSK_STRUCT_MEMBER_SIZE (struct sockaddr_un, sun_path);
address_class->sizeof_native_address = sizeof (struct sockaddr_un);
address_class->address_family = GSK_AF_LOCAL;
address_class->protocol_family = GSK_PF_LOCAL;
address_class->to_native = gsk_socket_address_local_to_native;
address_class->from_native = gsk_socket_address_local_from_native;
address_class->to_string = gsk_socket_address_local_to_string;
address_class->equals = gsk_socket_address_local_equals;
address_class->hash = gsk_socket_address_local_hash;
gsk_socket_address_register_subclass (address_class);
}
/**
* gsk_socket_address_local_new:
* @path: path in filesystem to hook this socket up.
*
* Create a socket-address which is associated with a path
* in the local filesystem. Such socket-addresses
* are useful for fast communication between processes on the same
* host.
*
* Sometimes, these types of addresses are called unix-domain addresses,
* but it is better to avoid the term unix for a generic concept.
*
* returns: the newly allocated socket address.
*/
GskSocketAddress *
gsk_socket_address_local_new (const char *path)
{
GskSocketAddressLocalClass *class = g_type_class_ref (GSK_TYPE_SOCKET_ADDRESS_LOCAL);
guint path_len = strlen (path);
GskSocketAddressLocal *rv;
if (path_len > class->max_path_length)
return NULL;
rv = g_object_new (G_OBJECT_CLASS_TYPE (class), NULL);
rv->path = g_strdup (path);
g_type_class_unref (class);
return GSK_SOCKET_ADDRESS (rv);
}
/* --- Ethernet (MAC) addresses --- */
#if 0 /* TODO: conversions to/from native */
static gboolean
gsk_socket_address_ethernet_to_native (GskSocketAddress *address,
gpointer output)
{
GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (address);
...
}
static gboolean
gsk_socket_address_ethernet_from_native (GskSocketAddress *address,
gconstpointer sockaddr_data,
gsize sockaddr_length)
{
GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (address);
...
}
#endif
static guint
gsk_socket_address_ethernet_hash (GskSocketAddress *addr)
{
GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (addr);
guint i;
guint rv = 0;
for (i = 0; i < 6; i++)
{
rv *= 167;
rv += ethernet->mac_address[i];
}
return rv;
}
static char *
gsk_socket_address_ethernet_to_string (GskSocketAddress *address)
{
GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (address);
return g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
ethernet->mac_address[0],
ethernet->mac_address[1],
ethernet->mac_address[2],
ethernet->mac_address[3],
ethernet->mac_address[4],
ethernet->mac_address[5]);
}
static gboolean
gsk_socket_address_ethernet_equals (GskSocketAddress *addr1,
GskSocketAddress *addr2)
{
GskSocketAddressEthernet *ethernet1 = GSK_SOCKET_ADDRESS_ETHERNET (addr1);
GskSocketAddressEthernet *ethernet2 = GSK_SOCKET_ADDRESS_ETHERNET (addr2);
return memcmp (ethernet1->mac_address, ethernet2->mac_address, 6) == 0;
}
/* --- functions --- */
static void
gsk_socket_address_ethernet_init (GskSocketAddressEthernet *socket_address_ethernet)
{
}
static void
gsk_socket_address_ethernet_class_init (GskSocketAddressEthernetClass *eth_class)
{
GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_CLASS (eth_class);
class->hash = gsk_socket_address_ethernet_hash;
class->to_string = gsk_socket_address_ethernet_to_string;
class->equals = gsk_socket_address_ethernet_equals;
/* TODO: convert to/from native */
#if 0
class->to_native = gsk_socket_address_ethernet_to_native;
class->from_native = gsk_socket_address_ethernet_from_native;
class->address_family = AF_???;
class->protocol_family = PF_???;
class->sizeof_native_address = sizeof (struct sockaddr_??? );
gsk_socket_address_register_subclass (class);
#endif
}
/**
* gsk_socket_address_ethernet_new:
* @mac_addr: the 6-byte unique address of this ethernet device.
*
* Allocate a new socket address corresponding to an
* ethernet device.
*
* returns: the newly allocated socket-address.
*/
GskSocketAddress *
gsk_socket_address_ethernet_new (const guint8 *mac_addr)
{
GskSocketAddressEthernet *eth = g_object_new (GSK_TYPE_SOCKET_ADDRESS_ETHERNET, NULL);
memcpy (eth->mac_address, mac_addr, 6);
return GSK_SOCKET_ADDRESS (eth);
}
/* --- public methods --- */
static GHashTable *native_to_gtype = NULL;
static GStaticRWLock native_to_gtype_lock = G_STATIC_RW_LOCK_INIT;
#define N2G_WRITE_LOCK() g_static_rw_lock_writer_lock(&native_to_gtype_lock)
#define N2G_WRITE_UNLOCK() g_static_rw_lock_writer_unlock(&native_to_gtype_lock)
#define N2G_READ_LOCK() g_static_rw_lock_reader_lock(&native_to_gtype_lock)
#define N2G_READ_UNLOCK() g_static_rw_lock_reader_unlock(&native_to_gtype_lock)
/**
* gsk_socket_address_from_native:
* @native_data: a struct sockaddr_t*.
* @native_size: length of native_data.
*
* Allocate a new GskSocketAddress based on
* native_data, if we know how.
*
* returns: a new GskSocketAddress or NULL if we could not interpret the sockaddr.
*/
GskSocketAddress *
gsk_socket_address_from_native (gconstpointer native_data,
gsize native_size)
{
const struct sockaddr *addr = native_data;
GType type;
GskSocketAddressClass *class;
GObject *rv_object;
GskSocketAddress *rv;
guint family;
N2G_READ_LOCK ();
if (native_to_gtype == NULL)
{
N2G_READ_UNLOCK ();
return NULL;
}
family = (guint) addr->sa_family;
type = (GType) g_hash_table_lookup (native_to_gtype, GUINT_TO_POINTER (family));
N2G_READ_UNLOCK ();
if (type == 0)
{
return NULL;
}
rv_object = g_object_new (type, NULL);
rv = GSK_SOCKET_ADDRESS (rv_object);
class = GSK_SOCKET_ADDRESS_GET_CLASS (rv);
if (!((*class->from_native) (rv, native_data, native_size)))
{
g_object_unref (rv);
return NULL;
}
return GSK_SOCKET_ADDRESS (rv);
}
/**
* gsk_socket_address_sizeof_native:
* @address: a socket address.
*
* Determine how many bytes of storage the sockaddr_t
* based on this object will require.
*
* returns: the size in bytes of the native sockaddr type.
*/
guint
gsk_socket_address_sizeof_native (GskSocketAddress *address)
{
return GSK_SOCKET_ADDRESS_GET_CLASS (address)->sizeof_native_address;
}
/**
* gsk_socket_address_protocol_family:
* @address: a socket address.
*
* Get the PF_* macro value corresponding to this address.
*
* returns: the protocol family.
*/
gint
gsk_socket_address_protocol_family (GskSocketAddress *address)
{
return GSK_SOCKET_ADDRESS_GET_CLASS (address)->protocol_family;
}
/**
* gsk_socket_address_address_family:
* @address: a socket address.
*
* Get the AF_* macro value corresponding to this address.
*
* returns: the address family.
*/
gint
gsk_socket_address_address_family (GskSocketAddress *address)
{
return GSK_SOCKET_ADDRESS_GET_CLASS (address)->address_family;
}
/**
* gsk_socket_address_to_native:
* @address: a socket address.
* @output: a struct sockaddr_t (at least conceptually)
* @error: optional error return value.
*
* Convert a socket-address to its native form.
*
* returns: whether it was able to convert the address.
*/
gboolean
gsk_socket_address_to_native (GskSocketAddress *address,
gpointer output,
GError **error)
{
GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_GET_CLASS (address);
if (G_UNLIKELY (!class->to_native (address, output)))
{
g_set_error (error, GSK_G_ERROR_DOMAIN, GSK_ERROR_FOREIGN_ADDRESS,
"error making a native socket-address for %s",
g_type_name (G_OBJECT_CLASS_TYPE (class)));
return FALSE;
}
return TRUE;
}
/**
* gsk_socket_address_to_string:
* @address: a socket address.
*
* Convert a socket-address to a newly allocated string,
* which the caller must free.
*
* returns: a string for the user to free.
*/
char *
gsk_socket_address_to_string (GskSocketAddress *address)
{
GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_GET_CLASS (address);
return class->to_string (address);
}
/**
* gsk_socket_address_ipv4_new:
* @ip_address: the 4-byte IP address
* @port: the port number.
*
* Allocate a new IPv4 address given a numeric IP and port number.
*
* returns: a new GskSocketAddress
*/
GskSocketAddress *
gsk_socket_address_ipv4_new (const guint8 *ip_address,
guint16 port)
{
GskSocketAddressIpv4 *ipv4;
ipv4 = g_object_new (GSK_TYPE_SOCKET_ADDRESS_IPV4, NULL);
ipv4->ip_port = port;
memcpy (ipv4->ip_address, ip_address, 4);
return GSK_SOCKET_ADDRESS (ipv4);
}
/**
* gsk_socket_address_equals:
* @address_a_ptr: a pointer to a #GskSocketAddress.
* @address_b_ptr: a pointer to a #GskSocketAddress.
*
* This function is a GEqualFunc which can determine
* if two socket address are the same.
* This is principally used with #gsk_socket_address_hash
* to make a hash-table mapping from socket-addresses.
*
* (This just uses the virtual method of GskSocketAddressClass)
*
* returns: whether the addresses are equal.
*/
gboolean
gsk_socket_address_equals (gconstpointer address_a_ptr,
gconstpointer address_b_ptr)
{
GskSocketAddress *address_a = (GskSocketAddress *) address_a_ptr;
GskSocketAddress *address_b = (GskSocketAddress *) address_b_ptr;
GskSocketAddressClass *class;
GType type_a, type_b;
g_return_val_if_fail (GSK_IS_SOCKET_ADDRESS (address_a)
&& GSK_IS_SOCKET_ADDRESS (address_b), FALSE);
type_a = G_OBJECT_TYPE (address_a);
type_b = G_OBJECT_TYPE (address_b);
if (type_a != type_b)
return FALSE;
class = GSK_SOCKET_ADDRESS_GET_CLASS (address_a);
return (*class->equals) (address_a, address_b);
}
/**
* gsk_socket_address_hash:
* @address_ptr: a pointer to a #GskSocketAddress.
*
* This function is a GHashFunc which can determine
* a hash value for a socket-address.
*
* This is principally used with #gsk_socket_address_equals
* to make a hash-table mapping from socket-addresses.
*
* (This just uses the virtual method of GskSocketAddressClass)
*
* returns: the hash value for the socket-address.
*/
guint
gsk_socket_address_hash (gconstpointer address_ptr)
{
GskSocketAddress *address = (GskSocketAddress *) address_ptr;
GskSocketAddressClass *class;
g_return_val_if_fail (GSK_IS_SOCKET_ADDRESS (address), 0);
class = GSK_SOCKET_ADDRESS_GET_CLASS (address);
return (*class->hash) (address);
}
/* --- protected methods --- */
/**
* gsk_socket_address_register_subclass:
* @klass: a concrete derived class.
*
* Add the class to a per address-family hash table
* for use converting from native.
*/
void
gsk_socket_address_register_subclass (GskSocketAddressClass *klass)
{
GType type = G_OBJECT_CLASS_TYPE (klass);
N2G_WRITE_LOCK ();
if (native_to_gtype == NULL)
native_to_gtype = g_hash_table_new (NULL, NULL);
g_hash_table_insert (native_to_gtype,
GUINT_TO_POINTER (klass->address_family),
(gpointer) type);
N2G_WRITE_UNLOCK ();
}
/* --- public: a few useful quarks, for use with g_object_set_qdata --- */
GQuark
gsk_socket_address_get_remote_quark()
{
static GQuark rv = 0;
if (rv == 0)
rv = g_quark_from_static_string ("gsk-socket-address-remote-quark");
return rv;
}
GQuark
gsk_socket_address_get_local_quark()
{
static GQuark rv = 0;
if (rv == 0)
rv = g_quark_from_static_string ("gsk-socket-address-local-quark");
return rv;
}
/* Deprecated. included for binary compatibility */
#undef gsk_socket_address_new_local
GskSocketAddress *gsk_socket_address_new_local (const char *path)
{
return gsk_socket_address_local_new (path);
}
#undef gsk_socket_address_new_ethernet
GskSocketAddress *gsk_socket_address_new_ethernet (const guint8 *mac_addr)
{
return gsk_socket_address_ethernet_new (mac_addr);
}
syntax highlighted by Code2HTML, v. 0.9.1