From: Christian Kellner Date: Sat, 19 Jan 2008 12:13:58 +0000 (+0100) Subject: Patch from Samuel Cormier-Iijima : X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fgnio.git;a=commitdiff_plain;h=6d9680c2d5a0a77469a0e25934a3e7d726e78204 Patch from Samuel Cormier-Iijima : IPv6 isn't completely working, I wasn't sure of the differences in the is_mc_*'s. Also, ideally there should be a virtual function in GInetAddress called g_inet_address_to_string that delegates to either GInet4 or GInet6 to convert to a string representation. --- diff --git a/configure.ac b/configure.ac index 6132f5d..6c76996 100644 --- a/configure.ac +++ b/configure.ac @@ -44,18 +44,234 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.13.8 gthread-2.0 gobject-2.0 gmodule-no-ex AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) +PKG_CHECK_MODULES(GTHREAD, gthread-2.0) + GETTEXT_PACKAGE=gnio AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [The gettext domain name]) AC_SUBST(GETTEXT_PACKAGE) AM_GLIB_GNU_GETTEXT +AC_CHECK_FUNC(getaddrinfo_a) +AC_CHECK_FUNC(gethostbyname_r) dnl ========================================================================== dnl Globally define_GNU_SOURCE and therefore enable the GNU extensions AC_DEFINE(_GNU_SOURCE, 1, [Enable GNU Extensions]) +AC_CHECK_HEADERS([sys/sockio.h sys/param.h ifaddrs.h]) + +AM_CONDITIONAL(WIN32, [echo "$host" | grep -qE '^.*-.*-mingw.*$']) + +case "$host" in + *-*-mingw*) + AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if IPv6 is potentially available]) + AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if the system provides getaddrinfo(2)]) + AC_DEFINE(HAVE_GETADDRINFO_THREADSAFE, 1, [Define if getaddrinfo is threadsafe]) + AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[Whether you have struct sockaddr_storage]) + ;; + *) + AC_MSG_CHECKING([for linux/netlink.h]) + AC_TRY_CPP([#include ], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_LINUX_NETLINK_H, 1, + [Define if linux/netlink.h header exists]) + ],[ + AC_MSG_RESULT(no) + ]) + + AC_CHECK_MEMBER([struct sockaddr.sa_len], + AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, + [Define if struct sockaddr has sa_len field]),, + [#include + #include ]) + + AC_MSG_CHECKING([for struct sockaddr_storage]) + AC_TRY_COMPILE([ #include + #include ], [struct sockaddr_storage s; s], + have_sockaddr_storage=yes, have_sockaddr_storage=no) + if test "$have_sockaddr_storage" = yes; then + AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[Whether you have struct sockaddr_storage]) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + + # Check for IPv6 support on unix + # (will be done at runtime on win32) + AC_MSG_CHECKING([for IPv6 availability]) + AC_TRY_LINK([ #include + #include + #include ], + [ struct sockaddr_in6 s; + struct in6_addr t=in6addr_any; + int i=AF_INET6; + s; + t.s6_addr[0] = 0; ], + [ + AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if IPv6 is potentially available]) + AC_MSG_RESULT(yes) + ], + [ + AC_DEFINE(HAVE_IPV6, 0, [Define to 1 if IPv6 is potentially available]) + AC_MSG_RESULT(no) + ] + ) + # Most of this code checks for variants of gethostbyname(). For + # simplicity and curiosity, we check for all variants, though only one + # working variant is needed. + + # Look for getifaddrs() + AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS, 1, + [Define if getifaddrs() is available])) + + + # The user may be able to tell us if a function is thread-safe. We + # know of no good way to test this programaticly. + + # On some systems, getaddrinfo() is thread-safe + AC_ARG_ENABLE(threadsafe_getaddrinfo, + AC_HELP_STRING([--enable-threadsafe-getaddrinfo], + [assume getaddrinfo() is threadsafe])) + + # On some systems, gethostbyname() is thread-safe + AC_ARG_ENABLE(threadsafe_gethostbyname, + AC_HELP_STRING([--enable-threadsafe-gethostbyname], + [assume gethostbyname() is threadsafe])) + + + # Look for getaddrinfo(). If we have that, we don't need + # gethostbyname(). We assume if the system has getaddrinfo(), they + # have getnameinfo(). + AC_CHECK_FUNC(getaddrinfo, + [ # have getaddrinfo() + HAVE_GETADDRINFO=yes + AC_DEFINE(HAVE_GETADDRINFO, 1, + [Define if getaddrinfo() is available]) + # Check for threadsafe getaddrinfo() + AC_MSG_CHECKING([for threadsafe getaddrinfo()]) + if test "x$enable_threadsafe_getaddrinfo" = "xyes" ; then + HAVE_GETADDRINFO_THREADSAFE=yes + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_GETADDRINFO_THREADSAFE, 1, + [Define if getaddrinfo is threadsafe]) + else + AC_MSG_RESULT(no) + # If there is no threadsafe getaddrinfo, use a Glib mutex. + if test "x$GTHREAD_CFLAGS" != "x"; then + AC_DEFINE(HAVE_GETADDRINFO_GLIB_MUTEX, 1, + [Define if getaddrinfo requires a mutex for thread-safety]) + HAVE_GETADDRINFO_GLIB_MUTEX=yes + else + AC_MSG_WARN([ + + You do not have a thread-safe getaddrinfo() or GLib threads. + Calls to getaddrinfo() may + not be thread-safe. This build of GNIO could malfunction if used in + programs that use threads. If your system has a thread-safe version + of getaddrinfo(), pass the option --enable-threadsafe-getaddrinfo + to configure. The function's manpage may be able to tell you whether + it is thread-safe or not. + + ]) + fi + fi + ], + [ # no getaddrinfo() + AC_MSG_RESULT(no) + ]) + # Check if the user told use gethostbyname() is thread-safe. + AC_MSG_CHECKING([for threadsafe gethostbyname()]) + if test "x$enable_threadsafe_gethostbyname" = "xyes" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_GETHOSTBYNAME_THREADSAFE, 1, + [Define if gethostbyname is threadsafe]) + HAVE_GETHOSTBYNAME_THREADSAFE=yes + else + AC_MSG_RESULT(no) + fi + + # Look for a gethostbyname_r() we can use. We assume that if the + # system has gethostbyname_r(), they also have gethostbyaddr_r(). + + # First, look for the glibc varient + AC_MSG_CHECKING([for glibc gethostbyname_r]) + AC_TRY_LINK([#include ], + [struct hostent result_buf; + char buf[1024]; + struct hostent *result; + int h_erropp; + + gethostbyname_r("localhost", + &result_buf, + buf, + sizeof(buf), + &result, + &h_erropp);], + [AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_GETHOSTBYNAME_R_GLIBC, 1, + [Define if glibc variant of gethostbyname() is available]) + HAVE_GETHOSTBYNAME_R=yes], + [AC_MSG_RESULT([no])]) + # Whups, maybe we're on Solaris or Irix + AC_MSG_CHECKING([for Solaris/Irix gethostbyname_r]) + AC_TRY_LINK([#include ], + [struct hostent result; + char buf[1024]; + int h_errnop; + + gethostbyname_r("localhost", + &result, + buf, + sizeof(buf), + &h_errnop);], + [AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_GETHOSTBYNAME_R_SOLARIS, 1, + [Define if Solaris variant of gethostbyname() is available]) + HAVE_GETHOSTBYNAME_R=yes], + [AC_MSG_RESULT([no])]) + + # Or not. Perhaps we're on HP-UX? + AC_MSG_CHECKING([for HP-UX gethostbyname_r]) + AC_TRY_LINK([#include ], + [struct hostent result; + char buf[1024]; + + gethostbyname_r("localhost", + &result, + buf);], + [AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_GETHOSTBYNAME_R_HPUX, 1, + [Define if HPUX variant of gethostbyname() is available]) + HAVE_GETHOSTBYNAME_R=yes], + [AC_MSG_RESULT([no])]) + # If there is no gethostbyname_r, use Glib threads. + if test -z "$HAVE_GETHOSTBYNAME_THREADSAFE" -a -z "$HAVE_GETHOSTBYNAME_R" -a "$GTHREAD_CFLAGS"; then + AC_DEFINE(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX, 1, + [Define if gethostbyname requires a mutex for thread-safety]) + HAVE_GETHOSTBYNAME_R=yes + fi + + # Duh-oh. We don't have _any_ thread-safety, so warn the builder + if test -z "$HAVE_GETADDRINFO_THREADSAFE" -a -z "$HAVE_GETHOSTBYNAME_THREADSAFE" -a -z "$HAVE_GETHOSTBYNAME_R"; then + AC_MSG_WARN([ + + You do not have a thread-safe gethostbyname_r() or GLib threads. + Calls to gethostbyname() (called by the GOIO address functions) may + not be thread-safe. This build of GOIO could malfunction if used in + programs that use threads. If your system has a thread-safe version + of gethostbyname(), pass the option --enable-threadsafe-gethostbyname + to configure. The function's manpage may be able to tell you whether + it is thread-safe or not. + + ]) + fi + ;; +esac + + dnl ========================================================================== AC_DEFINE(_FILE_OFFSET_BITS, 64, [Enable LFS]) diff --git a/gnio/Makefile.am b/gnio/Makefile.am index c2380da..2bf1f93 100644 --- a/gnio/Makefile.am +++ b/gnio/Makefile.am @@ -14,6 +14,7 @@ gnio_headers = \ ginetaddress.h \ ginet4address.h \ ginet6address.h \ + gresolver.h \ gsocketaddress.h \ ginetsocketaddress.h \ $(NULL) @@ -27,6 +28,7 @@ libgnio_la_SOURCES = \ ginetaddress.c \ ginet4address.c \ ginet6address.c \ + gresolver.c \ gsocketaddress.c \ ginetsocketaddress.c \ $(NULL) diff --git a/gnio/ginet4address.c b/gnio/ginet4address.c index 8cb70fa..a7473f8 100644 --- a/gnio/ginet4address.c +++ b/gnio/ginet4address.c @@ -23,27 +23,109 @@ #include #include -#include "ginet4address.h" +#include +#include +#include "ginet4address.h" G_DEFINE_TYPE (GInet4Address, g_inet4_address, G_TYPE_INET_ADDRESS); struct _GInet4AddressPrivate { - - union { - guint32 u4_addr8[4]; - guint8 u4_addr32; - } addr; + union { + guint8 u4_addr8[4]; + guint32 u4_addr32; + } addr; }; +static gboolean +g_inet4_address_is_any (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return (g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32) == INADDR_ANY); +} + +static gboolean +g_inet4_address_is_linklocal (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return ((g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32) & 0xffff0000) == 0xa9fe0000); +} + +static gboolean +g_inet4_address_is_loopback (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return (G_INET4_ADDRESS (address)->priv->addr.u4_addr8[0] == IN_LOOPBACKNET); +} + +static gboolean +g_inet4_address_is_sitelocal (GInetAddress *address) +{ + guint32 addr; + + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + addr = g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32); + + return ((addr & 0xff000000) == (10 << 24)) || ((addr & 0xfff00000) == 0xac100000) || ((addr & 0xffff0000) == 0xc0a80000); +} + +static gboolean +g_inet4_address_is_multicast (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return IN_MULTICAST (g_ntohl (G_INET4_ADDRESS (address)->priv->addr.u4_addr32)); +} + +static gboolean +g_inet4_address_is_mc_global (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return FALSE; +} + +static gboolean +g_inet4_address_is_mc_linklocal (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return FALSE; +} + +static gboolean +g_inet4_address_is_mc_nodelocal (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return FALSE; +} + +static gboolean +g_inet4_address_is_mc_orglocal (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return FALSE; +} + +static gboolean +g_inet4_address_is_mc_sitelocal (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), FALSE); + + return FALSE; +} static void g_inet4_address_finalize (GObject *object) { - GInet4Address *address; + GInet4Address *address G_GNUC_UNUSED = G_INET4_ADDRESS (object); - address = G_INET4_ADDRESS (object); - if (G_OBJECT_CLASS (g_inet4_address_parent_class)->finalize) (*G_OBJECT_CLASS (g_inet4_address_parent_class)->finalize) (object); } @@ -51,25 +133,33 @@ g_inet4_address_finalize (GObject *object) static void g_inet4_address_dispose (GObject *object) { - GInet4Address *address; + GInet4Address *address G_GNUC_UNUSED = G_INET4_ADDRESS (object);; - address = G_INET4_ADDRESS (object); - if (G_OBJECT_CLASS (g_inet4_address_parent_class)->dispose) (*G_OBJECT_CLASS (g_inet4_address_parent_class)->dispose) (object); } - static void g_inet4_address_class_init (GInet4AddressClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GInetAddressClass *ginetaddress_class = G_INET_ADDRESS_CLASS (klass); g_type_class_add_private (klass, sizeof (GInet4AddressPrivate)); - + gobject_class->finalize = g_inet4_address_finalize; gobject_class->dispose = g_inet4_address_dispose; + ginetaddress_class->is_any = g_inet4_address_is_any; + ginetaddress_class->is_linklocal = g_inet4_address_is_linklocal; + ginetaddress_class->is_loopback = g_inet4_address_is_loopback; + ginetaddress_class->is_sitelocal = g_inet4_address_is_sitelocal; + ginetaddress_class->is_multicast = g_inet4_address_is_multicast; + ginetaddress_class->is_mc_global = g_inet4_address_is_mc_global; + ginetaddress_class->is_mc_linklocal = g_inet4_address_is_mc_linklocal; + ginetaddress_class->is_mc_nodelocal = g_inet4_address_is_mc_nodelocal; + ginetaddress_class->is_mc_orglocal = g_inet4_address_is_mc_orglocal; + ginetaddress_class->is_mc_sitelocal = g_inet4_address_is_mc_sitelocal; } static void @@ -84,38 +174,66 @@ g_inet4_address_init (GInet4Address *address) /* Public Functions */ GInet4Address * -g_inet4_address_from_string (const char *string) +g_inet4_address_from_string (const gchar *string) { - return NULL; + struct in_addr addr; + + if (!inet_aton (string, &addr)) + { + g_warning ("Could not parse IP address %s", string); + return NULL; + } + + return g_inet4_address_from_bytes ((guint8 *) &(addr.s_addr)); } char * g_inet4_address_to_string (GInet4Address *address) { - return NULL; + guint8 *addr; + + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), NULL); + + addr = address->priv->addr.u4_addr8; + + return g_strdup_printf ("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); } GInet4Address * g_inet4_address_from_bytes (guint8 bytes[]) { - return NULL; + GInet4Address *address = G_INET4_ADDRESS (g_object_new (G_TYPE_INET4_ADDRESS, NULL)); + + guint8 *addr = address->priv->addr.u4_addr8; + + addr[0] = bytes[0]; + addr[1] = bytes[1]; + addr[2] = bytes[2]; + addr[3] = bytes[3]; + + return address; } const guint8 * g_inet4_address_to_bytes (GInet4Address *address) { - return NULL; + g_return_val_if_fail (G_IS_INET4_ADDRESS (address), NULL); + + return address->priv->addr.u4_addr8; } -GInetAddress * -g_inet4address_new_loopback (void) +GInet4Address * +g_inet4_address_new_loopback (void) { - return NULL; + guint8 addr[8] = {127, 0, 0, 1}; + + return g_inet4_address_from_bytes (addr); } -GInetAddress * -g_inet4address_new_any (void) +GInet4Address * +g_inet4_address_new_any (void) { - return NULL; -} + guint8 addr[8] = {0, 0, 0, 0}; + return g_inet4_address_from_bytes (addr); +} diff --git a/gnio/ginet4address.h b/gnio/ginet4address.h index 39de93d..e9e8f59 100644 --- a/gnio/ginet4address.h +++ b/gnio/ginet4address.h @@ -2,7 +2,7 @@ #define G_INET4_ADDRESS_H #include -#include +#include G_BEGIN_DECLS @@ -17,30 +17,31 @@ typedef struct _GInet4Address GInet4Address; typedef struct _GInet4AddressClass GInet4AddressClass; typedef struct _GInet4AddressPrivate GInet4AddressPrivate; -struct _GInet4Address { - - GInetAddress parent; +struct _GInet4Address +{ + GInetAddress parent; - GInet4AddressPrivate *priv; + GInet4AddressPrivate *priv; }; -struct _GInet4AddressClass { - - GInetAddressClass parent_class; +struct _GInet4AddressClass +{ + GInetAddressClass parent_class; }; +GType g_inet4_address_get_type (void) G_GNUC_CONST; -GType g_inet4_address_get_type (void) G_GNUC_CONST; +GInet4Address * g_inet4_address_from_string (const char *string); -GInet4Address * g_inet4_address_from_string (const char *string); -char * g_inet4_address_to_string (GInet4Address *address); +char * g_inet4_address_to_string (GInet4Address *address); -GInet4Address * g_inet4_address_from_bytes (guint8 bytes[]); -const guint8 * g_inet4_address_to_bytes (GInet4Address *address); +GInet4Address * g_inet4_address_from_bytes (guint8 bytes[]); -GInetAddress * g_inet4address_new_loopback (void); -GInetAddress * g_inet4address_new_any (void); +const guint8 * g_inet4_address_to_bytes (GInet4Address *address); +GInet4Address * g_inet4_address_new_loopback (void); + +GInet4Address * g_inet4_address_new_any (void); G_END_DECLS diff --git a/gnio/ginet6address.c b/gnio/ginet6address.c index 7016ff0..3fff994 100644 --- a/gnio/ginet6address.c +++ b/gnio/ginet6address.c @@ -21,31 +21,26 @@ */ #include +#include #include #include "ginet6address.h" - G_DEFINE_TYPE (GInet6Address, g_inet6_address, G_TYPE_INET_ADDRESS); struct _GInet6AddressPrivate { - - union { - guint8 u6_addr8[16]; - guint16 u6_addr16[8]; - guint32 u6_addr32[4]; - - } addr; + union { + guint8 u6_addr8[16]; + guint16 u6_addr16[8]; + guint32 u6_addr32[4]; + } addr; }; - static void g_inet6_address_finalize (GObject *object) { - GInet6Address *address; + GInet6Address *address G_GNUC_UNUSED = G_INET6_ADDRESS (object); - address = G_INET6_ADDRESS (object); - if (G_OBJECT_CLASS (g_inet6_address_parent_class)->finalize) (*G_OBJECT_CLASS (g_inet6_address_parent_class)->finalize) (object); } @@ -53,25 +48,21 @@ g_inet6_address_finalize (GObject *object) static void g_inet6_address_dispose (GObject *object) { - GInet6Address *address; + GInet6Address *address G_GNUC_UNUSED = G_INET6_ADDRESS (object); - address = G_INET6_ADDRESS (object); - if (G_OBJECT_CLASS (g_inet6_address_parent_class)->dispose) (*G_OBJECT_CLASS (g_inet6_address_parent_class)->dispose) (object); } - static void g_inet6_address_class_init (GInet6AddressClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - + g_type_class_add_private (klass, sizeof (GInet6AddressPrivate)); - + gobject_class->finalize = g_inet6_address_finalize; gobject_class->dispose = g_inet6_address_dispose; - } static void @@ -88,7 +79,7 @@ g_inet6_address_init (GInet6Address *address) GInet6Address * g_inet6_address_from_string (const char *string) { - return NULL; + return NULL; } char * @@ -100,7 +91,11 @@ g_inet6_address_to_string (GInet6Address *address) GInet6Address * g_inet6_address_from_bytes (guint8 bytes[]) { - return NULL; + GInet6Address *address = G_INET6_ADDRESS (g_object_new (G_TYPE_INET6_ADDRESS, NULL)); + + g_memmove (address->priv->addr.u6_addr8, bytes, 16); + + return address; } const guint8 * @@ -109,15 +104,16 @@ g_inet6_address_to_bytes (GInet6Address *address) return NULL; } -GInetAddress * -g_inet6address_new_loopback (void) +GInet6Address * +g_inet6_address_new_loopback (void) { - return NULL; + guint8 bytes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + + return g_inet6_address_from_bytes (bytes); } -GInetAddress * -g_inet6address_new_any (void) +GInet6Address * +g_inet6_address_new_any (void) { return NULL; } - diff --git a/gnio/ginet6address.h b/gnio/ginet6address.h index 146b98d..ea85526 100644 --- a/gnio/ginet6address.h +++ b/gnio/ginet6address.h @@ -17,29 +17,32 @@ typedef struct _GInet6Address GInet6Address; typedef struct _GInet6AddressClass GInet6AddressClass; typedef struct _GInet6AddressPrivate GInet6AddressPrivate; -struct _GInet6Address { - - GInetAddress parent; +struct _GInet6Address +{ + GInetAddress parent; - GInet6AddressPrivate *priv; + GInet6AddressPrivate *priv; }; -struct _GInet6AddressClass { - - GInetAddressClass parent_class; +struct _GInet6AddressClass +{ + GInetAddressClass parent_class; }; +GType g_inet6_address_get_type (void) G_GNUC_CONST; -GType g_inet6_address_get_type (void) G_GNUC_CONST; +GInet6Address * g_inet6_address_from_string (const char *string); -GInet6Address * g_inet6_address_from_string (const char *string); -char * g_inet6_address_to_string (GInet6Address *address); +char * g_inet6_address_to_string (GInet6Address *address); -GInet6Address * g_inet6_address_from_bytes (guint8 bytes[]); -const guint8 * g_inet6_address_to_bytes (GInet6Address *address); +GInet6Address * g_inet6_address_from_bytes (guint8 bytes[]); + +const guint8 * g_inet6_address_to_bytes (GInet6Address *address); + +GInet6Address * g_inet6_address_new_loopback (void); + +GInet6Address * g_inet6_address_new_any (void); -GInetAddress * g_inet6address_new_loopback (void); -GInetAddress * g_inet6address_new_any (void); G_END_DECLS #endif /* G_INET6_ADDRESS_H */ diff --git a/gnio/ginetaddress.c b/gnio/ginetaddress.c index 782c707..ed02fc3 100644 --- a/gnio/ginetaddress.c +++ b/gnio/ginetaddress.c @@ -35,136 +35,214 @@ G_DEFINE_ABSTRACT_TYPE (GInetAddress, g_inet_address, G_TYPE_OBJECT); +enum +{ + PROP_0, + PROP_IS_ANY, + PROP_IS_LINKLOCAL, + PROP_IS_LOOPBACK, + PROP_IS_SITELOCAL, + PROP_IS_MULTICAST, + PROP_IS_MC_GLOBAL, + PROP_IS_MC_LINKLOCAL, + PROP_IS_MC_NODELOCAL, + PROP_IS_MC_ORGLOCAL, + PROP_IS_MC_SITELOCAL, +}; +static void +g_inet_address_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GInetAddress *address = G_INET_ADDRESS (object); + switch (prop_id) + { + case PROP_IS_ANY: + g_value_set_boolean (value, G_INET_ADDRESS_GET_CLASS (address)->is_any (address)); + break; + case PROP_IS_LINKLOCAL: + g_value_set_boolean (value, G_INET_ADDRESS_GET_CLASS (address)->is_linklocal (address)); + break; -static void -g_inet_address_class_init (GInetAddressClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + case PROP_IS_LOOPBACK: + g_value_set_boolean (value, G_INET_ADDRESS_GET_CLASS (address)->is_loopback (address)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void -g_inet_address_init (GInetAddress *address) +g_inet_address_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + GInetAddress *address G_GNUC_UNUSED = G_INET_ADDRESS (object); + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } -/* ************************************************************************* */ -/* Public Functions */ - -GInetAddress * -g_inet_address_resolve (const char *host, - GCancellable *cancellable, - GError **error) +static void +g_inet_address_class_init (GInetAddressClass *klass) { - return NULL; + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = g_inet_address_get_property; + gobject_class->set_property = g_inet_address_set_property; + + g_object_class_install_property (gobject_class, PROP_IS_ANY, + g_param_spec_boolean ("is-any", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_LINKLOCAL, + g_param_spec_boolean ("is-link-local", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_LOOPBACK, + g_param_spec_boolean ("is-loopback", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_SITELOCAL, + g_param_spec_boolean ("is-site-local", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_MULTICAST, + g_param_spec_boolean ("is-multicast", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_MC_GLOBAL, + g_param_spec_boolean ("is-mc-global", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_MC_LINKLOCAL, + g_param_spec_boolean ("is-mc-link-local", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_MC_NODELOCAL, + g_param_spec_boolean ("is-mc-node-local", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_MC_ORGLOCAL, + g_param_spec_boolean ("is-mc-org-local", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_IS_MC_SITELOCAL, + g_param_spec_boolean ("is-mc-site-local", + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME)); } -void -g_inet_address_resolve_async (const char *host, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +static void +g_inet_address_init (GInetAddress *address) { } -GInetAddress * -g_inet_address_resolve_finish (GInetAddress *address, - GAsyncResult *result, - GError **error) -{ - return NULL; -} +/* ******************************************* */ +/* Getters for properties */ -char * -g_inet_address_lookup_reverse (GInetAddress *address, - GCancellable *cancellable, - GError **error) +static gboolean +get_boolean_property (GInetAddress *address, const gchar *property) { - return NULL; -} + gboolean value; -void -g_inet_address_lookup_reverse_async (GInetAddress *address, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ + g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE); -} + g_object_get (address, property, &value, NULL); -char * -g_inet_address_lookup_reverse_finish (GInetAddress *address, - GAsyncResult *result, - GError **error) -{ - return NULL; + return value; } -/* ******************************************* */ -/* Getteres for properties*/ - gboolean -g_inet_address_is_any_local (GInetAddress *address) +g_inet_address_is_any (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-any"); } gboolean -g_inet_address_is_link_local (GInetAddress *address) +g_inet_address_is_linklocal (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-link-local"); } gboolean g_inet_address_is_loopback (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-loopback"); } gboolean g_inet_address_is_sitelocal (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-site-local"); } gboolean g_inet_address_is_multicast (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-multicast"); } gboolean g_inet_address_is_mc_global (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-mc-global"); } gboolean g_inet_address_is_mc_linklocal (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-mc-link-local"); } gboolean g_inet_address_is_mc_nodelocal (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-mc-node-local"); } gboolean g_inet_address_is_mc_orglocal (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-mc-org-local"); } gboolean g_inet_address_is_mc_sitelocal (GInetAddress *address) { - return FALSE; + return get_boolean_property (address, "is-mc-site-local"); } diff --git a/gnio/ginetaddress.h b/gnio/ginetaddress.h index 815df40..eec559e 100644 --- a/gnio/ginetaddress.h +++ b/gnio/ginetaddress.h @@ -2,8 +2,7 @@ #define G_INET_ADDRESS_H #include -#include -#include +#include G_BEGIN_DECLS @@ -14,63 +13,52 @@ G_BEGIN_DECLS #define G_IS_INET_ADDRESS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_INET_ADDRESS)) #define G_INET_ADDRESS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_INET_ADDRESS, GInetAddressClass)) -typedef struct GInetAddress GInetAddress; -typedef struct GInetAddressClass GInetAddressClass; +typedef struct _GInetAddress GInetAddress; +typedef struct _GInetAddressClass GInetAddressClass; -struct GInetAddress { - +struct _GInetAddress +{ GObject parent; - }; -struct GInetAddressClass { - +struct _GInetAddressClass +{ GObjectClass parent_class; -}; - -GType g_inet_address_get_type (void) G_GNUC_CONST; - - -/* DNS query functions */ -GInetAddress *g_inet_address_resolve (const char *host, - GCancellable *cancellable, - GError **error); -void g_inet_address_resolve_async (const char *host, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -GInetAddress * g_inet_address_resolve_finish (GInetAddress *address, - GAsyncResult *result, - GError **error); + gboolean (*is_any) (GInetAddress *address); + gboolean (*is_linklocal) (GInetAddress *address); + gboolean (*is_loopback) (GInetAddress *address); + gboolean (*is_sitelocal) (GInetAddress *address); + gboolean (*is_multicast) (GInetAddress *address); + gboolean (*is_mc_global) (GInetAddress *address); + gboolean (*is_mc_linklocal) (GInetAddress *address); + gboolean (*is_mc_nodelocal) (GInetAddress *address); + gboolean (*is_mc_orglocal) (GInetAddress *address); + gboolean (*is_mc_sitelocal) (GInetAddress *address); +}; -char * g_inet_address_lookup_reverse (GInetAddress *address, - GCancellable *cancellable, - GError **error); +GType g_inet_address_get_type (void) G_GNUC_CONST; -void g_inet_address_lookup_reverse_async (GInetAddress *address, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +/* accessors to gobject properties that get overridden by subclasses */ +gboolean g_inet_address_is_any (GInetAddress *address); -char * g_inet_address_lookup_reverse_finish (GInetAddress *address, - GAsyncResult *result, - GError **error); +gboolean g_inet_address_is_linklocal (GInetAddress *address); -/* accessors to gobject properties that get overridden by subclasses */ -gboolean g_inet_address_is_any_local (GInetAddress *address); -gboolean g_inet_address_is_link_local (GInetAddress *address); gboolean g_inet_address_is_loopback (GInetAddress *address); + gboolean g_inet_address_is_sitelocal (GInetAddress *address); + gboolean g_inet_address_is_multicast (GInetAddress *address); + gboolean g_inet_address_is_mc_global (GInetAddress *address); + gboolean g_inet_address_is_mc_linklocal (GInetAddress *address); + gboolean g_inet_address_is_mc_nodelocal (GInetAddress *address); -gboolean g_inet_address_is_mc_orglocal (GInetAddress *address); -gboolean g_inet_address_is_mc_sitelocal (GInetAddress *address); +gboolean g_inet_address_is_mc_orglocal (GInetAddress *address); +gboolean g_inet_address_is_mc_sitelocal (GInetAddress *address); G_END_DECLS diff --git a/gnio/ginetsocketaddress.c b/gnio/ginetsocketaddress.c index 4c1a232..5682657 100644 --- a/gnio/ginetsocketaddress.c +++ b/gnio/ginetsocketaddress.c @@ -25,23 +25,24 @@ #include "ginetsocketaddress.h" - G_DEFINE_TYPE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS); -struct _GInetSocketAddressPrivate { - - GInetAddress *address; - guint16 port; +enum { + PROP_0, + PROP_ADDRESS, + PROP_PORT }; +struct _GInetSocketAddressPrivate { + GInetAddress *address; + guint16 port; +}; static void g_inet_socket_address_finalize (GObject *object) { - GInetSocketAddress *address; + GInetSocketAddress *address G_GNUC_UNUSED = G_INET_SOCKET_ADDRESS (object); - address = G_INET_SOCKET_ADDRESS (object); - if (G_OBJECT_CLASS (g_inet_socket_address_parent_class)->finalize) (*G_OBJECT_CLASS (g_inet_socket_address_parent_class)->finalize) (object); } @@ -49,25 +50,75 @@ g_inet_socket_address_finalize (GObject *object) static void g_inet_socket_address_dispose (GObject *object) { - GInetSocketAddress *address; + GInetSocketAddress *address G_GNUC_UNUSED = G_INET_SOCKET_ADDRESS (object); - address = G_INET_SOCKET_ADDRESS (object); - if (G_OBJECT_CLASS (g_inet_socket_address_parent_class)->dispose) (*G_OBJECT_CLASS (g_inet_socket_address_parent_class)->dispose) (object); } +static void +g_inet_socket_address_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object); + + switch (prop_id) + { + case PROP_ADDRESS: + g_value_set_object (value, address->priv->address); + break; + + case PROP_PORT: + g_value_set_uint (value, address->priv->port); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_inet_socket_address_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object); + + switch (prop_id) + { + case PROP_ADDRESS: + address->priv->address = G_INET_ADDRESS (g_value_get_object (value)); + break; + + case PROP_PORT: + address->priv->port = (guint16) g_value_get_uint (value); + } +} static void g_inet_socket_address_class_init (GInetSocketAddressClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - + g_type_class_add_private (klass, sizeof (GInetSocketAddressPrivate)); - + gobject_class->finalize = g_inet_socket_address_finalize; gobject_class->dispose = g_inet_socket_address_dispose; - + gobject_class->set_property = g_inet_socket_address_set_property; + gobject_class->get_property = g_inet_socket_address_get_property; + + g_object_class_install_property (gobject_class, PROP_ADDRESS, + g_param_spec_object ("address", + "address", + "address", + G_TYPE_INET_ADDRESS, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); + + g_object_class_install_property (gobject_class, PROP_PORT, + g_param_spec_uint ("port", + "port", + "port", + 0, + 65535, + 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); } static void @@ -82,19 +133,23 @@ g_inet_socket_address_init (GInetSocketAddress *address) GInetSocketAddress * g_inet_socket_address_new (GInetAddress *address, guint16 port) { - return NULL; + return NULL; } GInetAddress * g_inet_socket_address_get_address (GInetSocketAddress *sockaddr) { - return NULL; + g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (sockaddr), NULL); + + return sockaddr->priv->address; } guint16 g_inet_socket_address_get_port (GInetSocketAddress *sockaddr) { - return 0; + g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (sockaddr), 0); + + return sockaddr->priv->port; } diff --git a/gnio/ginetsocketaddress.h b/gnio/ginetsocketaddress.h index d4740ed..f4cfef5 100644 --- a/gnio/ginetsocketaddress.h +++ b/gnio/ginetsocketaddress.h @@ -18,27 +18,25 @@ typedef struct _GInetSocketAddress GInetSocketAddress; typedef struct _GInetSocketAddressClass GInetSocketAddressClass; typedef struct _GInetSocketAddressPrivate GInetSocketAddressPrivate; -struct _GInetSocketAddress { - - GSocketAddress parent; +struct _GInetSocketAddress +{ + GSocketAddress parent; - GInetSocketAddressPrivate *priv; + GInetSocketAddressPrivate *priv; }; -struct _GInetSocketAddressClass { - - GSocketAddressClass parent_class; +struct _GInetSocketAddressClass +{ + GSocketAddressClass parent_class; }; +GType g_inet_socket_address_get_type (void) G_GNUC_CONST; -GType g_inet_socket_address_get_type (void) G_GNUC_CONST; +GInetSocketAddress * g_inet_socket_address_new (GInetAddress *address, guint16 port); -GInetSocketAddress *g_inet_socket_address_new (GInetAddress *address, guint16 port); - - -GInetAddress *g_inet_socket_address_get_address (GInetSocketAddress *sockaddr); -guint16 g_inet_socket_address_get_port (GInetSocketAddress *sockaddr); +GInetAddress * g_inet_socket_address_get_address (GInetSocketAddress *sockaddr); +guint16 g_inet_socket_address_get_port (GInetSocketAddress *sockaddr); G_END_DECLS diff --git a/gnio/gsocketaddress.c b/gnio/gsocketaddress.c index 600662e..5dc4fd5 100644 --- a/gnio/gsocketaddress.c +++ b/gnio/gsocketaddress.c @@ -25,14 +25,12 @@ #include "gsocketaddress.h" - G_DEFINE_ABSTRACT_TYPE (GSocketAddress, g_socket_address, G_TYPE_OBJECT); static void g_socket_address_class_init (GSocketAddressClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - + GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass); } static void diff --git a/gnio/gsocketaddress.h b/gnio/gsocketaddress.h index 4b861b9..09a5a9b 100644 --- a/gnio/gsocketaddress.h +++ b/gnio/gsocketaddress.h @@ -15,21 +15,18 @@ G_BEGIN_DECLS typedef struct _GSocketAddress GSocketAddress; typedef struct _GSocketAddressClass GSocketAddressClass; -struct _GSocketAddress { - - GObject parent; - +struct _GSocketAddress +{ + GObject parent; }; -struct _GSocketAddressClass { - - GObjectClass parent_class; +struct _GSocketAddressClass +{ + GObjectClass parent_class; }; - GType g_socket_address_get_type (void) G_GNUC_CONST; G_END_DECLS #endif /* G_SOCKET_ADDRESS_H */ - diff --git a/test/Makefile.am b/test/Makefile.am index 2a27ad1..08d7702 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,7 +7,7 @@ AM_CFLAGS = \ -DG_DISABLE_DEPRECATED AM_LDFLAGS = \ - $(GLIB_LIBS) + $(GLIB_LIBS) -lgio-2.0 -lgnio noinst_PROGRAMS = \ test-stuff \ diff --git a/test/test-stuff.c b/test/test-stuff.c index f70dc41..0972fad 100644 --- a/test/test-stuff.c +++ b/test/test-stuff.c @@ -1,7 +1,103 @@ +#include +#include +#include +#include +#include +#include +GMainLoop *loop; -int -main (int argc, char **argv) +void print_address (GInetAddress *address, gpointer data); + +void +print_address (GInetAddress *address, gpointer data) +{ + gchar *string = g_inet4_address_to_string (G_INET4_ADDRESS (address)); + + g_printf ("%s\n", string); + + g_free (string); +} + +void +resolve_callback (GObject *source, GAsyncResult *result, gpointer data) { - return 0; + GError *error = NULL; + + GResolver *resolver = G_RESOLVER (source); + + GList *list; + + list = g_resolver_resolve_list_finish (resolver, result, &error); + + if (error) { + g_error (error->message); + return; + } + + g_printf ("\nwww.google.com (list, async):\n"); + + g_list_foreach (list, (GFunc) print_address, NULL); + + g_list_foreach (list, (GFunc) g_object_unref, NULL); + + g_list_free (list); + + g_main_loop_quit (loop); +} + +int main (int argc, char *argv[]) +{ + GInetAddress *address; + GResolver *resolver; + GError *error = NULL; + + loop = g_main_loop_new (NULL, FALSE); + + g_type_init (); + + address = (GInetAddress *) g_inet4_address_from_string ("127.0.0.1"); + + g_printf ("%s:\n", g_inet4_address_to_string (G_INET4_ADDRESS (address))); + + g_printf ("is_any: %d, is_linklocal: %d, is_loopback: %d\n", g_inet_address_is_any (address), g_inet_address_is_linklocal (address), g_inet_address_is_loopback (address)); + + g_object_unref (address); + + address = (GInetAddress *) g_inet4_address_from_string ("0.0.0.0"); + + g_printf ("\n%s:\n", g_inet4_address_to_string (G_INET4_ADDRESS (address))); + + g_printf ("is_any: %d, is_linklocal: %d, is_loopback: %d\n", g_inet_address_is_any (address), g_inet_address_is_linklocal (address), g_inet_address_is_loopback (address)); + + g_object_unref (address); + + address = (GInetAddress *) g_inet4_address_from_string ("169.254.0.0"); + + g_printf ("\n%s:\n", g_inet4_address_to_string (G_INET4_ADDRESS (address))); + + g_printf ("is_any: %d, is_linklocal: %d, is_loopback: %d\n", g_inet_address_is_any (address), g_inet_address_is_linklocal (address), g_inet_address_is_loopback (address)); + + g_object_unref (address); + + resolver = G_RESOLVER (g_object_new (G_TYPE_RESOLVER, NULL)); + + address = g_resolver_resolve (resolver, "www.yahoo.com", NULL, &error); + + if (!address) { + g_error (error->message); + return 0; + } + + g_printf ("\nwww.yahoo.com: %s\n", g_inet4_address_to_string (G_INET4_ADDRESS (address))); + + g_printf ("is_any: %d, is_linklocal: %d, is_loopback: %d\n", g_inet_address_is_any (address), g_inet_address_is_linklocal (address), g_inet_address_is_loopback (address)); + + g_object_unref (address); + + g_resolver_resolve_list_async (resolver, "www.google.com", NULL, resolve_callback, NULL); + + g_main_loop_run (loop); + + return 0; }