mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
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
This commit is contained in:
parent
8c4c16ddf4
commit
5d68947466
522
gio/gsocket.c
522
gio/gsocket.c
@ -135,6 +135,9 @@ static gboolean g_socket_initable_init (GInitable *initable,
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
static GSocketAddress *
|
||||||
|
cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len);
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
g_socket_send_messages_with_blocking (GSocket *socket,
|
g_socket_send_messages_with_blocking (GSocket *socket,
|
||||||
GOutputMessage *messages,
|
GOutputMessage *messages,
|
||||||
@ -3699,6 +3702,227 @@ g_socket_condition_timed_wait (GSocket *socket,
|
|||||||
#endif
|
#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:
|
* g_socket_send_message:
|
||||||
* @socket: a #GSocket
|
* @socket: a #GSocket
|
||||||
@ -3813,84 +4037,25 @@ g_socket_send_message (GSocket *socket,
|
|||||||
|
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
{
|
{
|
||||||
|
GOutputMessage output_message;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
gssize result;
|
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 */
|
output_message_to_msghdr (&output_message, NULL, &msg, NULL, &child_error);
|
||||||
if (address)
|
|
||||||
|
if (child_error != NULL)
|
||||||
{
|
{
|
||||||
msg.msg_namelen = g_socket_address_get_native_size (address);
|
g_propagate_error (error, child_error);
|
||||||
msg.msg_name = g_alloca (msg.msg_namelen);
|
return -1;
|
||||||
if (!g_socket_address_to_native (address, msg.msg_name, msg.msg_namelen, error))
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
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 (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)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -4112,90 +4277,19 @@ g_socket_send_messages_with_blocking (GSocket *socket,
|
|||||||
{
|
{
|
||||||
GOutputMessage *msg = &messages[i];
|
GOutputMessage *msg = &messages[i];
|
||||||
struct msghdr *msg_hdr = &msgvec[i].msg_hdr;
|
struct msghdr *msg_hdr = &msgvec[i].msg_hdr;
|
||||||
|
GError *child_error = NULL;
|
||||||
|
|
||||||
msgvec[i].msg_len = 0;
|
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 (child_error != NULL)
|
||||||
if (i > 0 && msg->address == messages[i-1].address)
|
|
||||||
{
|
{
|
||||||
msg_hdr->msg_name = msgvec[i-1].msg_hdr.msg_name;
|
g_propagate_error (error, child_error);
|
||||||
msg_hdr->msg_namelen = msgvec[i-1].msg_hdr.msg_namelen;
|
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;
|
num_sent = result = 0;
|
||||||
@ -4469,68 +4563,28 @@ g_socket_receive_message (GSocket *socket,
|
|||||||
|
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
{
|
{
|
||||||
|
GInputMessage input_message;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
gssize result;
|
gssize result;
|
||||||
struct sockaddr_storage one_sockaddr;
|
|
||||||
|
|
||||||
/* name */
|
input_message.address = address;
|
||||||
if (address)
|
input_message.vectors = vectors;
|
||||||
{
|
input_message.num_vectors = num_vectors;
|
||||||
msg.msg_name = &one_sockaddr;
|
input_message.bytes_received = 0;
|
||||||
msg.msg_namelen = sizeof (struct sockaddr_storage);
|
input_message.flags = (flags != NULL) ? *flags : 0;
|
||||||
}
|
input_message.control_messages = messages;
|
||||||
else
|
input_message.num_control_messages = (guint *) num_messages;
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* We always set the close-on-exec flag so we don't leak file
|
/* We always set the close-on-exec flag so we don't leak file
|
||||||
* descriptors into child processes. Note that gunixfdmessage.c
|
* descriptors into child processes. Note that gunixfdmessage.c
|
||||||
* will later call fcntl (fd, FD_CLOEXEC), but that isn't atomic.
|
* will later call fcntl (fd, FD_CLOEXEC), but that isn't atomic.
|
||||||
*/
|
*/
|
||||||
#ifdef MSG_CMSG_CLOEXEC
|
#ifdef MSG_CMSG_CLOEXEC
|
||||||
msg.msg_flags |= MSG_CMSG_CLOEXEC;
|
input_message.flags |= MSG_CMSG_CLOEXEC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
input_message_to_msghdr (&input_message, &msg);
|
||||||
|
|
||||||
/* do it */
|
/* do it */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -4568,72 +4622,10 @@ g_socket_receive_message (GSocket *socket,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decode address */
|
input_message_from_msghdr (&msg, &input_message, socket);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* capture the flags */
|
|
||||||
if (flags != NULL)
|
if (flags != NULL)
|
||||||
*flags = msg.msg_flags;
|
*flags = input_message.flags;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user