[gnio] Add keepalive property to GSocket
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnio] Add keepalive property to GSocket
- Date: Tue, 28 Apr 2009 06:09:33 -0400 (EDT)
commit f80d5b6ae57efaaa8435e3aa59514a3f8f2db293
Author: Alexander Larsson <alexl redhat com>
Date: Tue Apr 28 11:59:59 2009 +0200
Add keepalive property to GSocket
---
gio/gsocket.c | 131 +++++++++++++++++++++++++++++++++++++++++++--------------
gio/gsocket.h | 3 +
2 files changed, 102 insertions(+), 32 deletions(-)
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 8942ac7..ca40bb6 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -57,6 +57,7 @@ enum
PROP_BLOCKING,
PROP_LISTEN_BACKLOG,
PROP_REUSE_ADDRESS,
+ PROP_KEEPALIVE,
PROP_LOCAL_ADDRESS,
PROP_REMOTE_ADDRESS
};
@@ -69,6 +70,7 @@ struct _GSocketPrivate
gboolean blocking;
gint listen_backlog;
gboolean reuse_address;
+ gboolean keepalive;
GError *construct_error;
GSocketAddress *local_address;
GSocketAddress *remote_address;
@@ -100,18 +102,17 @@ g_socket_details_from_fd (GSocket *socket)
{
#ifndef G_OS_WIN32
struct sockaddr_storage address;
- gint fd, result;
+ gint fd;
guint addrlen;
guint optlen;
- gint value;
+ int value, result;
+ int errsv;
fd = socket->priv->fd;
optlen = sizeof value;
- result = getsockopt (fd, SOL_SOCKET, SO_TYPE, &value, &optlen);
-
- if G_UNLIKELY (result < 0)
+ if (getsockopt (fd, SOL_SOCKET, SO_TYPE, &value, &optlen) != 0)
{
- gint errsv = errno;
+ errsv = errno;
switch (errsv)
{
@@ -120,15 +121,11 @@ g_socket_details_from_fd (GSocket *socket)
/* programmer error */
g_error ("creating GSocket from fd %d: %s\n",
fd, g_strerror (errsv));
-
default:
- g_set_error (&socket->priv->construct_error, G_IO_ERROR,
- g_io_error_from_errno (errsv),
- "creating GSocket from fd: %s",
- g_strerror (errsv));
+ break;
}
- return;
+ goto err;
}
g_assert (optlen == sizeof value);
@@ -152,18 +149,10 @@ g_socket_details_from_fd (GSocket *socket)
}
addrlen = sizeof address;
- result = getsockname (fd, (struct sockaddr *) &address, &addrlen);
-
- if G_UNLIKELY (result < 0)
+ if (getsockname (fd, (struct sockaddr *) &address, &addrlen) != 0)
{
- gint errsv = errno;
-
- g_set_error (&socket->priv->construct_error, G_IO_ERROR,
- g_io_error_from_errno (errsv),
- "creating GSocket from fd: %s",
- g_strerror (errsv));
-
- return;
+ errsv = errno;
+ goto err;
}
g_assert (G_STRUCT_OFFSET (struct sockaddr, sa_family) +
@@ -192,25 +181,55 @@ g_socket_details_from_fd (GSocket *socket)
g_socket_address_new_from_native (&address, addrlen);
}
-
result = fcntl (fd, F_GETFL, NULL);
-
- if G_UNLIKELY (result < 0)
+ if (result == -1)
{
- gint errsv = errno;
+ errsv = errno;
+ goto err;
+ }
+ socket->priv->blocking = !(result & O_NONBLOCK);
- g_error ("fcntl failed while constructing a GSocket from fd (%s). "
- "This is really quite unexpected. Please file a bug.",
- g_strerror (errsv));
+ optlen = sizeof value;
+ if (getsockopt (fd, SOL_SOCKET, SO_KEEPALIVE,
+ &value, &optlen) == 0)
+ {
+ g_assert (optlen == sizeof value);
+ socket->priv->keepalive = !!value;
+ }
+ else
+ {
+ /* Can't read, maybe not supported, assume FALSE */
+ socket->priv->keepalive = FALSE;
}
- socket->priv->blocking = !(result & O_NONBLOCK);
+ optlen = sizeof value;
+ if (getsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
+ &value, &optlen) == 0)
+ {
+ g_assert (optlen == sizeof value);
+ socket->priv->reuse_address = !!value;
+ }
+ else
+ {
+ /* Can't read, maybe not supported, assume FALSE */
+ socket->priv->reuse_address = FALSE;
+ }
#else /* windows */
socket->type = G_SOCKET_TYPE_INVALID;
socket->family = G_SOCKET_DOMAIN_INVALID;
socket->blocking = FALSE;
+ socket->keepalive = FALSE;
+ socket->reuse_address = FALSE;
#endif
+
+ return;
+
+ err:
+ g_set_error (&socket->priv->construct_error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ "creating GSocket from fd: %s",
+ g_strerror (errsv));
}
static gint
@@ -302,6 +321,10 @@ g_socket_get_property (GObject *object,
g_value_set_boolean (value, socket->priv->reuse_address);
break;
+ case PROP_KEEPALIVE:
+ g_value_set_boolean (value, socket->priv->keepalive);
+ break;
+
case PROP_LOCAL_ADDRESS:
g_value_set_object (value, socket->priv->local_address);
break;
@@ -349,6 +372,10 @@ g_socket_set_property (GObject *object,
g_socket_set_reuse_address (socket, g_value_get_boolean (value));
break;
+ case PROP_KEEPALIVE:
+ g_socket_set_keepalive (socket, g_value_get_boolean (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -454,6 +481,13 @@ g_socket_class_init (GSocketClass *klass)
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
+ g_object_class_install_property (gobject_class, PROP_KEEPALIVE,
+ g_param_spec_boolean ("keepalive",
+ "keep connection alive",
+ "keep connection alive by sending periodic pings",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
+
g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS,
g_param_spec_object ("local-address",
"local address",
@@ -548,7 +582,7 @@ void
g_socket_set_reuse_address (GSocket *socket,
gboolean reuse)
{
- gint value = (gint) reuse;
+ int value;
g_return_if_fail (G_IS_SOCKET (socket));
@@ -556,6 +590,7 @@ g_socket_set_reuse_address (GSocket *socket,
if (socket->priv->reuse_address == reuse)
return;
+ value = (int) reuse;
if (setsockopt (socket->priv->fd, SOL_SOCKET, SO_REUSEADDR,
(gpointer) &value, sizeof (value)) < 0)
{
@@ -575,6 +610,38 @@ g_socket_get_reuse_address (GSocket *socket)
return socket->priv->reuse_address;
}
+void
+g_socket_set_keepalive (GSocket *socket,
+ gboolean keepalive)
+{
+ int value;
+
+ g_return_if_fail (G_IS_SOCKET (socket));
+
+ keepalive = !!keepalive;
+ if (socket->priv->keepalive == keepalive)
+ return;
+
+ value = (gint) keepalive;
+ if (setsockopt (socket->priv->fd, SOL_SOCKET, SO_KEEPALIVE,
+ (gpointer) &value, sizeof (value)) < 0)
+ {
+ g_warning ("error setting keepalive: %s", g_strerror (errno));
+ return;
+ }
+
+ socket->priv->keepalive = keepalive;
+ g_object_notify (G_OBJECT (socket), "keepalive");
+}
+
+gboolean
+g_socket_get_keepalive (GSocket *socket)
+{
+ g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
+
+ return socket->priv->keepalive;
+}
+
gint
g_socket_get_listen_backlog (GSocket *socket)
{
diff --git a/gio/gsocket.h b/gio/gsocket.h
index 0a87590..cdb9697 100644
--- a/gio/gsocket.h
+++ b/gio/gsocket.h
@@ -88,6 +88,9 @@ gboolean g_socket_get_blocking (GSocket
void g_socket_set_reuse_address (GSocket *socket,
gboolean reuse);
gboolean g_socket_get_reuse_address (GSocket *socket);
+void g_socket_set_keepalive (GSocket *socket,
+ gboolean keepalive);
+gboolean g_socket_get_keepalive (GSocket *socket);
gint g_socket_get_listen_backlog (GSocket *socket);
void g_socket_set_listen_backlog (GSocket *socket,
gint backlog);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]