From 0063fdbe36db08ecfa9684434f51a95624e1a842 Mon Sep 17 00:00:00 2001 From: Samuel Cormier-Iijima Date: Sun, 17 Feb 2008 09:39:29 -0500 Subject: [PATCH] Converting InetAddresses to native struct in*_addr and SocketAddresses to struct sockaddr_* --- gnio/ginetaddress.h | 4 ++ gnio/ginetsocketaddress.c | 57 +++++++++++++++++++++++++ gnio/gsocket.c | 88 ++++++++++++++++++++++++++++++++++++--- gnio/gsocket.h | 14 +++++-- gnio/gsocketaddress.c | 16 +++++++ gnio/gsocketaddress.h | 10 ++++- test/Makefile.am | 1 + test/test-server.c | 26 ++++++++++++ 8 files changed, 206 insertions(+), 10 deletions(-) create mode 100644 test/test-server.c diff --git a/gnio/ginetaddress.h b/gnio/ginetaddress.h index 305ded2..6f01c7b 100644 --- a/gnio/ginetaddress.h +++ b/gnio/ginetaddress.h @@ -65,6 +65,10 @@ GType g_inet_address_get_type (void) G_GNUC_CONST; gchar * g_inet_address_to_string (GInetAddress *address); +gsize g_inet_address_sockaddr_size (GInetAddress *address); + +gboolean g_inet_address_to_sockaddr (GInetAddress *address, gpointer dest); + gboolean g_inet_address_is_any (GInetAddress *address); gboolean g_inet_address_is_linklocal (GInetAddress *address); diff --git a/gnio/ginetsocketaddress.c b/gnio/ginetsocketaddress.c index 6b2d7b1..5913aee 100644 --- a/gnio/ginetsocketaddress.c +++ b/gnio/ginetsocketaddress.c @@ -23,8 +23,14 @@ #include #include +#include +#include +#include #include "ginetsocketaddress.h" +#include "ginetaddress.h" +#include "ginet4address.h" +#include "ginet6address.h" G_DEFINE_TYPE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS); @@ -94,10 +100,55 @@ g_inet_socket_address_set_property (GObject *object, guint prop_id, const GValue } } +static gssize +g_inet_socket_address_native_size (GSocketAddress *address) +{ + GInetSocketAddress *addr; + + g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0); + + addr = G_INET_SOCKET_ADDRESS (address); + + if (G_IS_INET4_ADDRESS (addr->priv->address)) + return sizeof (struct sockaddr_in); + else if (G_IS_INET6_ADDRESS (addr->priv->address)) + return sizeof (struct sockaddr_in6); + else + return -1; +} + +static gboolean +g_inet_socket_address_to_native (GSocketAddress *address, gpointer dest) +{ + GInetSocketAddress *addr; + + g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0); + + addr = G_INET_SOCKET_ADDRESS (address); + + if (G_IS_INET4_ADDRESS (addr->priv->address)) + { + struct sockaddr_in *sock = (struct sockaddr_in *) dest; + + sock->sin_family = AF_INET; + sock->sin_port = addr->priv->port; + memcpy (&(sock->sin_addr.s_addr), g_inet4_address_to_bytes (G_INET4_ADDRESS (addr->priv->address)), sizeof (sock->sin_addr)); + memset (sock->sin_zero, 0, sizeof (sock->sin_zero)); + return TRUE; + } + else if (G_IS_INET6_ADDRESS (addr->priv->address)) + { + return FALSE; + } + else + return FALSE; +} + static void g_inet_socket_address_class_init (GInetSocketAddressClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass); g_type_class_add_private (klass, sizeof (GInetSocketAddressPrivate)); @@ -106,6 +157,9 @@ g_inet_socket_address_class_init (GInetSocketAddressClass *klass) gobject_class->set_property = g_inet_socket_address_set_property; gobject_class->get_property = g_inet_socket_address_get_property; + gsocketaddress_class->to_native = g_inet_socket_address_to_native; + gsocketaddress_class->native_size = g_inet_socket_address_native_size; + g_object_class_install_property (gobject_class, PROP_ADDRESS, g_param_spec_object ("address", "address", @@ -129,6 +183,9 @@ g_inet_socket_address_init (GInetSocketAddress *address) address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address, G_TYPE_INET_SOCKET_ADDRESS, GInetSocketAddressPrivate); + + address->priv->address = NULL; + address->priv->port = 0; } diff --git a/gnio/gsocket.c b/gnio/gsocket.c index c0a8a1a..42b6394 100644 --- a/gnio/gsocket.c +++ b/gnio/gsocket.c @@ -30,12 +30,9 @@ # include # include # include +# include #else -# include -# include -# include -# undef HAVE_GETADDRINFO -# define HAVE_GETHOSTBYNAME_THREADSAFE 1 + #endif #include @@ -53,12 +50,33 @@ struct _GSocketPrivate int fd; }; +static void +g_socket_finalize (GObject *object) +{ + GSocket *socket G_GNUC_UNUSED = G_SOCKET (object); + + if (G_OBJECT_CLASS (g_socket_parent_class)->finalize) + (*G_OBJECT_CLASS (g_socket_parent_class)->finalize) (object); +} + +static void +g_socket_dispose (GObject *object) +{ + GSocket *socket G_GNUC_UNUSED = G_SOCKET (object);; + + if (G_OBJECT_CLASS (g_socket_parent_class)->dispose) + (*G_OBJECT_CLASS (g_socket_parent_class)->dispose) (object); +} + static void g_socket_class_init (GSocketClass *klass) { GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (GSocketPrivate)); + + gobject_class->finalize = g_socket_finalize; + gobject_class->dispose = g_socket_dispose; } static void @@ -73,6 +91,28 @@ g_socket_new () return G_SOCKET (g_object_new (G_TYPE_SOCKET, NULL)); } +GSocket * +g_socket_new_from_fd (gint fd) +{ + return G_SOCKET (g_object_new (G_TYPE_SOCKET, NULL)); +} + +void +g_socket_set_blocking (GSocket *socket, gboolean blocking) +{ + glong arg; + + g_return_if_fail (G_IS_SOCKET (socket)); + + if ((arg = fcntl (socket->priv->fd, F_GETFL, NULL)) < 0) + g_warning ("Error getting socket status flags: %s", g_strerror (errno)); + + arg = blocking ? arg | O_NONBLOCK : arg & ~O_NONBLOCK; + + if (fcntl (socket->priv->fd, F_SETFL, arg) < 0) + g_warning ("Error setting socket status flags: %s", g_strerror (errno)); +} + void g_socket_listen (GSocket *socket, gint backlog) { @@ -80,3 +120,41 @@ g_socket_listen (GSocket *socket, gint backlog) listen (socket->priv->fd, backlog); } + +gboolean +g_socket_connect (GSocket *socket, + GSocketAddress *address, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); +/* + if (connect () < 0) + { + if (errno == EINPROGRESS) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, "connection in progress"); + else + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error connecting: %s", g_strerror (errno)); + return FALSE; + } +*/ + return TRUE; +} + +void +g_socket_connect_async (GSocket *socket, + GSocketAddress *address, + GCancellable *cancellable, + GAsyncReadyCallback *callback, + gpointer user_data) +{ + +} + +gboolean +g_socket_connect_finish (GSocket *socket, + GAsyncResult *result, + GError **error) +{ + +} diff --git a/gnio/gsocket.h b/gnio/gsocket.h index 4143d3e..7a0a568 100644 --- a/gnio/gsocket.h +++ b/gnio/gsocket.h @@ -59,13 +59,19 @@ GType g_socket_get_type (void) G_GNUC_CONST; GSocket * g_socket_new (void); +GSocket * g_socket_new_from_fd (gint fd); + +void g_socket_set_blocking (GSocket *socket, + gboolean blocking); + gboolean g_socket_bind (GSocket *socket, GSocketAddress *address, GError **error); -void g_socket_connect (GSocket *socket, - GSocketAddress *address, - GCancellable *cancellable); +gboolean g_socket_connect (GSocket *socket, + GSocketAddress *address, + GCancellable *cancellable, + GError **error); void g_socket_connect_async (GSocket *socket, GSocketAddress *address, @@ -73,7 +79,7 @@ void g_socket_connect_async (GSocket *socket, GAsyncReadyCallback *callback, gpointer user_data); -void g_socket_connect_finish (GSocket *socket, +gboolean g_socket_connect_finish (GSocket *socket, GAsyncResult *result, GError **error); diff --git a/gnio/gsocketaddress.c b/gnio/gsocketaddress.c index 88b4700..0f904cc 100644 --- a/gnio/gsocketaddress.c +++ b/gnio/gsocketaddress.c @@ -39,3 +39,19 @@ g_socket_address_init (GSocketAddress *address) { } + +gssize +g_socket_address_native_size (GSocketAddress *address) +{ + g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), -1); + + return G_SOCKET_ADDRESS_GET_CLASS (address)->native_size (address); +} + +gboolean +g_socket_address_to_native (GSocketAddress *address, gpointer dest) +{ + g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE); + + return G_SOCKET_ADDRESS_GET_CLASS (address)->to_native (address, dest); +} diff --git a/gnio/gsocketaddress.h b/gnio/gsocketaddress.h index 72fdcce..985ae5f 100644 --- a/gnio/gsocketaddress.h +++ b/gnio/gsocketaddress.h @@ -46,9 +46,17 @@ struct _GSocketAddress struct _GSocketAddressClass { GObjectClass parent_class; + + gssize (*native_size) (GSocketAddress *address); + + gboolean (*to_native) (GSocketAddress *address, gpointer dest); }; -GType g_socket_address_get_type (void) G_GNUC_CONST; +GType g_socket_address_get_type (void) G_GNUC_CONST; + +gboolean g_socket_address_to_native (GSocketAddress *address, gpointer dest); + +gssize g_socket_address_native_size (GSocketAddress *address); G_END_DECLS diff --git a/test/Makefile.am b/test/Makefile.am index 637039b..8366f20 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -11,6 +11,7 @@ AM_LDFLAGS = \ noinst_PROGRAMS = \ test-stuff \ + test-server \ $(NULL) EXTRA_DIST = diff --git a/test/test-server.c b/test/test-server.c new file mode 100644 index 0000000..0bbdb0e --- /dev/null +++ b/test/test-server.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +GMainLoop *loop; + +int main (int argc, char *argv[]) +{ + GSocket *socket; + GError *error = NULL; + + g_thread_init (NULL); + + g_type_init (); + + loop = g_main_loop_new (NULL, FALSE); + + socket = g_socket_new (); + + g_socket_set_blocking (socket, FALSE); + + g_main_loop_run (loop); + + return 0; +} -- 2.20.1