#include "gsocket.h"
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
+#endif
+
#include <errno.h>
#include <signal.h>
#include <string.h>
#include "gioerror.h"
#include "gioenums.h"
#include "gioerror.h"
+#include "gio-marshal.h"
#include "gnetworkingprivate.h"
#include "gsocketaddress.h"
#include "gsocketcontrolmessage.h"
set_fd_nonblocking (int fd)
{
#ifndef G_OS_WIN32
- glong arg;
+ GError *error = NULL;
#else
gulong arg;
#endif
#ifndef G_OS_WIN32
- if ((arg = fcntl (fd, F_GETFL, NULL)) < 0)
+ if (!g_unix_set_fd_nonblocking (fd, TRUE, &error))
{
- g_warning ("Error getting socket status flags: %s", socket_strerror (errno));
- arg = 0;
+ g_warning ("Error setting socket nonblocking: %s", error->message);
+ g_clear_error (&error);
}
-
- arg = arg | O_NONBLOCK;
-
- if (fcntl (fd, F_SETFL, arg) < 0)
- g_warning ("Error setting socket status flags: %s", socket_strerror (errno));
#else
arg = TRUE;
/* Make sure winsock has been initialized */
type = g_inet_address_get_type ();
+ (type); /* To avoid -Wunused-but-set-variable */
#ifdef SIGPIPE
/* There is no portable, thread-safe way to avoid having the process
/**
* g_socket_accept:
* @socket: a #GSocket.
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Accept incoming connections on a connection-based socket. This removes
* g_socket_connect:
* @socket: a #GSocket.
* @address: a #GSocketAddress specifying the remote address.
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Connect the socket to the specified remote address.
* @buffer: a buffer to read data into (which should be at least @size
* bytes long).
* @size: the number of bytes you want to read from the socket
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Receive data (up to @size bytes) from a socket. This is mainly used by
* received, the additional data will be returned in future calls to
* g_socket_receive().
*
- * If the socket is in blocking mode the call will block until there is
- * some data to receive or there is an error. If there is no data available
- * and the socket is in non-blocking mode, a %G_IO_ERROR_WOULD_BLOCK error
- * will be returned. To be notified when data is available, wait for the
+ * If the socket is in blocking mode the call will block until there
+ * is some data to receive, the connection is closed, or there is an
+ * error. If there is no data available and the socket is in
+ * non-blocking mode, a %G_IO_ERROR_WOULD_BLOCK error will be
+ * returned. To be notified when data is available, wait for the
* %G_IO_IN condition.
*
* On error -1 is returned and @error is set accordingly.
*
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
*
* Since: 2.22
*/
* bytes long).
* @size: the number of bytes you want to read from the socket
* @blocking: whether to do blocking or non-blocking I/O
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* This behaves exactly the same as g_socket_receive(), except that
* the choice of blocking or non-blocking behavior is determined by
* the @blocking argument rather than by @socket's properties.
*
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
*
* Since: 2.26
*/
* @buffer: a buffer to read data into (which should be at least @size
* bytes long).
* @size: the number of bytes you want to read from the socket
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Receive data (up to @size bytes) from a socket.
*
* See g_socket_receive() for additional information.
*
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
*
* Since: 2.22
*/
/**
* g_socket_send:
* @socket: a #GSocket
- * @buffer: the buffer containing the data to send.
+ * @buffer: (array length=size): the buffer containing the data to send.
* @size: the number of bytes to send
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Tries to send @size bytes from @buffer on the socket. This is
/**
* g_socket_send_with_blocking:
* @socket: a #GSocket
- * @buffer: the buffer containing the data to send.
+ * @buffer: (array length=size): the buffer containing the data to send.
* @size: the number of bytes to send
* @blocking: whether to do blocking or non-blocking I/O
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* This behaves exactly the same as g_socket_send(), except that
* g_socket_send_to:
* @socket: a #GSocket
* @address: a #GSocketAddress, or %NULL
- * @buffer: the buffer containing the data to send.
+ * @buffer: (array length=size): the buffer containing the data to send.
* @size: the number of bytes to send
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Tries to send @size bytes from @buffer to @address. If @address is
GSocketSourceFunc func = (GSocketSourceFunc)callback;
GSocketSource *socket_source = (GSocketSource *)source;
+#ifdef G_OS_WIN32
+ socket_source->pollfd.revents = update_condition (socket_source->socket);
+#endif
+
return (*func) (socket_source->socket,
socket_source->pollfd.revents & socket_source->condition,
user_data);
}
}
+static gboolean
+socket_source_closure_callback (GSocket *socket,
+ GIOCondition condition,
+ gpointer data)
+{
+ GClosure *closure = data;
+
+ GValue params[2] = { { 0, }, { 0, } };
+ GValue result_value = { 0, };
+ gboolean result;
+
+ g_value_init (&result_value, G_TYPE_BOOLEAN);
+
+ g_value_init (¶ms[0], G_TYPE_SOCKET);
+ g_value_set_object (¶ms[0], socket);
+ g_value_init (¶ms[1], G_TYPE_IO_CONDITION);
+ g_value_set_flags (¶ms[1], condition);
+
+ g_closure_invoke (closure, &result_value, 2, params, NULL);
+
+ result = g_value_get_boolean (&result_value);
+ g_value_unset (&result_value);
+ g_value_unset (¶ms[0]);
+ g_value_unset (¶ms[1]);
+
+ return result;
+}
+
static GSourceFuncs socket_source_funcs =
{
socket_source_prepare,
socket_source_check,
socket_source_dispatch,
- socket_source_finalize
+ socket_source_finalize,
+ (GSourceFunc)socket_source_closure_callback,
+ (GSourceDummyMarshal)_gio_marshal_BOOLEAN__FLAGS,
};
static GSource *
}
/**
- * g_socket_create_source:
+ * g_socket_create_source: (skip)
* @socket: a #GSocket
* @condition: a #GIOCondition mask to monitor
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
*
* Creates a %GSource that can be attached to a %GMainContext to monitor
* for the availibility of the specified @condition on the socket.
* g_socket_condition_wait:
* @socket: a #GSocket
* @condition: a #GIOCondition mask to wait for
- * @cancellable: a #GCancellable, or %NULL
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
* @error: a #GError pointer, or %NULL
*
* Waits for @condition to become true on @socket. When the condition
* g_socket_send_message:
* @socket: a #GSocket
* @address: a #GSocketAddress, or %NULL
- * @vectors: an array of #GOutputVector structs
+ * @vectors: (array length=num_vectors): an array of #GOutputVector structs
* @num_vectors: the number of elements in @vectors, or -1
- * @messages: a pointer to an array of #GSocketControlMessages, or
- * %NULL.
+ * @messages: (array length=num_messages) (allow-none): a pointer to an
+ * array of #GSocketControlMessages, or %NULL.
* @num_messages: number of elements in @messages, or -1.
* @flags: an int containing #GSocketMsgFlags flags
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
* Send data to @address on @socket. This is the most complicated and
* g_socket_receive_message:
* @socket: a #GSocket
* @address: a pointer to a #GSocketAddress pointer, or %NULL
- * @vectors: an array of #GInputVector structs
+ * @vectors: (array length=num_vectors): an array of #GInputVector structs
* @num_vectors: the number of elements in @vectors, or -1
- * @messages: a pointer which may be filled with an array of
- * #GSocketControlMessages, or %NULL
+ * @messages: (array length=num_messages) (allow-none): a pointer which
+ * may be filled with an array of #GSocketControlMessages, or %NULL
* @num_messages: a pointer which will be filled with the number of
* elements in @messages, or %NULL
* @flags: a pointer to an int containing #GSocketMsgFlags flags
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
* @error: a #GError pointer, or %NULL
*
* Receive data from a socket. This is the most complicated and
* sufficiently-large buffer.
*
* If the socket is in blocking mode the call will block until there
- * is some data to receive or there is an error. If there is no data
- * available and the socket is in non-blocking mode, a
- * %G_IO_ERROR_WOULD_BLOCK error will be returned. To be notified when
- * data is available, wait for the %G_IO_IN condition.
+ * is some data to receive, the connection is closed, or there is an
+ * error. If there is no data available and the socket is in
+ * non-blocking mode, a %G_IO_ERROR_WOULD_BLOCK error will be
+ * returned. To be notified when data is available, wait for the
+ * %G_IO_IN condition.
*
* On error -1 is returned and @error is set accordingly.
*
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
*
* Since: 2.22
*/
else
msg.msg_flags = 0;
+ /* 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;
+#endif
+
/* do it */
while (1)
{
return -1;
result = recvmsg (socket->priv->fd, &msg, msg.msg_flags);
+#ifdef MSG_CMSG_CLOEXEC
+ if (result < 0 && get_socket_errno () == EINVAL)
+ {
+ /* We must be running on an old kernel. Call without the flag. */
+ msg.msg_flags &= ~(MSG_CMSG_CLOEXEC);
+ result = recvmsg (socket->priv->fd, &msg, msg.msg_flags);
+ }
+#endif
if (result < 0)
{
/* decode control messages */
{
GPtrArray *my_messages = NULL;
- const gchar *scm_pointer;
struct cmsghdr *cmsg;
- gsize scm_size;
-
- scm_pointer = (const gchar *) msg.msg_control;
- scm_size = msg.msg_controllen;
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
{