From a6fb7a0df0b70717e0a21635471af65cdbd239e4 Mon Sep 17 00:00:00 2001 From: Samuel Cormier-Iijima Date: Tue, 26 Feb 2008 21:40:10 -0500 Subject: [PATCH] Some more stuff for GSockets --- gnio/ginetsocketaddress.c | 10 ++- gnio/ginetsocketaddress.h | 4 +- gnio/gsocket.c | 96 ++++++++++++++++++++++- gnio/gsocket.h | 156 +++++++++++++++++++------------------- gnio/gsocketaddress.c | 29 +++++++ gnio/gsocketaddress.h | 8 +- test/test-server.c | 22 +++++- 7 files changed, 234 insertions(+), 91 deletions(-) diff --git a/gnio/ginetsocketaddress.c b/gnio/ginetsocketaddress.c index 60fe284..f636162 100644 --- a/gnio/ginetsocketaddress.c +++ b/gnio/ginetsocketaddress.c @@ -99,6 +99,10 @@ g_inet_socket_address_set_property (GObject *object, guint prop_id, const GValue case PROP_PORT: address->priv->port = (guint16) g_value_get_uint (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } @@ -133,7 +137,7 @@ g_inet_socket_address_to_native (GSocketAddress *address, gpointer dest) struct sockaddr_in *sock = (struct sockaddr_in *) dest; sock->sin_family = AF_INET; - sock->sin_port = addr->priv->port; + sock->sin_port = g_htons (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; @@ -167,7 +171,7 @@ g_inet_socket_address_class_init (GInetSocketAddressClass *klass) "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_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | 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", @@ -176,7 +180,7 @@ g_inet_socket_address_class_init (GInetSocketAddressClass *klass) 0, 65535, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); } static void diff --git a/gnio/ginetsocketaddress.h b/gnio/ginetsocketaddress.h index 670a5e7..5982e55 100644 --- a/gnio/ginetsocketaddress.h +++ b/gnio/ginetsocketaddress.h @@ -25,8 +25,8 @@ #define G_INET_SOCKET_ADDRESS_H #include -#include -#include +#include "gsocketaddress.h" +#include "ginetaddress.h" G_BEGIN_DECLS diff --git a/gnio/gsocket.c b/gnio/gsocket.c index 3cf7534..fe93ca8 100644 --- a/gnio/gsocket.c +++ b/gnio/gsocket.c @@ -31,6 +31,7 @@ # include # include # include +# include #else #endif @@ -48,7 +49,8 @@ G_DEFINE_TYPE (GSocket, g_socket, G_TYPE_OBJECT); enum { PROP_0, - PROP_FD + PROP_FD, + PROP_BLOCKING }; struct _GSocketPrivate @@ -68,6 +70,10 @@ g_socket_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec g_value_set_int (value, socket->priv->fd); break; + case PROP_BLOCKING: + g_value_set_boolean (value, socket->priv->blocking); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -84,6 +90,10 @@ g_socket_set_property (GObject *object, guint prop_id, const GValue *value, GPar socket->priv->fd = g_value_get_int (value); break; + case PROP_BLOCKING: + g_socket_set_blocking (socket, g_value_get_boolean (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -118,6 +128,22 @@ g_socket_class_init (GSocketClass *klass) gobject_class->dispose = g_socket_dispose; gobject_class->set_property = g_socket_set_property; gobject_class->get_property = g_socket_get_property; + + g_object_class_install_property (gobject_class, PROP_FD, + g_param_spec_int ("fd", + "file descriptor", + "the socket's file descriptor", + G_MININT, + G_MAXINT, + -1, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); + + g_object_class_install_property (gobject_class, PROP_BLOCKING, + g_param_spec_boolean ("blocking", + "blocking", + "whether or not this socket is blocking", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); } static void @@ -145,7 +171,15 @@ g_socket_new (gint domain, gint type, gint protocol) GSocket * g_socket_new_from_fd (gint fd) { - return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, NULL)); + glong arg; + gboolean blocking; + + if ((arg = fcntl (fd, F_GETFL, NULL)) < 0) + g_warning ("Error getting socket status flags: %s", g_strerror (errno)); + + blocking = ((arg & O_NONBLOCK) != 0); + + return G_SOCKET (g_object_new (G_TYPE_SOCKET, "blocking", blocking, "fd", fd, NULL)); } void @@ -165,6 +199,22 @@ g_socket_set_blocking (GSocket *socket, g_warning ("Error setting socket status flags: %s", g_strerror (errno)); } +GSocketAddress * +g_socket_get_peer_address (GSocket *socket, + GError **error) +{ + gchar buffer[128]; + gsize len; + + if (getpeername (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get peer address"); + return NULL; + } + + return g_socket_address_from_native (buffer, len); +} + void g_socket_listen (GSocket *socket, gint backlog) @@ -199,6 +249,48 @@ g_socket_bind (GSocket *socket, } } +GSocket * +g_socket_accept (GSocket *socket, + GCancellable *cancellable, + GError **error) +{ + gint ret; + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return NULL; + + if ((ret = accept (socket->priv->fd, NULL, 0)) < 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error accepting connection"); + return NULL; + } + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + { + close (ret); + return NULL; + } + + return g_socket_new_from_fd (ret); +} + +void +g_socket_accept_async (GSocket *socket, + GCancellable *cancellable, + GAsyncReadyCallback *callback, + gpointer user_data) +{ + +} + +GSocket * +g_socket_accept_finish (GSocket *socket, + GAsyncResult *result, + GError **error) +{ + return NULL; +} + gboolean g_socket_connect (GSocket *socket, GSocketAddress *address, diff --git a/gnio/gsocket.h b/gnio/gsocket.h index 0571108..97ac900 100644 --- a/gnio/gsocket.h +++ b/gnio/gsocket.h @@ -55,83 +55,85 @@ struct _GSocketClass GObjectClass parent_class; }; -GType g_socket_get_type (void) G_GNUC_CONST; - -GSocket * g_socket_new (gint domain, gint type, gint protocol); - -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); - -gboolean g_socket_connect (GSocket *socket, - GSocketAddress *address, - GCancellable *cancellable, - GError **error); - -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); - -GSocket * g_socket_accept (GSocket *socket, - GCancellable *cancellable, - GError **error); - -void g_socket_accept_async (GSocket *socket, - GCancellable *cancellable, - GAsyncReadyCallback *callback, - gpointer user_data); - -GSocket * g_socket_accept_finish (GSocket *socket, - GAsyncResult *result, - GError **error); - -void g_socket_listen (GSocket *socket, - int backlog); - -gssize g_socket_receive (GSocket *socket, - gchar *buffer, - gsize size, - GCancellable *cancellable, - GError **error); - -void g_socket_receive_async (GSocket *socket, - gchar *buffer, - gsize size, - GCancellable *cancellable, - GAsyncReadyCallback *callback, - gpointer user_data); - -gssize g_socket_receive_finish (GSocket *socket, - GAsyncResult *result, - GError **error); - -gssize g_socket_send (GSocket *socket, - gchar *buffer, - gsize size, - GCancellable *cancellable, - GError **error); - -void g_socket_send_async (GSocket *socket, - gchar *buffer, - gsize size, - GCancellable *cancellable, - GAsyncReadyCallback *callback, - gpointer user_data); - -gssize g_socket_send_finish (GSocket *socket, - GAsyncResult *result, - GError **error); +GType g_socket_get_type (void) G_GNUC_CONST; + +GSocket * g_socket_new (gint domain, gint type, gint protocol); + +GSocket * g_socket_new_from_fd (gint fd); + +GSocketAddress * g_socket_get_peer_address (GSocket *socket, GError **error); + +void g_socket_set_blocking (GSocket *socket, + gboolean blocking); + +gboolean g_socket_bind (GSocket *socket, + GSocketAddress *address, + GError **error); + +gboolean g_socket_connect (GSocket *socket, + GSocketAddress *address, + GCancellable *cancellable, + GError **error); + +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); + +GSocket * g_socket_accept (GSocket *socket, + GCancellable *cancellable, + GError **error); + +void g_socket_accept_async (GSocket *socket, + GCancellable *cancellable, + GAsyncReadyCallback *callback, + gpointer user_data); + +GSocket * g_socket_accept_finish (GSocket *socket, + GAsyncResult *result, + GError **error); + +void g_socket_listen (GSocket *socket, + gint backlog); + +gssize g_socket_receive (GSocket *socket, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error); + +void g_socket_receive_async (GSocket *socket, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GAsyncReadyCallback *callback, + gpointer user_data); + +gssize g_socket_receive_finish (GSocket *socket, + GAsyncResult *result, + GError **error); + +gssize g_socket_send (GSocket *socket, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error); + +void g_socket_send_async (GSocket *socket, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GAsyncReadyCallback *callback, + gpointer user_data); + +gssize g_socket_send_finish (GSocket *socket, + GAsyncResult *result, + GError **error); G_END_DECLS diff --git a/gnio/gsocketaddress.c b/gnio/gsocketaddress.c index 6f362ac..cd77127 100644 --- a/gnio/gsocketaddress.c +++ b/gnio/gsocketaddress.c @@ -24,7 +24,12 @@ #include #include +#include +#include + #include "gsocketaddress.h" +#include "ginetsocketaddress.h" +#include "ginet4address.h" G_DEFINE_ABSTRACT_TYPE (GSocketAddress, g_socket_address, G_TYPE_INITIALLY_UNOWNED); @@ -55,3 +60,27 @@ g_socket_address_to_native (GSocketAddress *address, gpointer dest) return G_SOCKET_ADDRESS_GET_CLASS (address)->to_native (address, dest); } + +GSocketAddress * +g_socket_address_from_native (gpointer native, gsize len) +{ + gshort family; + + if (len < sizeof (gshort)) + return NULL; + + family = ((struct sockaddr *) native)->sa_family; + + if (family == AF_UNSPEC) + return NULL; + + if (family == AF_INET) + { + struct sockaddr_in *addr = (struct sockaddr_in *) native; + + return G_SOCKET_ADDRESS (g_inet_socket_address_new (G_INET_ADDRESS (g_inet4_address_from_bytes ((guint8 *) &(addr->sin_addr))), g_ntohs (addr->sin_port))); + } + // TODO: handle AF_INET6 and AF_UNIX + + return NULL; +} diff --git a/gnio/gsocketaddress.h b/gnio/gsocketaddress.h index a770574..d2b7db3 100644 --- a/gnio/gsocketaddress.h +++ b/gnio/gsocketaddress.h @@ -52,11 +52,13 @@ struct _GSocketAddressClass 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); +gboolean g_socket_address_to_native (GSocketAddress *address, gpointer dest); -gssize g_socket_address_native_size (GSocketAddress *address); +gssize g_socket_address_native_size (GSocketAddress *address); + +GSocketAddress * g_socket_address_from_native (gpointer native, gsize len); G_END_DECLS diff --git a/test/test-server.c b/test/test-server.c index e50326a..7507a98 100644 --- a/test/test-server.c +++ b/test/test-server.c @@ -1,13 +1,17 @@ #include #include +#include +#include #include #include +#include GMainLoop *loop; int main (int argc, char *argv[]) { - GSocket *socket; + GSocket *socket, *new_socket; + GSocketAddress *address; g_thread_init (NULL); @@ -15,11 +19,21 @@ int main (int argc, char *argv[]) loop = g_main_loop_new (NULL, FALSE); - socket = g_socket_new (); + socket = g_socket_new (AF_INET, SOCK_STREAM, 0); - g_socket_set_blocking (socket, FALSE); + g_socket_bind (socket, G_SOCKET_ADDRESS (g_inet_socket_address_new (G_INET_ADDRESS (g_inet4_address_from_string ("127.0.0.1")), 31882)), NULL); - g_main_loop_run (loop); + g_socket_listen (socket, 10); + + g_printf ("listening on port 31882...\n"); + + new_socket = g_socket_accept (socket, NULL, NULL); + + address = g_socket_get_peer_address (new_socket, NULL); + + g_printf ("got a new connection from %s:%d\n", g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address))), g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address))); + +// g_main_loop_run (loop); return 0; } -- 2.20.1