[glib] gsocket: Split out functions to convert to and from struct msghdr
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] gsocket: Split out functions to convert to and from struct msghdr
- Date: Thu, 1 Oct 2015 13:17:02 +0000 (UTC)
commit 5d6894746635d19d719fbf15881dbd7fc375d77c
Author: Philip Withnall <philip withnall collabora co uk>
Date: Fri Jun 12 08:30:20 2015 +0100
gsocket: Split out functions to convert to and from struct msghdr
As new methods are added to GSocket, we don’t want to duplicate this
code, so factor it out.
https://bugzilla.gnome.org/show_bug.cgi?id=751924
gio/gsocket.c | 522 ++++++++++++++++++++++++++++-----------------------------
1 files changed, 257 insertions(+), 265 deletions(-)
---
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 807a423..7a87690 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -135,6 +135,9 @@ static gboolean g_socket_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error);
+static GSocketAddress *
+cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len);
+
static gint
g_socket_send_messages_with_blocking (GSocket *socket,
GOutputMessage *messages,
@@ -3699,6 +3702,227 @@ g_socket_condition_timed_wait (GSocket *socket,
#endif
}
+/* Unfortunately these have to be macros rather than inline functions due to
+ * using alloca(). */
+#define output_message_to_msghdr(message, prev_message, msg, prev_msg, error) \
+G_STMT_START { \
+ const GOutputMessage *_message = (message); \
+ const GOutputMessage *_prev_message = (prev_message); \
+ struct msghdr *_msg = (msg); \
+ const struct msghdr *_prev_msg = (prev_msg); \
+ GError **_error = (error); \
+ \
+ _msg->msg_flags = 0; \
+ \
+ /* name */ \
+ if (_prev_message != NULL && _prev_message->address == _message->address) \
+ { \
+ _msg->msg_name = _prev_msg->msg_name; \
+ _msg->msg_namelen = _prev_msg->msg_namelen; \
+ } \
+ else if (_message->address != NULL) \
+ { \
+ _msg->msg_namelen = g_socket_address_get_native_size (_message->address); \
+ _msg->msg_name = g_alloca (_msg->msg_namelen); \
+ if (!g_socket_address_to_native (_message->address, _msg->msg_name, \
+ _msg->msg_namelen, _error)) \
+ break; \
+ } \
+ else \
+ { \
+ _msg->msg_name = NULL; \
+ _msg->msg_namelen = 0; \
+ } \
+ \
+ /* iov */ \
+ { \
+ /* this entire expression will be evaluated at compile time */ \
+ if (sizeof *_msg->msg_iov == sizeof *_message->vectors && \
+ sizeof _msg->msg_iov->iov_base == sizeof _message->vectors->buffer && \
+ G_STRUCT_OFFSET (struct iovec, iov_base) == \
+ G_STRUCT_OFFSET (GOutputVector, buffer) && \
+ sizeof _msg->msg_iov->iov_len == sizeof _message->vectors->size && \
+ G_STRUCT_OFFSET (struct iovec, iov_len) == \
+ G_STRUCT_OFFSET (GOutputVector, size)) \
+ /* ABI is compatible */ \
+ { \
+ _msg->msg_iov = (struct iovec *) _message->vectors; \
+ _msg->msg_iovlen = _message->num_vectors; \
+ } \
+ else \
+ /* ABI is incompatible */ \
+ { \
+ gint i; \
+ \
+ _msg->msg_iov = g_newa (struct iovec, _message->num_vectors); \
+ for (i = 0; i < _message->num_vectors; i++) \
+ { \
+ _msg->msg_iov[i].iov_base = (void *) _message->vectors[i].buffer; \
+ _msg->msg_iov[i].iov_len = _message->vectors[i].size; \
+ } \
+ _msg->msg_iovlen = _message->num_vectors; \
+ } \
+ } \
+ \
+ /* control */ \
+ { \
+ struct cmsghdr *cmsg; \
+ gint i; \
+ \
+ _msg->msg_controllen = 0; \
+ for (i = 0; i < _message->num_control_messages; i++) \
+ _msg->msg_controllen += CMSG_SPACE (g_socket_control_message_get_size
(_message->control_messages[i])); \
+ \
+ if (_msg->msg_controllen == 0) \
+ _msg->msg_control = NULL; \
+ else \
+ { \
+ _msg->msg_control = g_alloca (_msg->msg_controllen); \
+ memset (_msg->msg_control, '\0', _msg->msg_controllen); \
+ } \
+ \
+ cmsg = CMSG_FIRSTHDR (_msg); \
+ for (i = 0; i < _message->num_control_messages; i++) \
+ { \
+ cmsg->cmsg_level = g_socket_control_message_get_level (_message->control_messages[i]); \
+ cmsg->cmsg_type = g_socket_control_message_get_msg_type (_message->control_messages[i]); \
+ cmsg->cmsg_len = CMSG_LEN (g_socket_control_message_get_size (_message->control_messages[i])); \
+ g_socket_control_message_serialize (_message->control_messages[i], \
+ CMSG_DATA (cmsg)); \
+ cmsg = CMSG_NXTHDR (_msg, cmsg); \
+ } \
+ g_assert (cmsg == NULL); \
+ } \
+} G_STMT_END
+
+#define input_message_to_msghdr(message, msg) \
+G_STMT_START { \
+ const GInputMessage *_message = (message); \
+ struct msghdr *_msg = (msg); \
+ \
+ /* name */ \
+ if (_message->address) \
+ { \
+ _msg->msg_namelen = sizeof (struct sockaddr_storage); \
+ _msg->msg_name = g_alloca (_msg->msg_namelen); \
+ } \
+ else \
+ { \
+ _msg->msg_name = NULL; \
+ _msg->msg_namelen = 0; \
+ } \
+ \
+ /* iov */ \
+ /* this entire expression will be evaluated at compile time */ \
+ if (sizeof *_msg->msg_iov == sizeof *_message->vectors && \
+ sizeof _msg->msg_iov->iov_base == sizeof _message->vectors->buffer && \
+ G_STRUCT_OFFSET (struct iovec, iov_base) == \
+ G_STRUCT_OFFSET (GInputVector, buffer) && \
+ sizeof _msg->msg_iov->iov_len == sizeof _message->vectors->size && \
+ G_STRUCT_OFFSET (struct iovec, iov_len) == \
+ G_STRUCT_OFFSET (GInputVector, size)) \
+ /* ABI is compatible */ \
+ { \
+ _msg->msg_iov = (struct iovec *) _message->vectors; \
+ _msg->msg_iovlen = _message->num_vectors; \
+ } \
+ else \
+ /* ABI is incompatible */ \
+ { \
+ guint i; \
+ \
+ _msg->msg_iov = g_newa (struct iovec, _message->num_vectors); \
+ for (i = 0; i < _message->num_vectors; i++) \
+ { \
+ _msg->msg_iov[i].iov_base = _message->vectors[i].buffer; \
+ _msg->msg_iov[i].iov_len = _message->vectors[i].size; \
+ } \
+ _msg->msg_iovlen = _message->num_vectors; \
+ } \
+ \
+ /* control */ \
+ _msg->msg_controllen = 2048; \
+ _msg->msg_control = g_alloca (_msg->msg_controllen); \
+ \
+ /* flags */ \
+ _msg->msg_flags = _message->flags; \
+} G_STMT_END
+
+static void
+input_message_from_msghdr (const struct msghdr *msg,
+ GInputMessage *message,
+ GSocket *socket)
+{
+ /* decode address */
+ if (message->address != NULL)
+ {
+ *message->address = cache_recv_address (socket, msg->msg_name,
+ msg->msg_namelen);
+ }
+
+ /* decode control messages */
+ {
+ GPtrArray *my_messages = NULL;
+ struct cmsghdr *cmsg;
+
+ if (msg->msg_controllen >= sizeof (struct cmsghdr))
+ {
+ for (cmsg = CMSG_FIRSTHDR (msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg))
+ {
+ GSocketControlMessage *control_message;
+
+ control_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 (control_message == NULL)
+ /* We've already spewed about the problem in the
+ deserialization code, so just continue */
+ continue;
+
+ if (message->control_messages == NULL)
+ {
+ /* we have to do it this way if the user ignores the
+ * messages so that we will close any received fds.
+ */
+ g_object_unref (control_message);
+ }
+ else
+ {
+ if (my_messages == NULL)
+ my_messages = g_ptr_array_new ();
+ g_ptr_array_add (my_messages, control_message);
+ }
+ }
+ }
+
+ if (message->num_control_messages)
+ *message->num_control_messages = my_messages != NULL ? my_messages->len : 0;
+
+ if (message->control_messages)
+ {
+ if (my_messages == NULL)
+ {
+ *message->control_messages = NULL;
+ }
+ else
+ {
+ g_ptr_array_add (my_messages, NULL);
+ *message->control_messages = (GSocketControlMessage **) g_ptr_array_free (my_messages, FALSE);
+ }
+ }
+ else
+ {
+ g_assert (my_messages == NULL);
+ }
+ }
+
+ /* capture the flags */
+ message->flags = msg->msg_flags;
+}
+
/**
* g_socket_send_message:
* @socket: a #GSocket
@@ -3813,85 +4037,26 @@ g_socket_send_message (GSocket *socket,
#ifndef G_OS_WIN32
{
+ GOutputMessage output_message;
struct msghdr msg;
gssize result;
+ GError *child_error = NULL;
- msg.msg_flags = 0;
+ output_message.address = address;
+ output_message.vectors = vectors;
+ output_message.num_vectors = num_vectors;
+ output_message.bytes_sent = 0;
+ output_message.control_messages = messages;
+ output_message.num_control_messages = num_messages;
- /* name */
- if (address)
- {
- msg.msg_namelen = g_socket_address_get_native_size (address);
- msg.msg_name = g_alloca (msg.msg_namelen);
- if (!g_socket_address_to_native (address, msg.msg_name, msg.msg_namelen, error))
- return -1;
- }
- else
+ output_message_to_msghdr (&output_message, NULL, &msg, NULL, &child_error);
+
+ if (child_error != NULL)
{
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
+ g_propagate_error (error, child_error);
+ return -1;
}
- /* iov */
- {
- /* this entire expression will be evaluated at compile time */
- if (sizeof *msg.msg_iov == sizeof *vectors &&
- sizeof msg.msg_iov->iov_base == sizeof vectors->buffer &&
- G_STRUCT_OFFSET (struct iovec, iov_base) ==
- G_STRUCT_OFFSET (GOutputVector, buffer) &&
- sizeof msg.msg_iov->iov_len == sizeof vectors->size &&
- G_STRUCT_OFFSET (struct iovec, iov_len) ==
- G_STRUCT_OFFSET (GOutputVector, size))
- /* ABI is compatible */
- {
- msg.msg_iov = (struct iovec *) vectors;
- msg.msg_iovlen = num_vectors;
- }
- else
- /* ABI is incompatible */
- {
- gint i;
-
- msg.msg_iov = g_newa (struct iovec, num_vectors);
- for (i = 0; i < num_vectors; i++)
- {
- msg.msg_iov[i].iov_base = (void *) vectors[i].buffer;
- msg.msg_iov[i].iov_len = vectors[i].size;
- }
- msg.msg_iovlen = num_vectors;
- }
- }
-
- /* control */
- {
- struct cmsghdr *cmsg;
- gint i;
-
- msg.msg_controllen = 0;
- for (i = 0; i < num_messages; i++)
- msg.msg_controllen += CMSG_SPACE (g_socket_control_message_get_size (messages[i]));
-
- if (msg.msg_controllen == 0)
- msg.msg_control = NULL;
- else
- {
- msg.msg_control = g_alloca (msg.msg_controllen);
- memset (msg.msg_control, '\0', msg.msg_controllen);
- }
-
- cmsg = CMSG_FIRSTHDR (&msg);
- for (i = 0; i < num_messages; i++)
- {
- 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);
- }
-
while (1)
{
result = sendmsg (socket->priv->fd, &msg, flags | G_SOCKET_DEFAULT_SEND_FLAGS);
@@ -4112,90 +4277,19 @@ g_socket_send_messages_with_blocking (GSocket *socket,
{
GOutputMessage *msg = &messages[i];
struct msghdr *msg_hdr = &msgvec[i].msg_hdr;
+ GError *child_error = NULL;
msgvec[i].msg_len = 0;
- msg_hdr->msg_flags = 0;
+ output_message_to_msghdr (msg, (i > 0) ? &messages[i - 1] : NULL,
+ msg_hdr, (i > 0) ? &msgvec[i - 1].msg_hdr : NULL,
+ &child_error);
- /* name */
- if (i > 0 && msg->address == messages[i-1].address)
+ if (child_error != NULL)
{
- msg_hdr->msg_name = msgvec[i-1].msg_hdr.msg_name;
- msg_hdr->msg_namelen = msgvec[i-1].msg_hdr.msg_namelen;
+ g_propagate_error (error, child_error);
+ return -1;
}
- else if (msg->address)
- {
- msg_hdr->msg_namelen = g_socket_address_get_native_size (msg->address);
- msg_hdr->msg_name = g_alloca (msg_hdr->msg_namelen);
- if (!g_socket_address_to_native (msg->address, msg_hdr->msg_name, msg_hdr->msg_namelen, error))
- return -1;
- }
- else
- {
- msg_hdr->msg_name = NULL;
- msg_hdr->msg_namelen = 0;
- }
-
- /* iov */
- {
- /* this entire expression will be evaluated at compile time */
- if (sizeof (struct iovec) == sizeof (GOutputVector) &&
- sizeof msg_hdr->msg_iov->iov_base == sizeof msg->vectors->buffer &&
- G_STRUCT_OFFSET (struct iovec, iov_base) ==
- G_STRUCT_OFFSET (GOutputVector, buffer) &&
- sizeof msg_hdr->msg_iov->iov_len == sizeof msg->vectors->size &&
- G_STRUCT_OFFSET (struct iovec, iov_len) ==
- G_STRUCT_OFFSET (GOutputVector, size))
- /* ABI is compatible */
- {
- msg_hdr->msg_iov = (struct iovec *) msg->vectors;
- msg_hdr->msg_iovlen = msg->num_vectors;
- }
- else
- /* ABI is incompatible */
- {
- gint j;
-
- msg_hdr->msg_iov = g_newa (struct iovec, msg->num_vectors);
- for (j = 0; j < msg->num_vectors; j++)
- {
- msg_hdr->msg_iov[j].iov_base = (void *) msg->vectors[j].buffer;
- msg_hdr->msg_iov[j].iov_len = msg->vectors[j].size;
- }
- msg_hdr->msg_iovlen = msg->num_vectors;
- }
- }
-
- /* control */
- {
- struct cmsghdr *cmsg;
- gint j;
-
- msg_hdr->msg_controllen = 0;
- for (j = 0; j < msg->num_control_messages; j++)
- msg_hdr->msg_controllen += CMSG_SPACE (g_socket_control_message_get_size
(msg->control_messages[j]));
-
- if (msg_hdr->msg_controllen == 0)
- msg_hdr->msg_control = NULL;
- else
- {
- msg_hdr->msg_control = g_alloca (msg_hdr->msg_controllen);
- memset (msg_hdr->msg_control, '\0', msg_hdr->msg_controllen);
- }
-
- cmsg = CMSG_FIRSTHDR (msg_hdr);
- for (j = 0; j < msg->num_control_messages; j++)
- {
- GSocketControlMessage *cm = msg->control_messages[j];
-
- cmsg->cmsg_level = g_socket_control_message_get_level (cm);
- cmsg->cmsg_type = g_socket_control_message_get_msg_type (cm);
- cmsg->cmsg_len = CMSG_LEN (g_socket_control_message_get_size (cm));
- g_socket_control_message_serialize (cm, CMSG_DATA (cmsg));
- cmsg = CMSG_NXTHDR (msg_hdr, cmsg);
- }
- g_assert (cmsg == NULL);
- }
}
num_sent = result = 0;
@@ -4469,68 +4563,28 @@ g_socket_receive_message (GSocket *socket,
#ifndef G_OS_WIN32
{
+ GInputMessage input_message;
struct msghdr msg;
gssize result;
- struct sockaddr_storage one_sockaddr;
-
- /* name */
- if (address)
- {
- msg.msg_name = &one_sockaddr;
- msg.msg_namelen = sizeof (struct sockaddr_storage);
- }
- else
- {
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- }
-
- /* iov */
- /* this entire expression will be evaluated at compile time */
- if (sizeof *msg.msg_iov == sizeof *vectors &&
- sizeof msg.msg_iov->iov_base == sizeof vectors->buffer &&
- G_STRUCT_OFFSET (struct iovec, iov_base) ==
- G_STRUCT_OFFSET (GInputVector, buffer) &&
- sizeof msg.msg_iov->iov_len == sizeof vectors->size &&
- G_STRUCT_OFFSET (struct iovec, iov_len) ==
- G_STRUCT_OFFSET (GInputVector, size))
- /* ABI is compatible */
- {
- msg.msg_iov = (struct iovec *) vectors;
- msg.msg_iovlen = num_vectors;
- }
- else
- /* ABI is incompatible */
- {
- gint i;
-
- msg.msg_iov = g_newa (struct iovec, num_vectors);
- for (i = 0; i < num_vectors; i++)
- {
- msg.msg_iov[i].iov_base = vectors[i].buffer;
- msg.msg_iov[i].iov_len = vectors[i].size;
- }
- msg.msg_iovlen = num_vectors;
- }
- /* control */
- msg.msg_control = g_alloca (2048);
- msg.msg_controllen = 2048;
-
- /* flags */
- if (flags != NULL)
- msg.msg_flags = *flags;
- else
- msg.msg_flags = 0;
+ input_message.address = address;
+ input_message.vectors = vectors;
+ input_message.num_vectors = num_vectors;
+ input_message.bytes_received = 0;
+ input_message.flags = (flags != NULL) ? *flags : 0;
+ input_message.control_messages = messages;
+ input_message.num_control_messages = (guint *) num_messages;
/* We always set the close-on-exec flag so we don't leak file
* descriptors into child processes. Note that gunixfdmessage.c
* will later call fcntl (fd, FD_CLOEXEC), but that isn't atomic.
*/
#ifdef MSG_CMSG_CLOEXEC
- msg.msg_flags |= MSG_CMSG_CLOEXEC;
+ input_message.flags |= MSG_CMSG_CLOEXEC;
#endif
+ input_message_to_msghdr (&input_message, &msg);
+
/* do it */
while (1)
{
@@ -4568,72 +4622,10 @@ g_socket_receive_message (GSocket *socket,
break;
}
- /* decode address */
- if (address != NULL)
- {
- *address = cache_recv_address (socket, msg.msg_name, msg.msg_namelen);
- }
-
- /* decode control messages */
- {
- GPtrArray *my_messages = NULL;
- struct cmsghdr *cmsg;
-
- if (msg.msg_controllen >= sizeof (struct cmsghdr))
- {
- for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
- {
- GSocketControlMessage *message;
-
- 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 */
- continue;
-
- if (messages == NULL)
- {
- /* we have to do it this way if the user ignores the
- * messages so that we will close any received fds.
- */
- g_object_unref (message);
- }
- else
- {
- if (my_messages == NULL)
- my_messages = g_ptr_array_new ();
- g_ptr_array_add (my_messages, message);
- }
- }
- }
-
- if (num_messages)
- *num_messages = my_messages != NULL ? my_messages->len : 0;
-
- if (messages)
- {
- if (my_messages == NULL)
- {
- *messages = NULL;
- }
- else
- {
- g_ptr_array_add (my_messages, NULL);
- *messages = (GSocketControlMessage **) g_ptr_array_free (my_messages, FALSE);
- }
- }
- else
- {
- g_assert (my_messages == NULL);
- }
- }
+ input_message_from_msghdr (&msg, &input_message, socket);
- /* capture the flags */
if (flags != NULL)
- *flags = msg.msg_flags;
+ *flags = input_message.flags;
return result;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]