X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fgnio.git;a=blobdiff_plain;f=gnio%2Fgsocket.c;h=d92a1d0367d18c83c25d8b35a4c0e1a3987bdf50;hp=605f92b4ede8580cfedce1c51da780e47240a727;hb=a7b5dcd5941e314caa53623f6b3d53e2d2d0c7d8;hpb=48aa363fffb042f947130762acc7cd3c787b11d9 diff --git a/gnio/gsocket.c b/gnio/gsocket.c index 605f92b..d92a1d0 100644 --- a/gnio/gsocket.c +++ b/gnio/gsocket.c @@ -24,7 +24,9 @@ #include #include #include -#include +#include +#include "gasynchelper.h" +#include "gnioenumtypes.h" #include #ifndef G_OS_WIN32 @@ -51,6 +53,9 @@ G_DEFINE_TYPE (GSocket, g_socket, G_TYPE_OBJECT); enum { PROP_0, + PROP_DOMAIN, + PROP_TYPE, + PROP_PROTOCOL, PROP_FD, PROP_BLOCKING, PROP_BACKLOG, @@ -61,14 +66,109 @@ enum struct _GSocketPrivate { + GSocketDomain domain; + GSocketType type; + gchar *protocol; gint fd; gboolean blocking; gint backlog; gboolean reuse_address; + GError *error; GSocketAddress *local_address; GSocketAddress *remote_address; }; +static void +<<<<<<< HEAD:gnio/gsocket.c +g_socket_constructed (GObject *object) +{ + GSocket *sock = G_SOCKET (object); + GError *error = NULL; + static GStaticMutex getprotobyname_mutex = G_STATIC_MUTEX_INIT; + gint fd, native_domain, native_type, native_protocol; + + if (sock->priv->fd >= 0) + { + // we've been constructed from an existing file descriptor + glong arg; + gboolean blocking; + + // TODO: set the socket type with getsockopt (SO_TYPE) + // TODO: what should we do about domain and protocol? + + if ((arg = fcntl (sock->priv->fd, F_GETFL, NULL)) < 0) + g_warning ("Error getting socket status flags: %s", g_strerror (errno)); + + blocking = ((arg & O_NONBLOCK) == 0); + + return; + } + + switch (sock->priv->domain) + { + case G_SOCKET_DOMAIN_INET: + native_domain = PF_INET; + break; + + case G_SOCKET_DOMAIN_INET6: + native_domain = PF_INET6; + break; + + case G_SOCKET_DOMAIN_UNIX: + native_domain = PF_UNIX; + break; + + default: + g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket domain"); + return; + } + + switch (sock->priv->type) + { + case G_SOCKET_TYPE_STREAM: + native_type = SOCK_STREAM; + break; + + case G_SOCKET_TYPE_DATAGRAM: + native_type = SOCK_DGRAM; + break; + + case G_SOCKET_TYPE_SEQPACKET: + native_type = SOCK_SEQPACKET; + break; + + default: + g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket type"); + return; + } + + if (sock->priv->protocol == NULL) + native_protocol = 0; + else + { + struct protoent *ent; + g_static_mutex_lock (&getprotobyname_mutex); + if (!(ent = getprotobyname (sock->priv->protocol))) + { + g_static_mutex_unlock (&getprotobyname_mutex); + g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket protocol"); + return; + } + native_protocol = ent->p_proto; + g_static_mutex_unlock (&getprotobyname_mutex); + } + + fd = socket (native_domain, native_type, native_protocol); + + if (fd < 0) + { + g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (errno), "unable to create socket: %s", g_strerror (errno)); + return; + } + + sock->priv->fd = fd; +} + static void g_socket_get_property (GObject *object, guint prop_id, @@ -79,6 +179,18 @@ g_socket_get_property (GObject *object, switch (prop_id) { + case PROP_DOMAIN: + g_value_set_enum (value, socket->priv->domain); + break; + + case PROP_TYPE: + g_value_set_enum (value, socket->priv->type); + break; + + case PROP_PROTOCOL: + g_value_set_string (value, socket->priv->protocol); + break; + case PROP_FD: g_value_set_int (value, socket->priv->fd); break; @@ -118,6 +230,18 @@ g_socket_set_property (GObject *object, switch (prop_id) { + case PROP_DOMAIN: + socket->priv->domain = g_value_get_enum (value); + break; + + case PROP_TYPE: + socket->priv->type = g_value_get_enum (value); + break; + + case PROP_PROTOCOL: + socket->priv->protocol = g_value_dup_string (value); + break; + case PROP_FD: socket->priv->fd = g_value_get_int (value); break; @@ -159,6 +283,10 @@ g_socket_dispose (GObject *object) { GSocket *socket = G_SOCKET (object); + g_free (socket->priv->protocol); + + g_clear_error (&socket->priv->error); + g_socket_close (socket); if (G_OBJECT_CLASS (g_socket_parent_class)->dispose) @@ -176,9 +304,33 @@ g_socket_class_init (GSocketClass *klass) gobject_class->finalize = g_socket_finalize; gobject_class->dispose = g_socket_dispose; + gobject_class->constructed = g_socket_constructed; gobject_class->set_property = g_socket_set_property; gobject_class->get_property = g_socket_get_property; + g_object_class_install_property (gobject_class, PROP_DOMAIN, + g_param_spec_enum ("domain", + "socket domain", + "the socket's domain", + G_TYPE_SOCKET_DOMAIN, + G_SOCKET_DOMAIN_INET, + 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_TYPE, + g_param_spec_enum ("type", + "socket type", + "the socket's type", + G_TYPE_SOCKET_TYPE, + G_SOCKET_TYPE_STREAM, + 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_PROTOCOL, + g_param_spec_string ("protocol", + "socket protocol", + "the socket's protocol", + NULL, + 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_FD, g_param_spec_int ("fd", "file descriptor", @@ -234,93 +386,22 @@ g_socket_init (GSocket *socket) socket->priv->fd = -1; socket->priv->blocking = TRUE; socket->priv->backlog = 10; + socket->priv->reuse_address = FALSE; + socket->priv->error = NULL; socket->priv->remote_address = NULL; socket->priv->local_address = NULL; } GSocket * -g_socket_new (GSocketDomain domain, GSocketType type, const gchar *protocol, GError **error) +g_socket_new (GSocketDomain domain, GSocketType type, const gchar *protocol) { - static GStaticMutex getprotobyname_mutex = G_STATIC_MUTEX_INIT; - gint fd, native_domain, native_type, native_protocol; - - switch (domain) - { - case G_SOCKET_DOMAIN_INET: - native_domain = PF_INET; - break; - - case G_SOCKET_DOMAIN_INET6: - native_domain = PF_INET6; - break; - - case G_SOCKET_DOMAIN_UNIX: - native_domain = PF_UNIX; - break; - - default: - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket domain"); - return NULL; - } - - switch (type) - { - case G_SOCKET_TYPE_STREAM: - native_type = SOCK_STREAM; - break; - - case G_SOCKET_TYPE_DATAGRAM: - native_type = SOCK_DGRAM; - break; - - case G_SOCKET_TYPE_SEQPACKET: - native_type = SOCK_SEQPACKET; - break; - - default: - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket type"); - return NULL; - } - - if (protocol == NULL) - native_protocol = 0; - else - { - struct protoent *ent; - g_static_mutex_lock (&getprotobyname_mutex); - if (!(ent = getprotobyname (protocol))) - { - g_static_mutex_unlock (&getprotobyname_mutex); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket protocol"); - return NULL; - } - native_protocol = ent->p_proto; - g_static_mutex_unlock (&getprotobyname_mutex); - } - - fd = socket(native_domain, native_type, native_protocol); - - if (fd < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "unable to create socket: %s", g_strerror (errno)); - return NULL; - } - - return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, "blocking", TRUE, NULL)); + return G_SOCKET (g_object_new (G_TYPE_SOCKET, "domain", domain, "type", type, "protocol", protocol, NULL)); } GSocket * g_socket_new_from_fd (gint fd) { - 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, "fd", fd, "blocking", blocking, NULL)); + return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, NULL)); } void @@ -414,12 +495,27 @@ g_socket_get_remote_address (GSocket *socket, return (socket->priv->remote_address = g_object_ref_sink (g_socket_address_from_native (buffer, len))); } +gboolean +g_socket_has_error (GSocket *socket, + GError **error) +{ + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + + if (!socket->priv->error) + return FALSE; + + return TRUE; +} + gboolean g_socket_listen (GSocket *socket, GError **error) { g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + if (g_socket_has_error (socket, error)) + return FALSE; + if (listen (socket->priv->fd, socket->priv->backlog) < 0) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not listen: %s", g_strerror (errno)); @@ -436,6 +532,9 @@ g_socket_bind (GSocket *socket, { g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE); + if (g_socket_has_error (socket, error)) + return FALSE; + { gchar addr[256]; @@ -462,6 +561,11 @@ g_socket_accept (GSocket *socket, { gint ret; + g_return_val_if_fail (G_IS_SOCKET (socket), NULL); + + if (g_socket_has_error (socket, 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: %s", g_strerror (errno)); @@ -480,6 +584,9 @@ g_socket_connect (GSocket *socket, g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE); + if (g_socket_has_error (socket, error)) + return FALSE; + g_socket_address_to_native (address, buffer); if (connect (socket->priv->fd, (struct sockaddr *) buffer, g_socket_address_native_size (address)) < 0)