[gnio] Clean up and document GSocketControlMessage
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnio] Clean up and document GSocketControlMessage
- Date: Thu, 7 May 2009 14:59:16 -0400 (EDT)
commit 868d627f67653c5837e8ff8bf25df0c319575dd0
Author: Alexander Larsson <alexl redhat com>
Date: Thu May 7 20:53:38 2009 +0200
Clean up and document GSocketControlMessage
Move all cmsg munging to GSocket, instead passing raw ints and gpointers
to GSocketControlMessage.
Made deserialization extensible by trying the deserialize method of all
GSocketControlMessage subclasses when deserializing.
Removed gsocketcontrol-private.h and all knowledge of specific
control messages (other than type initialization) from the generic
code.
---
gio/gsocket.c | 15 +++--
gio/gsocketcontrol-private.h | 27 -------
gio/gsocketcontrolmessage.c | 158 +++++++++++++++++++++++++++++++-----------
gio/gsocketcontrolmessage.h | 44 ++++++++++--
gio/gunixfdmessage.c | 88 ++++++++++++++----------
5 files changed, 213 insertions(+), 119 deletions(-)
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 3da1218..4349e29 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -43,7 +43,6 @@
#include <gio/gcancellable.h>
#include <gio/gioenumtypes.h>
#include <gio/ginitable.h>
-#include "gsocketcontrol-private.h"
#include "gasynchelper.h"
#include "gnioerror.h"
#include "gnioenums.h"
@@ -2477,15 +2476,18 @@ g_socket_send_message (GSocket *socket,
msg.msg_controllen = 0;
for (i = 0; i < num_messages; i++)
- msg.msg_controllen += g_socket_control_message_space (messages[i]);
+ msg.msg_controllen += CMSG_SPACE (g_socket_control_message_get_size (messages[i]));
msg.msg_control = g_alloca (msg.msg_controllen);
cmsg = CMSG_FIRSTHDR (&msg);
for (i = 0; i < num_messages; i++)
{
- g_assert (cmsg != NULL);
- g_socket_control_message_serialise (messages[i], cmsg);
+ cmsg->cmsg_level = g_socket_control_message_get_level (messages[i]);
+ cmsg->cmsg_type = g_socket_control_message_get_msg_type (messages[i]);
+ cmsg->cmsg_len = CMSG_LEN (g_socket_control_message_get_size (messages[i]));
+ g_socket_control_message_serialize (messages[i],
+ CMSG_DATA (cmsg));
cmsg = CMSG_NXTHDR (&msg, cmsg);
}
g_assert (cmsg == NULL);
@@ -2783,7 +2785,10 @@ g_socket_receive_message (GSocket *socket,
{
GSocketControlMessage *message;
- message = g_socket_control_message_deserialise (cmsg);
+ message = g_socket_control_message_deserialize (cmsg->cmsg_level,
+ cmsg->cmsg_type,
+ cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg),
+ CMSG_DATA (cmsg));
if (message == NULL)
/* We've already spewed about the problem in the
deserialization code, so just continue */
diff --git a/gio/gsocketcontrol-private.h b/gio/gsocketcontrol-private.h
deleted file mode 100644
index a9b0adf..0000000
--- a/gio/gsocketcontrol-private.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright © 2009 Codethink Limited
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * See the included COPYING file for more information.
- *
- * Authors: Ryan Lortie <desrt desrt ca>
- */
-
-#ifndef _gsocketcontrol_private_h_
-#define _gsocketcontrol_private_h_
-
-#include "gsocketcontrolmessage.h"
-
-G_BEGIN_DECLS
-
-GSocketControlMessage * g_unix_fd_message_deserialise (gpointer scm_data,
- gssize scm_size);
-GSocketControlMessage * g_socket_control_message_deserialise (gpointer scm_pointer);
-
-G_END_DECLS
-
-#endif /* _gsocketcontrolmessage_h_ */
diff --git a/gio/gsocketcontrolmessage.c b/gio/gsocketcontrolmessage.c
index c5c4854..3af0029 100644
--- a/gio/gsocketcontrolmessage.c
+++ b/gio/gsocketcontrolmessage.c
@@ -28,9 +28,21 @@
*
* These messages are sent with g_socket_send_message() and received
* with g_socket_receive_message().
+ *
+ * To extend the set of control message that can be sent, subclass this
+ * class and override the get_size, get_level, get_type and serialize
+ * methods.
+ *
+ * To extend the set of control messages that can be recieved, subclass
+ * this class and implement the deserialize method. Also, make sure your
+ * class is registered with the GType typesystem before calling
+ * g_socket_recieve_message() to read such a message.
+ *
+ * Since: 2.22
**/
#include "gsocketcontrolmessage.h"
+#include "gunixfdmessage.h"
#ifndef G_OS_WIN32
#include <sys/socket.h>
@@ -43,72 +55,134 @@ G_DEFINE_ABSTRACT_TYPE (GSocketControlMessage,
g_socket_control_message,
G_TYPE_OBJECT);
+/**
+ * g_socket_control_message_get_size:
+ * @message: a #GSocketControlMessage
+ *
+ * Returns the space required for the control message, not including
+ * headers or alignment.
+ *
+ * Returns: The number of bytes required.
+ *
+ * Since: 2.22
+ **/
gsize
-g_socket_control_message_space (GSocketControlMessage *message)
+g_socket_control_message_get_size (GSocketControlMessage *message)
{
g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0);
- gsize size;
- size = G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)
- -> size (message);
-
-#ifndef G_OS_WIN32
- return CMSG_SPACE (size);
-#elif defined (WSA_CMSG_SPACE)
- return WSA_CMSG_SPACE (size);
-#else
- return size;
-#endif
+ return G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->get_size (message);
}
-static void
-g_socket_control_message_init (GSocketControlMessage *message)
+/**
+ * g_socket_control_message_get_level:
+ * @message: a #GSocketControlMessage
+ *
+ * Returns the "level" (i.e. the originating protocol) of the control message.
+ * This is often SOL_SOCKET.
+ *
+ * Returns: and int describing the level
+ *
+ * Since: 2.22
+ **/
+int
+g_socket_control_message_get_level (GSocketControlMessage *message)
{
+ g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0);
+
+ return G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->get_level (message);
}
-static void
-g_socket_control_message_class_init (GSocketControlMessageClass *class)
+/**
+ * g_socket_control_message_get_msg_type:
+ * @message: a #GSocketControlMessage
+ *
+ * Returns the protocol specify type of the control message.
+ * For instance, for unix fd passing this would be SCM_RIGHTS.
+ *
+ * Returns: and int describing the level
+ *
+ * Since: 2.22
+ **/
+int
+g_socket_control_message_get_msg_type (GSocketControlMessage *message)
{
-}
+ g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0);
-#include "gsocketcontrol-private.h"
+ return G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->get_type (message);
+}
+/**
+ * g_socket_control_message_serialize:
+ * @message: a #GSocketControlMessage
+ * @data: A buffer to write data to
+ *
+ * Converts the data in the message to bytes placed in the
+ * message.
+ *
+ * @data is guaranteed to have enough space to fit the size
+ * returned by g_socket_control_message_get_size() on this
+ * object.
+ *
+ * Since: 2.22
+ **/
void
-g_socket_control_message_serialise (GSocketControlMessage *message,
- gpointer scm_pointer)
+g_socket_control_message_serialize (GSocketControlMessage *message,
+ gpointer data)
{
g_return_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message));
- G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)
- -> serialise (message, scm_pointer);
+ return G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->serialize (message, data);
+}
+
+
+static void
+g_socket_control_message_init (GSocketControlMessage *message)
+{
}
+static void
+g_socket_control_message_class_init (GSocketControlMessageClass *class)
+{
+}
GSocketControlMessage *
-g_socket_control_message_deserialise (gpointer scm_pointer)
+g_socket_control_message_deserialize (int level,
+ int type,
+ gsize size,
+ gpointer data)
{
-#ifndef G_OS_WIN32
- struct cmsghdr *cmsg = scm_pointer;
- gpointer data;
- gssize size;
+ GSocketControlMessageClass *klass;
+ GSocketControlMessage *message;
+ volatile GType a_type;
+ GType *message_types;
+ guint n_message_types;
+ int i;
+
+ /* Ensure we know about the built in types */
+ a_type = g_unix_fd_message_get_type ();
- size = cmsg->cmsg_len - CMSG_LEN (0);
- data = CMSG_DATA (cmsg);
+ message_types = g_type_children (G_TYPE_SOCKET_CONTROL_MESSAGE, &n_message_types);
- switch (cmsg->cmsg_level)
+ message = NULL;
+ for (i = 0; i < n_message_types; i++)
{
- case SOL_SOCKET:
- switch (cmsg->cmsg_type)
- {
- case SCM_RIGHTS:
- return g_unix_fd_message_deserialise (data, size);
- }
+ klass = (GSocketControlMessageClass *)g_type_class_ref (type);
+
+ if (klass && klass->deserialize)
+ {
+ message = klass->deserialize (level, type, size, data);
+ g_type_class_unref ((GTypeClass *) klass);
+ }
+
+ if (message != NULL)
+ break;
}
- g_warning ("unknown control message type %d:%d",
- cmsg->cmsg_level, cmsg->cmsg_type);
-#else
- g_warning ("socket control messages not supported on windows");
-#endif
- return NULL;
+ g_free (message_types);
+
+ if (message == NULL)
+ g_warning ("unknown control message type %d:%d", level, type);
+
+ return message;
}
diff --git a/gio/gsocketcontrolmessage.h b/gio/gsocketcontrolmessage.h
index 1e5cbb9..0a6af86 100644
--- a/gio/gsocketcontrolmessage.h
+++ b/gio/gsocketcontrolmessage.h
@@ -33,17 +33,38 @@ G_BEGIN_DECLS
G_TYPE_SOCKET_CONTROL_MESSAGE, \
GSocketControlMessageClass))
+/**
+ * GSocketControlMessage:
+ *
+ * Base class for socket-type specific control messages that can be sent and
+ * recieved over #GSocket.
+ **/
+typedef struct _GSocketControlMessage GSocketControlMessage;
typedef struct _GSocketControlMessagePrivate GSocketControlMessagePrivate;
typedef struct _GSocketControlMessageClass GSocketControlMessageClass;
-typedef struct _GSocketControlMessage GSocketControlMessage;
+
+/**
+ * GSocketControlMessageClass:
+ * @get_size: gets the size of the message.
+ * @get_level: gets the protocol of the message.
+ * @get_type: gets the protocol specific type of the message.
+ * @serialize: Writes out the message data.
+ * @deserialize: Tries to deserialize a message.
+ **/
struct _GSocketControlMessageClass
{
GObjectClass parent_class;
- gsize (* size) (GSocketControlMessage *message);
- void (* serialise) (GSocketControlMessage *message,
- gpointer scm_pointer);
+ gsize (* get_size) (GSocketControlMessage *message);
+ int (* get_level) (GSocketControlMessage *message);
+ int (* get_type) (GSocketControlMessage *message);
+ void (* serialize) (GSocketControlMessage *message,
+ gpointer data);
+ GSocketControlMessage *(* deserialize) (int level,
+ int type,
+ gsize size,
+ gpointer data);
};
struct _GSocketControlMessage
@@ -52,10 +73,17 @@ struct _GSocketControlMessage
GSocketControlMessagePrivate *priv;
};
-GType g_socket_control_message_get_type (void);
-gsize g_socket_control_message_space (GSocketControlMessage *message);
-void g_socket_control_message_serialise (GSocketControlMessage *message,
- gpointer scm_pointer);
+GType g_socket_control_message_get_type (void);
+gsize g_socket_control_message_get_size (GSocketControlMessage *message);
+int g_socket_control_message_get_level (GSocketControlMessage *message);
+int g_socket_control_message_get_msg_type (GSocketControlMessage *message);
+void g_socket_control_message_serialize (GSocketControlMessage *message,
+ gpointer data);
+GSocketControlMessage *g_socket_control_message_deserialize (int level,
+ int type,
+ gsize size,
+ gpointer data);
+
G_END_DECLS
diff --git a/gio/gunixfdmessage.c b/gio/gunixfdmessage.c
index 7a74372..04174f8 100644
--- a/gio/gunixfdmessage.c
+++ b/gio/gunixfdmessage.c
@@ -46,28 +46,61 @@ struct _GUnixFDMessagePrivate
gint nfd;
};
-static void
-g_unix_fd_message_serialise (GSocketControlMessage *message,
- gpointer scm_pointer)
+static gsize
+g_unix_fd_message_get_size (GSocketControlMessage *message)
{
GUnixFDMessage *fd_message = G_UNIX_FD_MESSAGE (message);
- struct cmsghdr *cmsg = scm_pointer;
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN (sizeof (gint) * fd_message->priv->nfd);
- memcpy (CMSG_DATA (cmsg), fd_message->priv->fds,
- sizeof (gint) * fd_message->priv->nfd);
+ return fd_message->priv->nfd * sizeof (gint);
}
-static gsize
-g_unix_fd_message_size (GSocketControlMessage *message)
+static int
+g_unix_fd_message_get_level (GSocketControlMessage *message)
{
- GUnixFDMessage *fd_message = G_UNIX_FD_MESSAGE (message);
+ return SOL_SOCKET;
+}
- return fd_message->priv->nfd * sizeof (gint);
+static int
+g_unix_fd_message_get_msg_type (GSocketControlMessage *message)
+{
+ return SCM_RIGHTS;
}
+static GSocketControlMessage *
+g_unix_fd_message_deserialize (int level,
+ int type,
+ gsize size,
+ gpointer data)
+{
+ GUnixFDMessage *message;
+
+ if (level != SOL_SOCKET ||
+ level != SCM_RIGHTS)
+ return NULL;
+
+ if (size % 4 > 0)
+ {
+ g_warning ("Kernel returned non-integral number of fds");
+ return NULL;
+ }
+
+ message = g_object_new (G_TYPE_UNIX_FD_MESSAGE, NULL);
+ message->priv->nfd = size / sizeof (gint);
+ message->priv->fds = g_new (gint, message->priv->nfd + 1);
+ memcpy (message->priv->fds, data, size);
+ message->priv->fds[message->priv->nfd] = -1;
+
+ return G_SOCKET_CONTROL_MESSAGE (message);
+}
+
+static void
+g_unix_fd_message_serialize (GSocketControlMessage *message,
+ gpointer data)
+{
+ GUnixFDMessage *fd_message = G_UNIX_FD_MESSAGE (message);
+ memcpy (data, fd_message->priv->fds,
+ sizeof (gint) * fd_message->priv->nfd);
+}
static void
g_unix_fd_message_init (GUnixFDMessage *message)
{
@@ -97,8 +130,11 @@ g_unix_fd_message_class_init (GUnixFDMessageClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (GUnixFDMessagePrivate));
- scm_class->size = g_unix_fd_message_size;
- scm_class->serialise = g_unix_fd_message_serialise;
+ scm_class->get_size = g_unix_fd_message_get_size;
+ scm_class->get_level = g_unix_fd_message_get_level;
+ scm_class->get_type = g_unix_fd_message_get_msg_type;
+ scm_class->serialize = g_unix_fd_message_serialize;
+ scm_class->deserialize = g_unix_fd_message_deserialize;
object_class->finalize = g_unix_fd_message_finalize;
}
@@ -214,25 +250,3 @@ g_unix_fd_message_append_fd (GUnixFDMessage *message,
return TRUE;
}
-#include "gsocketcontrol-private.h"
-
-GSocketControlMessage *
-g_unix_fd_message_deserialise (gpointer scm_data,
- gssize scm_size)
-{
- GUnixFDMessage *message;
-
- if (scm_size % 4 > 0)
- {
- g_warning ("Kernel returned non-integral number of fds");
- return NULL;
- }
-
- message = g_object_new (G_TYPE_UNIX_FD_MESSAGE, NULL);
- message->priv->nfd = scm_size / sizeof (gint);
- message->priv->fds = g_new (gint, message->priv->nfd + 1);
- memcpy (message->priv->fds, scm_data, scm_size);
- message->priv->fds[message->priv->nfd] = -1;
-
- return G_SOCKET_CONTROL_MESSAGE (message);
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]