Silence a bunch of -Wunused-but-set-variable warnings
[platform/upstream/glib.git] / gio / gsocket.c
index 059f14e..aa0a39c 100644 (file)
 
 #include "config.h"
 
+#include "gsocket.h"
+
 #include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
 
 #ifndef G_OS_WIN32
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
 # include <fcntl.h>
 # include <unistd.h>
-# include <sys/types.h>
-#else
-# include <winsock2.h>
-# include <mswsock.h>
 #endif
 
-#include "gsocket.h"
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
 #include "gcancellable.h"
 #include "gioenumtypes.h"
+#include "ginetaddress.h"
 #include "ginitable.h"
-#include "gasynchelper.h"
 #include "gioerror.h"
 #include "gioenums.h"
 #include "gioerror.h"
+#include "gio-marshal.h"
+#include "gnetworkingprivate.h"
+#include "gsocketaddress.h"
+#include "gsocketcontrolmessage.h"
+#include "gcredentials.h"
 #include "glibintl.h"
 
-#include "gioalias.h"
-
 /**
  * SECTION:gsocket
- * @short_description: Low-level network socket handling
+ * @short_description: Low-level socket object
  * @include: gio/gio.h
  * @see_also: #GInitable
  *
  * A #GSocket is a low-level networking primitive. It is a more or less
  * direct mapping of the BSD socket API in a portable GObject based API.
- * It supports both the unix socket implementations and winsock2 on Windows.
+ * It supports both the UNIX socket implementations and winsock2 on Windows.
  *
  * #GSocket is the platform independent base upon which the higher level
  * network primitives are based. Applications are not typically meant to
- * use it directly, but rather through classes like #GSocketClient, etc.
- * However there may be cases where direct use of #GSocket is useful.
- *
- * TODO: Add more references to the highlevel API once that is more
- * finalized.
+ * use it directly, but rather through classes like #GSocketClient,
+ * #GSocketService and #GSocketConnection. However there may be cases where
+ * direct use of #GSocket is useful.
  *
  * #GSocket implements the #GInitable interface, so if it is manually constructed
  * by e.g. g_object_new() you must call g_initable_init() and check the
  *
  * All socket file descriptors are set to be close-on-exec.
  *
+ * Note that creating a #GSocket causes the signal %SIGPIPE to be
+ * ignored for the remainder of the program. If you are writing a
+ * command-line utility that uses #GSocket, you may need to take into
+ * account the fact that your program will not automatically be killed
+ * if it tries to write to %stdout after it has been closed.
+ *
  * Since: 2.22
- **/
+ */
 
 static void     g_socket_initable_iface_init (GInitableIface  *iface);
 static gboolean g_socket_initable_init       (GInitable       *initable,
@@ -125,23 +133,28 @@ enum
   PROP_LISTEN_BACKLOG,
   PROP_KEEPALIVE,
   PROP_LOCAL_ADDRESS,
-  PROP_REMOTE_ADDRESS
+  PROP_REMOTE_ADDRESS,
+  PROP_TIMEOUT
 };
 
 struct _GSocketPrivate
 {
   GSocketFamily   family;
   GSocketType     type;
-  char           *protocol;
+  GSocketProtocol protocol;
   gint            fd;
   gint            listen_backlog;
+  guint           timeout;
   GError         *construct_error;
-  GSocketAddress *local_address;
   GSocketAddress *remote_address;
   guint           inited : 1;
   guint           blocking : 1;
   guint           keepalive : 1;
   guint           closed : 1;
+  guint           connected : 1;
+  guint           listening : 1;
+  guint           timed_out : 1;
+  guint           connect_pending : 1;
 #ifdef G_OS_WIN32
   WSAEVENT        event;
   int             current_events;
@@ -201,20 +214,13 @@ socket_strerror (int err)
 #ifndef G_OS_WIN32
   return g_strerror (err);
 #else
-  static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
-  char *buf, *msg;
-
-  buf = g_static_private_get (&msg_private);
-  if (!buf)
-    {
-      buf = g_new (gchar, 128);
-      g_static_private_set (&msg_private, buf, g_free);
-    }
+  static GStaticPrivate last_msg = G_STATIC_PRIVATE_INIT;
+  char *msg;
 
   msg = g_win32_error_message (err);
-  strncpy (buf, msg, 128);
-  g_free (msg);
-  return buf;
+  g_static_private_set (&last_msg, msg, g_free);
+
+  return msg;
 #endif
 }
 
@@ -267,8 +273,8 @@ check_socket (GSocket *socket,
 {
   if (!socket->priv->inited)
     {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
-                  _("Invalid socket, not initialized"));
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
+                           _("Invalid socket, not initialized"));
       return FALSE;
     }
 
@@ -286,6 +292,15 @@ check_socket (GSocket *socket,
                           _("Socket is already closed"));
       return FALSE;
     }
+
+  if (socket->priv->timed_out)
+    {
+      socket->priv->timed_out = FALSE;
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+                          _("Socket I/O timed out"));
+      return FALSE;
+    }
+
   return TRUE;
 }
 
@@ -299,7 +314,8 @@ g_socket_details_from_fd (GSocket *socket)
   int value;
   int errsv;
 #ifdef G_OS_WIN32
-  BOOL bool_val;
+  /* See bug #611756 */
+  BOOL bool_val = FALSE;
 #else
   int bool_val;
 #endif
@@ -362,31 +378,55 @@ g_socket_details_from_fd (GSocket *socket)
     {
      case G_SOCKET_FAMILY_IPV4:
      case G_SOCKET_FAMILY_IPV6:
+       socket->priv->family = address.ss_family;
+       switch (socket->priv->type)
+        {
+        case G_SOCKET_TYPE_STREAM:
+          socket->priv->protocol = G_SOCKET_PROTOCOL_TCP;
+          break;
+
+        case G_SOCKET_TYPE_DATAGRAM:
+          socket->priv->protocol = G_SOCKET_PROTOCOL_UDP;
+          break;
+
+        case G_SOCKET_TYPE_SEQPACKET:
+          socket->priv->protocol = G_SOCKET_PROTOCOL_SCTP;
+          break;
+
+        default:
+          break;
+        }
+       break;
+
      case G_SOCKET_FAMILY_UNIX:
-      socket->priv->family = address.ss_family;
-      break;
+       socket->priv->family = G_SOCKET_FAMILY_UNIX;
+       socket->priv->protocol = G_SOCKET_PROTOCOL_DEFAULT;
+       break;
 
      default:
-      socket->priv->family = G_SOCKET_FAMILY_INVALID;
-      break;
+       socket->priv->family = G_SOCKET_FAMILY_INVALID;
+       break;
     }
 
   if (socket->priv->family != G_SOCKET_FAMILY_INVALID)
     {
-      socket->priv->local_address =
-       g_socket_address_new_from_native (&address, addrlen);
-
       addrlen = sizeof address;
       if (getpeername (fd, (struct sockaddr *) &address, &addrlen) >= 0)
-       socket->priv->remote_address =
-         g_socket_address_new_from_native (&address, addrlen);
+       socket->priv->connected = TRUE;
     }
 
   optlen = sizeof bool_val;
   if (getsockopt (fd, SOL_SOCKET, SO_KEEPALIVE,
                  (void *)&bool_val, &optlen) == 0)
     {
+#ifndef G_OS_WIN32
+      /* Experimentation indicates that the SO_KEEPALIVE value is
+       * actually a char on Windows, even if documentation claims it
+       * to be a BOOL which is a typedef for int. So this g_assert()
+       * fails. See bug #611756.
+       */
       g_assert (optlen == sizeof bool_val);
+#endif
       socket->priv->keepalive = !!bool_val;
     }
   else
@@ -407,13 +447,11 @@ g_socket_details_from_fd (GSocket *socket)
 static gint
 g_socket_create_socket (GSocketFamily   family,
                        GSocketType     type,
-                       const char     *protocol_name,
+                       int             protocol,
                        GError        **error)
 {
   gint native_type;
   gint fd;
-  gint protocol;
-  struct protoent *protoent;
 
   switch (type)
     {
@@ -433,41 +471,26 @@ g_socket_create_socket (GSocketFamily   family,
       g_assert_not_reached ();
     }
 
-  protocol = 0;
-  if (protocol_name)
+  if (protocol == -1)
     {
-#ifdef HAVE_GETPROTOBYNAME_R
-      char buffer[1024];
-      struct protoent my_protoent;
-
-      protoent = NULL;
-      getprotobyname_r (protocol_name,
-                       &my_protoent, buffer, sizeof (buffer),
-                       &protoent);
-#else
-      protoent = getprotobyname (protocol_name);
-#endif
-      if (protoent == NULL)
-       {
-         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                      _("unable to create socket: Protocol %s not supported"),
-                      protocol_name);
-         return -1;
-       }
-      protocol = protoent->p_proto;
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+                  _("Unable to create socket: %s"), _("Unknown protocol was specified"));
+      return -1;
     }
 
 #ifdef SOCK_CLOEXEC
-  native_type |= SOCK_CLOEXEC;
+  fd = socket (family, native_type | SOCK_CLOEXEC, protocol);
+  /* It's possible that libc has SOCK_CLOEXEC but the kernel does not */
+  if (fd < 0 && errno == EINVAL)
 #endif
-  fd = socket (family, native_type, protocol);
+    fd = socket (family, native_type, protocol);
 
   if (fd < 0)
     {
       int errsv = get_socket_errno ();
 
       g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
-                  _("unable to create socket: %s"), socket_strerror (errsv));
+                  _("Unable to create socket: %s"), socket_strerror (errsv));
     }
 
 #ifndef G_OS_WIN32
@@ -521,6 +544,7 @@ g_socket_get_property (GObject    *object,
                       GParamSpec *pspec)
 {
   GSocket *socket = G_SOCKET (object);
+  GSocketAddress *address;
 
   switch (prop_id)
     {
@@ -533,7 +557,7 @@ g_socket_get_property (GObject    *object,
        break;
 
       case PROP_PROTOCOL:
-       g_value_set_string (value, socket->priv->protocol);
+       g_value_set_enum (value, socket->priv->protocol);
        break;
 
       case PROP_FD:
@@ -553,11 +577,17 @@ g_socket_get_property (GObject    *object,
        break;
 
       case PROP_LOCAL_ADDRESS:
-       g_value_set_object (value, socket->priv->local_address);
+       address = g_socket_get_local_address (socket, NULL);
+       g_value_take_object (value, address);
        break;
 
       case PROP_REMOTE_ADDRESS:
-       g_value_set_object (value, socket->priv->remote_address);
+       address = g_socket_get_remote_address (socket, NULL);
+       g_value_take_object (value, address);
+       break;
+
+      case PROP_TIMEOUT:
+       g_value_set_uint (value, socket->priv->timeout);
        break;
 
       default:
@@ -584,7 +614,7 @@ g_socket_set_property (GObject      *object,
        break;
 
       case PROP_PROTOCOL:
-       socket->priv->protocol = g_value_dup_string (value);
+       socket->priv->protocol = g_value_get_enum (value);
        break;
 
       case PROP_FD:
@@ -603,6 +633,10 @@ g_socket_set_property (GObject      *object,
        g_socket_set_keepalive (socket, g_value_get_boolean (value));
        break;
 
+      case PROP_TIMEOUT:
+       g_socket_set_timeout (socket, g_value_get_uint (value));
+       break;
+
       default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -619,9 +653,16 @@ g_socket_finalize (GObject *object)
       !socket->priv->closed)
     g_socket_close (socket, NULL);
 
-  g_free (socket->priv->protocol);
+  if (socket->priv->remote_address)
+    g_object_unref (socket->priv->remote_address);
 
 #ifdef G_OS_WIN32
+  if (socket->priv->event != WSA_INVALID_EVENT)
+    {
+      WSACloseEvent (socket->priv->event);
+      socket->priv->event = WSA_INVALID_EVENT;
+    }
+
   g_assert (socket->priv->requested_conditions == NULL);
 #endif
 
@@ -630,27 +671,6 @@ g_socket_finalize (GObject *object)
 }
 
 static void
-g_socket_dispose (GObject *object)
-{
-  GSocket *socket = G_SOCKET (object);
-
-  if (socket->priv->local_address)
-    {
-      g_object_unref (socket->priv->local_address);
-      socket->priv->local_address = NULL;
-    }
-
-  if (socket->priv->remote_address)
-    {
-      g_object_unref (socket->priv->remote_address);
-      socket->priv->remote_address = NULL;
-    }
-
-  if (G_OBJECT_CLASS (g_socket_parent_class)->dispose)
-    (*G_OBJECT_CLASS (g_socket_parent_class)->dispose) (object);
-}
-
-static void
 g_socket_class_init (GSocketClass *klass)
 {
   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
@@ -658,11 +678,19 @@ g_socket_class_init (GSocketClass *klass)
 
   /* 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
+   * be killed by SIGPIPE when calling send() or sendmsg(), so we are
+   * forced to simply ignore the signal process-wide.
+   */
+  signal (SIGPIPE, SIG_IGN);
+#endif
 
   g_type_class_add_private (klass, sizeof (GSocketPrivate));
 
   gobject_class->finalize = g_socket_finalize;
-  gobject_class->dispose = g_socket_dispose;
   gobject_class->constructed = g_socket_constructed;
   gobject_class->set_property = g_socket_set_property;
   gobject_class->get_property = g_socket_get_property;
@@ -673,7 +701,9 @@ g_socket_class_init (GSocketClass *klass)
                                                      P_("The sockets address family"),
                                                      G_TYPE_SOCKET_FAMILY,
                                                      G_SOCKET_FAMILY_INVALID,
-                                                     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                     G_PARAM_CONSTRUCT_ONLY |
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_TYPE,
                                   g_param_spec_enum ("type",
@@ -681,14 +711,19 @@ g_socket_class_init (GSocketClass *klass)
                                                      P_("The sockets type"),
                                                      G_TYPE_SOCKET_TYPE,
                                                      G_SOCKET_TYPE_STREAM,
-                                                     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                     G_PARAM_CONSTRUCT_ONLY |
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_PROTOCOL,
-                                  g_param_spec_string ("protocol",
-                                                       P_("Socket protocol"),
-                                                       P_("The name of the protocol to use, or NULL"),
-                                                       NULL,
-                                                       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                  g_param_spec_enum ("protocol",
+                                                     P_("Socket protocol"),
+                                                     P_("The id of the protocol to use, or -1 for unknown"),
+                                                     G_TYPE_SOCKET_PROTOCOL,
+                                                     G_SOCKET_PROTOCOL_UNKNOWN,
+                                                     G_PARAM_CONSTRUCT_ONLY |
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_FD,
                                   g_param_spec_int ("fd",
@@ -697,44 +732,68 @@ g_socket_class_init (GSocketClass *klass)
                                                     G_MININT,
                                                     G_MAXINT,
                                                     -1,
-                                                    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                    G_PARAM_CONSTRUCT_ONLY |
+                                                     G_PARAM_READWRITE |
+                                                     G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BLOCKING,
                                   g_param_spec_boolean ("blocking",
                                                         P_("blocking"),
                                                         P_("Whether or not I/O on this socket is blocking"),
                                                         TRUE,
-                                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                        G_PARAM_READWRITE |
+                                                         G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_LISTEN_BACKLOG,
                                   g_param_spec_int ("listen-backlog",
                                                     P_("Listen backlog"),
-                                                    P_("outstanding connections in the listen queue"),
+                                                    P_("Outstanding connections in the listen queue"),
                                                     0,
                                                     SOMAXCONN,
                                                     10,
-                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                    G_PARAM_READWRITE |
+                                                     G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_KEEPALIVE,
                                   g_param_spec_boolean ("keepalive",
                                                         P_("Keep connection alive"),
                                                         P_("Keep connection alive by sending periodic pings"),
                                                         FALSE,
-                                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                        G_PARAM_READWRITE |
+                                                         G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS,
                                   g_param_spec_object ("local-address",
                                                        P_("Local address"),
                                                        P_("The local address the socket is bound to"),
                                                        G_TYPE_SOCKET_ADDRESS,
-                                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+                                                       G_PARAM_READABLE |
+                                                        G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_REMOTE_ADDRESS,
                                   g_param_spec_object ("remote-address",
                                                        P_("Remote address"),
                                                        P_("The remote address the socket is connected to"),
                                                        G_TYPE_SOCKET_ADDRESS,
-                                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+                                                       G_PARAM_READABLE |
+                                                        G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GSocket:timeout:
+   *
+   * The timeout in seconds on socket I/O
+   *
+   * Since: 2.26
+   */
+  g_object_class_install_property (gobject_class, PROP_TIMEOUT,
+                                  g_param_spec_uint ("timeout",
+                                                     P_("Timeout"),
+                                                     P_("The timeout in seconds on socket I/O"),
+                                                     0,
+                                                     G_MAXUINT,
+                                                     0,
+                                                     G_PARAM_READWRITE |
+                                                     G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -752,8 +811,6 @@ g_socket_init (GSocket *socket)
   socket->priv->blocking = TRUE;
   socket->priv->listen_backlog = 10;
   socket->priv->construct_error = NULL;
-  socket->priv->remote_address = NULL;
-  socket->priv->local_address = NULL;
 #ifdef G_OS_WIN32
   socket->priv->event = WSA_INVALID_EVENT;
 #endif
@@ -772,8 +829,8 @@ g_socket_initable_init (GInitable *initable,
 
   if (cancellable != NULL)
     {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                  _("Cancellable initialization not supported"));
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Cancellable initialization not supported"));
       return FALSE;
     }
 
@@ -794,23 +851,33 @@ g_socket_initable_init (GInitable *initable,
  * g_socket_new:
  * @family: the socket family to use, e.g. %G_SOCKET_FAMILY_IPV4.
  * @type: the socket type to use.
- * @protocol: the name of the protocol to use, or %NULL.
+ * @protocol: the id of the protocol to use, or 0 for default.
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Creates a new #GSocket with the defined family, type and protocol.
- * If @protocol is %NULL the default protocol type for the family and
- * type is used.
+ * If @protocol is 0 (%G_SOCKET_PROTOCOL_DEFAULT) the default protocol type
+ * for the family and type is used.
+ *
+ * The @protocol is a family and type specific int that specifies what
+ * kind of protocol to use. #GSocketProtocol lists several common ones.
+ * Many families only support one protocol, and use 0 for this, others
+ * support several and using 0 means to use the default protocol for
+ * the family and type.
+ *
+ * The protocol id is passed directly to the operating
+ * system, so you can use protocols not listed in #GSocketProtocol if you
+ * know the protocol number used for it.
  *
  * Returns: a #GSocket or %NULL on error.
  *     Free the returned object with g_object_unref().
  *
  * Since: 2.22
- **/
+ */
 GSocket *
-g_socket_new (GSocketFamily family,
-             GSocketType type,
-             const char *protocol,
-             GError **error)
+g_socket_new (GSocketFamily     family,
+             GSocketType       type,
+             GSocketProtocol   protocol,
+             GError          **error)
 {
   return G_SOCKET (g_initable_new (G_TYPE_SOCKET,
                                   NULL, error,
@@ -837,9 +904,9 @@ g_socket_new (GSocketFamily family,
  *     Free the returned object with g_object_unref().
  *
  * Since: 2.22
- **/
+ */
 GSocket *
-g_socket_new_from_fd (gint fd,
+g_socket_new_from_fd (gint     fd,
                      GError **error)
 {
   return G_SOCKET (g_initable_new (G_TYPE_SOCKET,
@@ -863,7 +930,7 @@ g_socket_new_from_fd (gint fd,
  * is a GSocket level feature.
  *
  * Since: 2.22
- **/
+ */
 void
 g_socket_set_blocking (GSocket  *socket,
                       gboolean  blocking)
@@ -889,7 +956,7 @@ g_socket_set_blocking (GSocket  *socket,
  * Returns: %TRUE if blocking I/O is used, %FALSE otherwise.
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_get_blocking (GSocket *socket)
 {
@@ -901,26 +968,29 @@ g_socket_get_blocking (GSocket *socket)
 /**
  * g_socket_set_keepalive:
  * @socket: a #GSocket.
- * @keepalive: Whether to use try to keep the connection alive or not.
+ * @keepalive: Value for the keepalive flag
+ *
+ * Sets or unsets the %SO_KEEPALIVE flag on the underlying socket. When
+ * this flag is set on a socket, the system will attempt to verify that the
+ * remote socket endpoint is still present if a sufficiently long period of
+ * time passes with no data being exchanged. If the system is unable to
+ * verify the presence of the remote endpoint, it will automatically close
+ * the connection.
  *
- * Setting @keepalive to %TRUE enables the sending of periodic ping requests
- * on idle connections in order to keep the connection alive. This is only
- * useful for connection oriented sockets. The exact period used between
- * each ping is system and protocol dependent.
+ * This option is only functional on certain kinds of sockets. (Notably,
+ * %G_SOCKET_PROTOCOL_TCP sockets.)
  *
- * Sending keepalive requests like this has a few disadvantages. For instance,
- * it uses more network bandwidth, and it makes your application more sensitive
- * to temporary outages in the network (i.e. if a cable is pulled your otherwise
- * idle connection could be terminated, whereas otherwise it would survive unless
- * actually used before the cable was reinserted). However, it is sometimes
- * useful to ensure that connections are eventually terminated if e.g. the
- * remote side is disconnected, so as to avoid leaking resources forever.
+ * The exact time between pings is system- and protocol-dependent, but will
+ * normally be at least two hours. Most commonly, you would set this flag
+ * on a server socket if you want to allow clients to remain idle for long
+ * periods of time, but also want to ensure that connections are eventually
+ * garbage-collected if clients crash or become unreachable.
  *
  * Since: 2.22
- **/
+ */
 void
-g_socket_set_keepalive (GSocket *socket,
-                       gboolean keepalive)
+g_socket_set_keepalive (GSocket  *socket,
+                       gboolean  keepalive)
 {
   int value;
 
@@ -953,7 +1023,7 @@ g_socket_set_keepalive (GSocket *socket,
  * Returns: %TRUE if keepalive is active, %FALSE otherwise.
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_get_keepalive (GSocket *socket)
 {
@@ -972,9 +1042,9 @@ g_socket_get_keepalive (GSocket *socket)
  * Returns: the maximum number of pending connections.
  *
  * Since: 2.22
- **/
+ */
 gint
-g_socket_get_listen_backlog  (GSocket                 *socket)
+g_socket_get_listen_backlog  (GSocket *socket)
 {
   g_return_val_if_fail (G_IS_SOCKET (socket), 0);
 
@@ -991,13 +1061,17 @@ g_socket_get_listen_backlog  (GSocket                 *socket)
  * connecting to the socket and the application is not handling them
  * on time then the new connections will be refused.
  *
+ * Note that this must be called before g_socket_listen() and has no
+ * effect if called after that.
+ *
  * Since: 2.22
- **/
+ */
 void
 g_socket_set_listen_backlog (GSocket *socket,
-                            gint backlog)
+                            gint     backlog)
 {
   g_return_if_fail (G_IS_SOCKET (socket));
+  g_return_if_fail (!socket->priv->listening);
 
   if (backlog != socket->priv->listen_backlog)
     {
@@ -1007,6 +1081,66 @@ g_socket_set_listen_backlog (GSocket *socket,
 }
 
 /**
+ * g_socket_get_timeout:
+ * @socket: a #GSocket.
+ *
+ * Gets the timeout setting of the socket. For details on this, see
+ * g_socket_set_timeout().
+ *
+ * Returns: the timeout in seconds
+ *
+ * Since: 2.26
+ */
+guint
+g_socket_get_timeout (GSocket *socket)
+{
+  g_return_val_if_fail (G_IS_SOCKET (socket), 0);
+
+  return socket->priv->timeout;
+}
+
+/**
+ * g_socket_set_timeout:
+ * @socket: a #GSocket.
+ * @timeout: the timeout for @socket, in seconds, or 0 for none
+ *
+ * Sets the time in seconds after which I/O operations on @socket will
+ * time out if they have not yet completed.
+ *
+ * On a blocking socket, this means that any blocking #GSocket
+ * operation will time out after @timeout seconds of inactivity,
+ * returning %G_IO_ERROR_TIMED_OUT.
+ *
+ * On a non-blocking socket, calls to g_socket_condition_wait() will
+ * also fail with %G_IO_ERROR_TIMED_OUT after the given time. Sources
+ * created with g_socket_create_source() will trigger after
+ * @timeout seconds of inactivity, with the requested condition
+ * set, at which point calling g_socket_receive(), g_socket_send(),
+ * g_socket_check_connect_result(), etc, will fail with
+ * %G_IO_ERROR_TIMED_OUT.
+ *
+ * If @timeout is 0 (the default), operations will never time out
+ * on their own.
+ *
+ * Note that if an I/O operation is interrupted by a signal, this may
+ * cause the timeout to be reset.
+ *
+ * Since: 2.26
+ */
+void
+g_socket_set_timeout (GSocket *socket,
+                     guint    timeout)
+{
+  g_return_if_fail (G_IS_SOCKET (socket));
+
+  if (timeout != socket->priv->timeout)
+    {
+      socket->priv->timeout = timeout;
+      g_object_notify (G_OBJECT (socket), "timeout");
+    }
+}
+
+/**
  * g_socket_get_family:
  * @socket: a #GSocket.
  *
@@ -1015,7 +1149,7 @@ g_socket_set_listen_backlog (GSocket *socket,
  * Returns: a #GSocketFamily
  *
  * Since: 2.22
- **/
+ */
 GSocketFamily
 g_socket_get_family (GSocket *socket)
 {
@@ -1033,7 +1167,7 @@ g_socket_get_family (GSocket *socket)
  * Returns: a #GSocketType
  *
  * Since: 2.22
- **/
+ */
 GSocketType
 g_socket_get_socket_type (GSocket *socket)
 {
@@ -1046,17 +1180,17 @@ g_socket_get_socket_type (GSocket *socket)
  * g_socket_get_protocol:
  * @socket: a #GSocket.
  *
- * Gets the socket protocol type name the socket was created with.
- * This can be %NULL if the socket was created with a NULL protocol.
+ * Gets the socket protocol id the socket was created with.
+ * In case the protocol is unknown, -1 is returned.
  *
- * Returns: a string or %NULL, do not free
+ * Returns: a protocol id, or -1 if unknown
  *
  * Since: 2.22
- **/
-const char *
+ */
+GSocketProtocol
 g_socket_get_protocol (GSocket *socket)
 {
-  g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
+  g_return_val_if_fail (G_IS_SOCKET (socket), -1);
 
   return socket->priv->protocol;
 }
@@ -1074,7 +1208,7 @@ g_socket_get_protocol (GSocket *socket)
  * Returns: the file descriptor of the socket.
  *
  * Since: 2.22
- **/
+ */
 int
 g_socket_get_fd (GSocket *socket)
 {
@@ -1089,25 +1223,24 @@ g_socket_get_fd (GSocket *socket)
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Try to get the local address of a bound socket. This is only
- * useful if the socket has been bound to a local address.
+ * useful if the socket has been bound to a local address,
+ * either explicitly or implicitly when connecting.
  *
- * Returns: a #GSocketAddress or %NULL on error.
+ * Returns: (transfer full): a #GSocketAddress or %NULL on error.
+ *     Free the returned object with g_object_unref().
  *
  * Since: 2.22
- **/
+ */
 GSocketAddress *
 g_socket_get_local_address (GSocket  *socket,
                            GError  **error)
 {
-  gchar buffer[256];
-  guint32 len = 256;
+  struct sockaddr_storage buffer;
+  guint32 len = sizeof (buffer);
 
   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
 
-  if (socket->priv->local_address)
-    return socket->priv->local_address;
-
-  if (getsockname (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
+  if (getsockname (socket->priv->fd, (struct sockaddr *) &buffer, &len) < 0)
     {
       int errsv = get_socket_errno ();
       g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
@@ -1115,8 +1248,7 @@ g_socket_get_local_address (GSocket  *socket,
       return NULL;
     }
 
-  socket->priv->local_address = g_socket_address_new_from_native (buffer, len);
-  return socket->priv->local_address;
+  return g_socket_address_new_from_native (&buffer, len);
 }
 
 /**
@@ -1127,32 +1259,42 @@ g_socket_get_local_address (GSocket  *socket,
  * Try to get the remove address of a connected socket. This is only
  * useful for connection oriented sockets that have been connected.
  *
- * Returns: a #GSocketAddress or %NULL on error.
+ * Returns: (transfer full): a #GSocketAddress or %NULL on error.
+ *     Free the returned object with g_object_unref().
  *
  * Since: 2.22
- **/
+ */
 GSocketAddress *
 g_socket_get_remote_address (GSocket  *socket,
                             GError  **error)
 {
-  gchar buffer[256];
-  guint32 len = 256;
+  struct sockaddr_storage buffer;
+  guint32 len = sizeof (buffer);
 
   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
 
-  if (socket->priv->remote_address)
-    return socket->priv->remote_address;
+  if (socket->priv->connect_pending)
+    {
+      if (!g_socket_check_connect_result (socket, error))
+        return NULL;
+      else
+        socket->priv->connect_pending = FALSE;
+    }
 
-  if (getpeername (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
+  if (!socket->priv->remote_address)
     {
-      int errsv = get_socket_errno ();
-      g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
-                  _("could not get remote address: %s"), socket_strerror (errsv));
-      return NULL;
+      if (getpeername (socket->priv->fd, (struct sockaddr *) &buffer, &len) < 0)
+       {
+         int errsv = get_socket_errno ();
+         g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
+                      _("could not get remote address: %s"), socket_strerror (errsv));
+         return NULL;
+       }
+
+      socket->priv->remote_address = g_socket_address_new_from_native (&buffer, len);
     }
 
-  socket->priv->remote_address = g_socket_address_new_from_native (buffer, len);
-  return socket->priv->remote_address;
+  return g_object_ref (socket->priv->remote_address);
 }
 
 /**
@@ -1165,13 +1307,13 @@ g_socket_get_remote_address (GSocket  *socket,
  * Returns: %TRUE if socket is connected, %FALSE otherwise.
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_is_connected (GSocket *socket)
 {
   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
 
-  return socket->priv->remote_address != NULL;
+  return socket->priv->connected;
 }
 
 /**
@@ -1185,10 +1327,13 @@ g_socket_is_connected (GSocket *socket)
  * Before calling this the socket must be bound to a local address using
  * g_socket_bind().
  *
+ * To set the maximum amount of outstanding clients, use
+ * g_socket_set_listen_backlog().
+ *
  * Returns: %TRUE on success, %FALSE on error.
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_listen (GSocket  *socket,
                 GError  **error)
@@ -1207,6 +1352,8 @@ g_socket_listen (GSocket  *socket,
       return FALSE;
     }
 
+  socket->priv->listening = TRUE;
+
   return TRUE;
 }
 
@@ -1223,29 +1370,29 @@ g_socket_listen (GSocket  *socket,
  *
  * It is generally required to bind to a local address before you can
  * receive connections. (See g_socket_listen() and g_socket_accept() ).
- *
- * If @allow_reuse is %TRUE this allows the bind call to succeed in some
- * situation where it would otherwise return a %G_IO_ERROR_ADDRESS_IN_USE
- * error. The main example is for a TCP server socket where there are
- * outstanding connections in the WAIT state, which are generally safe
- * to ignore. However, setting it to %TRUE doesn't mean the call will
- * succeed if there is a socket actively bound to the address.
- *
- * In general, pass %TRUE if the socket will be used to accept connections,
- * otherwise pass %FALSE.
+ * In certain situations, you may also want to bind a socket that will be
+ * used to initiate connections, though this is not normally required.
+ *
+ * @allow_reuse should be %TRUE for server sockets (sockets that you will
+ * eventually call g_socket_accept() on), and %FALSE for client sockets.
+ * (Specifically, if it is %TRUE, then g_socket_bind() will set the
+ * %SO_REUSEADDR flag on the socket, allowing it to bind @address even if
+ * that address was previously used by another socket that has not yet been
+ * fully cleaned-up by the kernel. Failing to set this flag on a server
+ * socket may cause the bind call to return %G_IO_ERROR_ADDRESS_IN_USE if
+ * the server program is stopped and then immediately restarted.)
  *
  * Returns: %TRUE on success, %FALSE on error.
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_bind (GSocket         *socket,
               GSocketAddress  *address,
               gboolean         reuse_address,
               GError         **error)
 {
-  gchar addr[256];
-  int value;
+  struct sockaddr_storage addr;
 
   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
 
@@ -1255,22 +1402,21 @@ g_socket_bind (GSocket         *socket,
   /* SO_REUSEADDR on windows means something else and is not what we want.
      It always allows the unix variant of SO_REUSEADDR anyway */
 #ifndef G_OS_WIN32
-  value = (int) !!reuse_address;
-  if (setsockopt (socket->priv->fd, SOL_SOCKET, SO_REUSEADDR,
-                 (gpointer) &value, sizeof (value)) < 0)
-    {
-      int errsv = get_socket_errno ();
-      g_set_error (error,
-                  G_IO_ERROR, socket_io_error_from_errno (errsv),
-                  _("Error setting reuse_address: %s"), socket_strerror (errsv));
-      return FALSE;
-    }
+  {
+    int value;
+
+    value = (int) !!reuse_address;
+    /* Ignore errors here, the only likely error is "not supported", and
+       this is a "best effort" thing mainly */
+    setsockopt (socket->priv->fd, SOL_SOCKET, SO_REUSEADDR,
+               (gpointer) &value, sizeof (value));
+  }
 #endif
 
-  if (!g_socket_address_to_native (address, addr, sizeof addr))
+  if (!g_socket_address_to_native (address, &addr, sizeof addr, error))
     return FALSE;
 
-  if (bind (socket->priv->fd, (struct sockaddr *) addr,
+  if (bind (socket->priv->fd, (struct sockaddr *) &addr,
            g_socket_address_get_native_size (address)) < 0)
     {
       int errsv = get_socket_errno ();
@@ -1280,14 +1426,61 @@ g_socket_bind (GSocket         *socket,
       return FALSE;
     }
 
-  socket->priv->local_address = g_object_ref (address);
-
   return TRUE;
 }
 
 /**
+ * g_socket_speaks_ipv4:
+ * @socket: a #GSocket
+ *
+ * Checks if a socket is capable of speaking IPv4.
+ *
+ * IPv4 sockets are capable of speaking IPv4.  On some operating systems
+ * and under some combinations of circumstances IPv6 sockets are also
+ * capable of speaking IPv4.  See RFC 3493 section 3.7 for more
+ * information.
+ *
+ * No other types of sockets are currently considered as being capable
+ * of speaking IPv4.
+ *
+ * Returns: %TRUE if this socket can be used with IPv4.
+ *
+ * Since: 2.22
+ **/
+gboolean
+g_socket_speaks_ipv4 (GSocket *socket)
+{
+  switch (socket->priv->family)
+    {
+    case G_SOCKET_FAMILY_IPV4:
+      return TRUE;
+
+    case G_SOCKET_FAMILY_IPV6:
+#if defined (IPPROTO_IPV6) && defined (IPV6_V6ONLY)
+      {
+        guint sizeof_int = sizeof (int);
+        gint v6_only;
+
+        if (getsockopt (socket->priv->fd,
+                        IPPROTO_IPV6, IPV6_V6ONLY,
+                        &v6_only, &sizeof_int) != 0)
+          return FALSE;
+
+        return !v6_only;
+      }
+#else
+      return FALSE;
+#endif
+
+    default:
+      return FALSE;
+    }
+}
+
+/**
  * g_socket_accept:
  * @socket: a #GSocket.
+ * @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
@@ -1301,13 +1494,14 @@ g_socket_bind (GSocket         *socket,
  * or return %G_IO_ERROR_WOULD_BLOCK if non-blocking I/O is enabled.
  * To be notified of an incoming connection, wait for the %G_IO_IN condition.
  *
- * Returns: a new #GSocket, or %NULL on error.
+ * Returns: (transfer full): a new #GSocket, or %NULL on error.
  *     Free the returned object with g_object_unref().
  *
  * Since: 2.22
- **/
+ */
 GSocket *
 g_socket_accept (GSocket       *socket,
+                GCancellable  *cancellable,
                 GError       **error)
 {
   GSocket *new_socket;
@@ -1318,11 +1512,11 @@ g_socket_accept (GSocket       *socket,
   if (!check_socket (socket, error))
     return NULL;
 
-  while (1)
+  while (TRUE)
     {
       if (socket->priv->blocking &&
          !g_socket_condition_wait (socket,
-                                   G_IO_IN, NULL, error))
+                                   G_IO_IN, cancellable, error))
        return NULL;
 
       if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
@@ -1388,6 +1582,8 @@ g_socket_accept (GSocket       *socket,
       close (ret);
 #endif
     }
+  else
+    new_socket->priv->protocol = socket->priv->protocol;
 
   return new_socket;
 }
@@ -1396,6 +1592,7 @@ g_socket_accept (GSocket       *socket,
  * g_socket_connect:
  * @socket: a #GSocket.
  * @address: a #GSocketAddress specifying the remote address.
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Connect the socket to the specified remote address.
@@ -1405,41 +1602,43 @@ g_socket_accept (GSocket       *socket,
  * the default address for g_socket_send() and discards all incoming datagrams
  * from other sources.
  *
- * Generally connection oriented sockets can only connect once, but connection-less
- * sockets can connect multiple times to change the default address.
+ * Generally connection oriented sockets can only connect once, but
+ * connection-less sockets can connect multiple times to change the
+ * default address.
  *
  * If the connect call needs to do network I/O it will block, unless
  * non-blocking I/O is enabled. Then %G_IO_ERROR_PENDING is returned
  * and the user can be notified of the connection finishing by waiting
  * for the G_IO_OUT condition. The result of the connection can then be
- * checked with g_socket_check_pending_error().
+ * checked with g_socket_check_connect_result().
  *
  * Returns: %TRUE if connected, %FALSE on error.
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_connect (GSocket         *socket,
                  GSocketAddress  *address,
+                 GCancellable    *cancellable,
                  GError         **error)
 {
-  gchar buffer[256];
+  struct sockaddr_storage buffer;
 
   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
 
   if (!check_socket (socket, error))
     return FALSE;
 
-  g_socket_address_to_native (address, buffer, sizeof buffer);
+  if (!g_socket_address_to_native (address, &buffer, sizeof buffer, error))
+    return FALSE;
+
+  if (socket->priv->remote_address)
+    g_object_unref (socket->priv->remote_address);
+  socket->priv->remote_address = g_object_ref (address);
 
   while (1)
     {
-      if (socket->priv->blocking &&
-         !g_socket_condition_wait (socket,
-                                   G_IO_IN, NULL, error))
-       return FALSE;
-
-      if (connect (socket->priv->fd, (struct sockaddr *) buffer,
+      if (connect (socket->priv->fd, (struct sockaddr *) &buffer,
                   g_socket_address_get_native_size (address)) < 0)
        {
          int errsv = get_socket_errno ();
@@ -1450,20 +1649,24 @@ g_socket_connect (GSocket         *socket,
 #ifndef G_OS_WIN32
          if (errsv == EINPROGRESS)
 #else
-         if (errsv == WSAEINPROGRESS)
+         if (errsv == WSAEWOULDBLOCK)
 #endif
            {
              if (socket->priv->blocking)
                {
-                 g_socket_condition_wait (socket, G_IO_OUT, NULL, NULL);
-                 if (g_socket_check_pending_error (socket, error))
-                   break;
-                 else
-                   g_prefix_error (error, _("Error connecting: "));
+                 if (g_socket_condition_wait (socket, G_IO_OUT, cancellable, error))
+                   {
+                     if (g_socket_check_connect_result (socket, error))
+                       break;
+                   }
+                 g_prefix_error (error, _("Error connecting: "));
                }
              else
-               g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
-                            _("Connection in progress"));
+                {
+                  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
+                                       _("Connection in progress"));
+                  socket->priv->connect_pending = TRUE;
+                }
            }
          else
            g_set_error (error, G_IO_ERROR,
@@ -1477,30 +1680,34 @@ g_socket_connect (GSocket         *socket,
 
   win32_unset_event_mask (socket, FD_CONNECT);
 
-  socket->priv->remote_address = g_object_ref (address);
+  socket->priv->connected = TRUE;
 
   return TRUE;
 }
 
 /**
- * g_socket_check_pending_error:
+ * g_socket_check_connect_result:
  * @socket: a #GSocket
  * @error: #GError for error reporting, or %NULL to ignore.
  *
- * Checks and resets the pending error for the socket. This is typically
- * used to check for errors when g_socket_connect() is used in non-blocking mode.
+ * Checks and resets the pending connect error for the socket.
+ * This is used to check for errors when g_socket_connect() is
+ * used in non-blocking mode.
  *
  * Returns: %TRUE if no error, %FALSE otherwise, setting @error to the error
  *
  * Since: 2.22
- **/
+ */
 gboolean
-g_socket_check_pending_error (GSocket  *socket,
-                             GError  **error)
+g_socket_check_connect_result (GSocket  *socket,
+                              GError  **error)
 {
   guint optlen;
   int value;
 
+  if (!check_socket (socket, error))
+    return FALSE;
+
   optlen = sizeof (value);
   if (getsockopt (socket->priv->fd, SOL_SOCKET, SO_ERROR, (void *)&value, &optlen) != 0)
     {
@@ -1513,8 +1720,13 @@ g_socket_check_pending_error (GSocket  *socket,
 
   if (value != 0)
     {
-      g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (value),
-                  "%s", socket_strerror (value));
+      g_set_error_literal (error, G_IO_ERROR, socket_io_error_from_errno (value),
+                           socket_strerror (value));
+      if (socket->priv->remote_address)
+        {
+          g_object_unref (socket->priv->remote_address);
+          socket->priv->remote_address = NULL;
+        }
       return FALSE;
     }
   return TRUE;
@@ -1523,35 +1735,77 @@ g_socket_check_pending_error (GSocket  *socket,
 /**
  * g_socket_receive:
  * @socket: a #GSocket
- * @buffer: a buffer to read data into (which should be at least count bytes long).
- * @size: the number of bytes that will be read from the stream
+ * @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: (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
- * connection oriented sockets, it is identical to g_socket_receive_from()
+ * connection-oriented sockets; it is identical to g_socket_receive_from()
  * with @address set to %NULL.
  *
- * If a message is too long to fit in @buffer, excess bytes may be discarded
- * depending on the type of socket the message is received from.
+ * For %G_SOCKET_TYPE_DATAGRAM and %G_SOCKET_TYPE_SEQPACKET sockets,
+ * g_socket_receive() will always read either 0 or 1 complete messages from
+ * the socket. If the received message is too large to fit in @buffer, then
+ * the data beyond @size bytes will be discarded, without any explicit
+ * indication that this has occurred.
+ *
+ * For %G_SOCKET_TYPE_STREAM sockets, g_socket_receive() can return any
+ * number of bytes, up to @size. If more than @size bytes have been
+ * 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 of available data, wait for the %G_IO_IN
- * condition.
+ * 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
  *
  * Since: 2.22
- **/
+ */
 gssize
 g_socket_receive (GSocket       *socket,
                  gchar         *buffer,
                  gsize          size,
+                 GCancellable  *cancellable,
                  GError       **error)
 {
+  return g_socket_receive_with_blocking (socket, buffer, size,
+                                        socket->priv->blocking,
+                                        cancellable, error);
+}
+
+/**
+ * g_socket_receive_with_blocking:
+ * @socket: a #GSocket
+ * @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
+ * @blocking: whether to do blocking or non-blocking I/O
+ * @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
+ *
+ * Since: 2.26
+ */
+gssize
+g_socket_receive_with_blocking (GSocket       *socket,
+                               gchar         *buffer,
+                               gsize          size,
+                               gboolean       blocking,
+                               GCancellable  *cancellable,
+                               GError       **error)
+{
   gssize ret;
 
   g_return_val_if_fail (G_IS_SOCKET (socket) && buffer != NULL, FALSE);
@@ -1559,11 +1813,14 @@ g_socket_receive (GSocket       *socket,
   if (!check_socket (socket, error))
     return -1;
 
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return -1;
+
   while (1)
     {
-      if (socket->priv->blocking &&
+      if (blocking &&
          !g_socket_condition_wait (socket,
-                                   G_IO_IN, NULL, error))
+                                   G_IO_IN, cancellable, error))
        return -1;
 
       if ((ret = recv (socket->priv->fd, buffer, size, 0)) < 0)
@@ -1573,7 +1830,7 @@ g_socket_receive (GSocket       *socket,
          if (errsv == EINTR)
            continue;
 
-         if (socket->priv->blocking)
+         if (blocking)
            {
 #ifdef WSAEWOULDBLOCK
              if (errsv == WSAEWOULDBLOCK)
@@ -1605,8 +1862,10 @@ g_socket_receive (GSocket       *socket,
  * g_socket_receive_from:
  * @socket: a #GSocket
  * @address: a pointer to a #GSocketAddress pointer, or %NULL
- * @buffer: a buffer to read data into (which should be at least count bytes long).
- * @size: the number of bytes that will be read from the stream
+ * @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: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Receive data (up to @size bytes) from a socket.
@@ -1615,24 +1874,19 @@ g_socket_receive (GSocket       *socket,
  * source address of the received packet.
  * @address is owned by the caller.
  *
- * 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 of available data, wait for the %G_IO_IN
- * condition.
- *
- * On error -1 is returned and @error is set accordingly.
+ * See g_socket_receive() for additional information.
  *
  * Returns: Number of bytes read, or -1 on error
  *
  * Since: 2.22
- **/
+ */
 gssize
-g_socket_receive_from (GSocket       *socket,
-                      GSocketAddress  **address,
-                      gchar         *buffer,
-                      gsize          size,
-                      GError       **error)
+g_socket_receive_from (GSocket         *socket,
+                      GSocketAddress **address,
+                      gchar           *buffer,
+                      gsize            size,
+                      GCancellable    *cancellable,
+                      GError         **error)
 {
   GInputVector v;
 
@@ -1643,42 +1897,85 @@ g_socket_receive_from (GSocket       *socket,
                                   address,
                                   &v, 1,
                                   NULL, 0, NULL,
+                                  cancellable,
                                   error);
 }
 
+/* Although we ignore SIGPIPE, gdb will still stop if the app receives
+ * one, which can be confusing and annoying. So if possible, we want
+ * to suppress the signal entirely.
+ */
+#ifdef MSG_NOSIGNAL
+#define G_SOCKET_DEFAULT_SEND_FLAGS MSG_NOSIGNAL
+#else
+#define G_SOCKET_DEFAULT_SEND_FLAGS 0
+#endif
+
 /**
  * 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: (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 mainly used by
- * connection oriented sockets, it is identical to g_socket_send_to()
- * with @address set to %NULL.
+ * Tries to send @size bytes from @buffer on the socket. This is
+ * mainly used by connection-oriented sockets; it is identical to
+ * g_socket_send_to() with @address set to %NULL.
  *
  * If the socket is in blocking mode the call will block until there is
  * space for the data in the socket queue. If there is no space available
  * and the socket is in non-blocking mode a %G_IO_ERROR_WOULD_BLOCK error
- * will be returned. To be notified of available space, wait for the %G_IO_OUT
- * condition.
- *
- * Note that on Windows you can't rely on a %G_IO_OUT condition
- * not producing a %G_IO_ERROR_WOULD_BLOCK error, as this is how Winsock
- * write notification works. However, robust apps should always be able to
- * handle this since it can easily appear in other cases too.
+ * will be returned. To be notified when space is available, wait for the
+ * %G_IO_OUT condition. Note though that you may still receive
+ * %G_IO_ERROR_WOULD_BLOCK from g_socket_send() even if you were previously
+ * notified of a %G_IO_OUT condition. (On Windows in particular, this is
+ * very common due to the way the underlying APIs work.)
  *
  * On error -1 is returned and @error is set accordingly.
  *
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes written (which may be less than @size), or -1
+ * on error
  *
  * Since: 2.22
- **/
+ */
+gssize
+g_socket_send (GSocket       *socket,
+              const gchar   *buffer,
+              gsize          size,
+              GCancellable  *cancellable,
+              GError       **error)
+{
+  return g_socket_send_with_blocking (socket, buffer, size,
+                                     socket->priv->blocking,
+                                     cancellable, error);
+}
+
+/**
+ * g_socket_send_with_blocking:
+ * @socket: a #GSocket
+ * @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: (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
+ * the choice of blocking or non-blocking behavior is determined by
+ * the @blocking argument rather than by @socket's properties.
+ *
+ * Returns: Number of bytes written (which may be less than @size), or -1
+ * on error
+ *
+ * Since: 2.26
+ */
 gssize
-g_socket_send (GSocket      *socket,
-              const gchar  *buffer,
-              gsize         size,
-              GError      **error)
+g_socket_send_with_blocking (GSocket       *socket,
+                            const gchar   *buffer,
+                            gsize          size,
+                            gboolean       blocking,
+                            GCancellable  *cancellable,
+                            GError       **error)
 {
   gssize ret;
 
@@ -1687,14 +1984,17 @@ g_socket_send (GSocket      *socket,
   if (!check_socket (socket, error))
     return -1;
 
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return -1;
+
   while (1)
     {
-      if (socket->priv->blocking &&
+      if (blocking &&
          !g_socket_condition_wait (socket,
-                                   G_IO_OUT, NULL, error))
+                                   G_IO_OUT, cancellable, error))
        return -1;
 
-      if ((ret = send (socket->priv->fd, buffer, size, 0)) < 0)
+      if ((ret = send (socket->priv->fd, buffer, size, G_SOCKET_DEFAULT_SEND_FLAGS)) < 0)
        {
          int errsv = get_socket_errno ();
 
@@ -1706,7 +2006,7 @@ g_socket_send (GSocket      *socket,
            win32_unset_event_mask (socket, FD_WRITE);
 #endif
 
-         if (socket->priv->blocking)
+         if (blocking)
            {
 #ifdef WSAEWOULDBLOCK
              if (errsv == WSAEWOULDBLOCK)
@@ -1733,37 +2033,29 @@ g_socket_send (GSocket      *socket,
  * 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: (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
  * %NULL then the message is sent to the default receiver (set by
  * g_socket_connect()).
  *
- * If the socket is in blocking mode the call will block until there is
- * space for the data in the socket queue. If there is no space available
- * and the socket is in non-blocking mode a %G_IO_ERROR_WOULD_BLOCK error
- * will be returned. To be notified of available space, wait for the %G_IO_OUT
- * condition.
- *
- * Note that on Windows you can't rely on a %G_IO_OUT condition
- * not producing a %G_IO_ERROR_WOULD_BLOCK error, as this is how Winsock
- * write notification works. However, robust apps should always be able to
- * handle this since it can easily appear in other cases too.
+ * See g_socket_send() for additional information.
  *
- * On error -1 is returned and @error is set accordingly.
- *
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes written (which may be less than @size), or -1
+ * on error
  *
  * Since: 2.22
- **/
+ */
 gssize
-g_socket_send_to (GSocket      *socket,
-                 GSocketAddress *address,
-                 const gchar  *buffer,
-                 gsize         size,
-                 GError      **error)
+g_socket_send_to (GSocket         *socket,
+                 GSocketAddress  *address,
+                 const gchar     *buffer,
+                 gsize            size,
+                 GCancellable    *cancellable,
+                 GError         **error)
 {
   GOutputVector v;
 
@@ -1774,7 +2066,81 @@ g_socket_send_to (GSocket      *socket,
                                address,
                                &v, 1,
                                NULL, 0,
-                               0, error);
+                               0,
+                               cancellable,
+                               error);
+}
+
+/**
+ * g_socket_shutdown:
+ * @socket: a #GSocket
+ * @shutdown_read: whether to shut down the read side
+ * @shutdown_write: whether to shut down the write side
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Shut down part of a full-duplex connection.
+ *
+ * If @shutdown_read is %TRUE then the recieving side of the connection
+ * is shut down, and further reading is disallowed.
+ *
+ * If @shutdown_write is %TRUE then the sending side of the connection
+ * is shut down, and further writing is disallowed.
+ *
+ * It is allowed for both @shutdown_read and @shutdown_write to be %TRUE.
+ *
+ * One example where this is used is graceful disconnect for TCP connections
+ * where you close the sending side, then wait for the other side to close
+ * the connection, thus ensuring that the other side saw all sent data.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.22
+ */
+gboolean
+g_socket_shutdown (GSocket   *socket,
+                  gboolean   shutdown_read,
+                  gboolean   shutdown_write,
+                  GError   **error)
+{
+  int how;
+
+  g_return_val_if_fail (G_IS_SOCKET (socket), TRUE);
+
+  if (!check_socket (socket, NULL))
+    return FALSE;
+
+  /* Do nothing? */
+  if (!shutdown_read && !shutdown_write)
+    return TRUE;
+
+#ifndef G_OS_WIN32
+  if (shutdown_read && shutdown_write)
+    how = SHUT_RDWR;
+  else if (shutdown_read)
+    how = SHUT_RD;
+  else
+    how = SHUT_WR;
+#else
+  if (shutdown_read && shutdown_write)
+    how = SD_BOTH;
+  else if (shutdown_read)
+    how = SD_RECEIVE;
+  else
+    how = SD_SEND;
+#endif
+
+  if (shutdown (socket->priv->fd, how) != 0)
+    {
+      int errsv = get_socket_errno ();
+      g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
+                  _("Unable to create socket: %s"), socket_strerror (errsv));
+      return FALSE;
+    }
+
+  if (shutdown_read && shutdown_write)
+    socket->priv->connected = FALSE;
+
+  return TRUE;
 }
 
 /**
@@ -1784,24 +2150,41 @@ g_socket_send_to (GSocket      *socket,
  *
  * Closes the socket, shutting down any active connection.
  *
- * Closing a socket does not wait for all outstanding I/O operations to finish,
- * so the caller should not rely on them to be guaranteed to complete even
- * if the close returns with no error.
+ * Closing a socket does not wait for all outstanding I/O operations
+ * to finish, so the caller should not rely on them to be guaranteed
+ * to complete even if the close returns with no error.
  *
- * Once the socket is closed, all other operations will return %G_IO_ERROR_CLOSED.
- * Closing a stream multiple times will not return an error.
+ * Once the socket is closed, all other operations will return
+ * %G_IO_ERROR_CLOSED. Closing a socket multiple times will not
+ * return an error.
  *
  * Sockets will be automatically closed when the last reference
  * is dropped, but you might want to call this function to make sure
  * resources are released as early as possible.
  *
+ * Beware that due to the way that TCP works, it is possible for
+ * recently-sent data to be lost if either you close a socket while the
+ * %G_IO_IN condition is set, or else if the remote connection tries to
+ * send something to you after you close the socket but before it has
+ * finished reading all of the data you sent. There is no easy generic
+ * way to avoid this problem; the easiest fix is to design the network
+ * protocol such that the client will never send data "out of turn".
+ * Another solution is for the server to half-close the connection by
+ * calling g_socket_shutdown() with only the @shutdown_write flag set,
+ * and then wait for the client to notice this and close its side of the
+ * connection, after which the server can safely call g_socket_close().
+ * (This is what #GTcpConnection does if you call
+ * g_tcp_connection_set_graceful_disconnect(). But of course, this
+ * only works if the client will close its connection after the server
+ * does.)
+ *
  * Returns: %TRUE on success, %FALSE on error
  *
  * Since: 2.22
- **/
+ */
 gboolean
-g_socket_close (GSocket *socket,
-               GError **error)
+g_socket_close (GSocket  *socket,
+               GError  **error)
 {
   int res;
 
@@ -1836,15 +2219,13 @@ g_socket_close (GSocket *socket,
       break;
     }
 
-#ifdef G_OS_WIN32
-  if (socket->priv->event != WSA_INVALID_EVENT)
+  socket->priv->connected = FALSE;
+  socket->priv->closed = TRUE;
+  if (socket->priv->remote_address)
     {
-      WSACloseEvent (socket->priv->event);
-      socket->priv->event = WSA_INVALID_EVENT;
+      g_object_unref (socket->priv->remote_address);
+      socket->priv->remote_address = NULL;
     }
-#endif
-
-  socket->priv->closed = TRUE;
 
   return TRUE;
 }
@@ -1858,7 +2239,7 @@ g_socket_close (GSocket *socket,
  * Returns: %TRUE if socket is closed, %FALSE otherwise
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_is_closed (GSocket *socket)
 {
@@ -1868,22 +2249,22 @@ g_socket_is_closed (GSocket *socket)
 #ifdef G_OS_WIN32
 /* Broken source, used on errors */
 static gboolean
-broken_prepare  (GSource  *source,
-                gint     *timeout)
+broken_prepare  (GSource *source,
+                gint    *timeout)
 {
   return FALSE;
 }
 
 static gboolean
-broken_check    (GSource  *source)
+broken_check (GSource *source)
 {
   return FALSE;
 }
 
 static gboolean
-broken_dispatch (GSource    *source,
-                GSourceFunc callback,
-                gpointer    user_data)
+broken_dispatch (GSource     *source,
+                GSourceFunc  callback,
+                gpointer     user_data)
 {
   return TRUE;
 }
@@ -1950,7 +2331,7 @@ update_select_events (GSocket *socket)
 }
 
 static void
-add_condition_watch (GSocket *socket,
+add_condition_watch (GSocket      *socket,
                     GIOCondition *condition)
 {
   g_assert (g_list_find (socket->priv->requested_conditions, condition) == NULL);
@@ -1962,7 +2343,7 @@ add_condition_watch (GSocket *socket,
 }
 
 static void
-remove_condition_watch (GSocket *socket,
+remove_condition_watch (GSocket      *socket,
                        GIOCondition *condition)
 {
   g_assert (g_list_find (socket->priv->requested_conditions, condition) != NULL);
@@ -2023,6 +2404,7 @@ update_condition (GSocket *socket)
 
   return condition;
 }
+#endif
 
 typedef struct {
   GSource       source;
@@ -2031,99 +2413,139 @@ typedef struct {
   GIOCondition  condition;
   GCancellable *cancellable;
   GPollFD       cancel_pollfd;
-  GIOCondition  result_condition;
-} GWinsockSource;
+  gint64        timeout_time;
+} GSocketSource;
 
 static gboolean
-winsock_prepare (GSource  *source,
-                gint     *timeout)
+socket_source_prepare (GSource *source,
+                      gint    *timeout)
 {
-  GWinsockSource *winsock_source = (GWinsockSource *)source;
-  GIOCondition current_condition;
+  GSocketSource *socket_source = (GSocketSource *)source;
 
-  current_condition = update_condition (winsock_source->socket);
+  if (g_cancellable_is_cancelled (socket_source->cancellable))
+    return TRUE;
 
-  if (g_cancellable_is_cancelled (winsock_source->cancellable))
+  if (socket_source->timeout_time)
     {
-      winsock_source->result_condition = current_condition;
-      return TRUE;
+      gint64 now;
+
+      now = g_source_get_time (source);
+      /* Round up to ensure that we don't try again too early */
+      *timeout = (socket_source->timeout_time - now + 999) / 1000;
+      if (*timeout < 0)
+        {
+          socket_source->socket->priv->timed_out = TRUE;
+          socket_source->pollfd.revents = socket_source->condition & (G_IO_IN | G_IO_OUT);
+          *timeout = 0;
+          return TRUE;
+        }
     }
+  else
+    *timeout = -1;
 
-  if ((winsock_source->condition & current_condition) != 0)
-    {
-      winsock_source->result_condition = current_condition;
-      return TRUE;
-    }
+#ifdef G_OS_WIN32
+  socket_source->pollfd.revents = update_condition (socket_source->socket);
+#endif
+
+  if ((socket_source->condition & socket_source->pollfd.revents) != 0)
+    return TRUE;
 
   return FALSE;
 }
 
 static gboolean
-winsock_check (GSource  *source)
+socket_source_check (GSource *source)
 {
-  GWinsockSource *winsock_source = (GWinsockSource *)source;
-  GIOCondition current_condition;
-
-  current_condition = update_condition (winsock_source->socket);
+  int timeout;
 
-  if (g_cancellable_is_cancelled (winsock_source->cancellable))
-    {
-      winsock_source->result_condition = current_condition;
-      return TRUE;
-    }
-
-  if ((winsock_source->condition & current_condition) != 0)
-    {
-      winsock_source->result_condition = current_condition;
-      return TRUE;
-    }
-
-  return FALSE;
+  return socket_source_prepare (source, &timeout);
 }
 
 static gboolean
-winsock_dispatch (GSource    *source,
-                 GSourceFunc callback,
-                 gpointer    user_data)
+socket_source_dispatch (GSource     *source,
+                       GSourceFunc  callback,
+                       gpointer     user_data)
 {
   GSocketSourceFunc func = (GSocketSourceFunc)callback;
-  GWinsockSource *winsock_source = (GWinsockSource *)source;
+  GSocketSource *socket_source = (GSocketSource *)source;
 
-  return (*func) (user_data,
-                 winsock_source->result_condition & winsock_source->condition);
+#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 void
-winsock_finalize (GSource *source)
+socket_source_finalize (GSource *source)
 {
-  GWinsockSource *winsock_source = (GWinsockSource *)source;
+  GSocketSource *socket_source = (GSocketSource *)source;
   GSocket *socket;
 
-  socket = winsock_source->socket;
+  socket = socket_source->socket;
+
+#ifdef G_OS_WIN32
+  remove_condition_watch (socket, &socket_source->condition);
+#endif
 
-  remove_condition_watch (socket, &winsock_source->condition);
   g_object_unref (socket);
 
-  if (winsock_source->cancellable)
-    g_object_unref (winsock_source->cancellable);
+  if (socket_source->cancellable)
+    {
+      g_cancellable_release_fd (socket_source->cancellable);
+      g_object_unref (socket_source->cancellable);
+    }
 }
 
-static GSourceFuncs winsock_funcs =
+static gboolean
+socket_source_closure_callback (GSocket      *socket,
+                               GIOCondition  condition,
+                               gpointer      data)
 {
-  winsock_prepare,
-  winsock_check,
-  winsock_dispatch,
-  winsock_finalize
+  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 (&params[0], G_TYPE_SOCKET);
+  g_value_set_object (&params[0], socket);
+  g_value_init (&params[1], G_TYPE_IO_CONDITION);
+  g_value_set_flags (&params[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 (&params[0]);
+  g_value_unset (&params[1]);
+
+  return result;
+}
+
+static GSourceFuncs socket_source_funcs =
+{
+  socket_source_prepare,
+  socket_source_check,
+  socket_source_dispatch,
+  socket_source_finalize,
+  (GSourceFunc)socket_source_closure_callback,
+  (GSourceDummyMarshal)_gio_marshal_BOOLEAN__FLAGS,
 };
 
 static GSource *
-winsock_source_new (GSocket      *socket,
-                   GIOCondition  condition,
-                   GCancellable *cancellable)
+socket_source_new (GSocket      *socket,
+                  GIOCondition  condition,
+                  GCancellable *cancellable)
 {
   GSource *source;
-  GWinsockSource *winsock_source;
+  GSocketSource *socket_source;
 
+#ifdef G_OS_WIN32
   ensure_event (socket);
 
   if (socket->priv->event == WSA_INVALID_EVENT)
@@ -2131,68 +2553,83 @@ winsock_source_new (GSocket      *socket,
       g_warning ("Failed to create WSAEvent");
       return g_source_new (&broken_funcs, sizeof (GSource));
     }
+#endif
 
   condition |= G_IO_HUP | G_IO_ERR;
 
-  source = g_source_new (&winsock_funcs, sizeof (GWinsockSource));
-  winsock_source = (GWinsockSource *)source;
+  source = g_source_new (&socket_source_funcs, sizeof (GSocketSource));
+  g_source_set_name (source, "GSocket");
+  socket_source = (GSocketSource *)source;
 
-  winsock_source->socket = g_object_ref (socket);
-  winsock_source->condition = condition;
-  add_condition_watch (socket, &winsock_source->condition);
+  socket_source->socket = g_object_ref (socket);
+  socket_source->condition = condition;
 
-  if (cancellable)
+  if (g_cancellable_make_pollfd (cancellable,
+                                 &socket_source->cancel_pollfd))
     {
-      winsock_source->cancellable = g_object_ref (cancellable);
-      g_cancellable_make_pollfd (cancellable,
-                                &winsock_source->cancel_pollfd);
-      g_source_add_poll (source, &winsock_source->cancel_pollfd);
+      socket_source->cancellable = g_object_ref (cancellable);
+      g_source_add_poll (source, &socket_source->cancel_pollfd);
     }
 
-  winsock_source->pollfd.fd = (gintptr) socket->priv->event;
-  winsock_source->pollfd.events = condition;
-  g_source_add_poll (source, &winsock_source->pollfd);
+#ifdef G_OS_WIN32
+  add_condition_watch (socket, &socket_source->condition);
+  socket_source->pollfd.fd = (gintptr) socket->priv->event;
+#else
+  socket_source->pollfd.fd = socket->priv->fd;
+#endif
+
+  socket_source->pollfd.events = condition;
+  socket_source->pollfd.revents = 0;
+  g_source_add_poll (source, &socket_source->pollfd);
+
+  if (socket->priv->timeout)
+    socket_source->timeout_time = g_get_monotonic_time () +
+                                  socket->priv->timeout * 1000000;
+
+  else
+    socket_source->timeout_time = 0;
 
   return source;
 }
-#endif
 
 /**
- * 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.
  *
  * The callback on the source is of the #GSocketSourceFunc type.
  *
- * It is meaningless to specify %G_IO_ERR or %G_IO_HUP in condition;
+ * It is meaningless to specify %G_IO_ERR or %G_IO_HUP in @condition;
  * these conditions will always be reported output if they are true.
  *
  * @cancellable if not %NULL can be used to cancel the source, which will
- * cause the source to trigger, reporting the current condition. You can
- * check for this in the callback using g_cancellable_is_cancelled().
+ * cause the source to trigger, reporting the current condition (which
+ * is likely 0 unless cancellation happened at the same time as a
+ * condition change). You can check for this in the callback using
+ * g_cancellable_is_cancelled().
+ *
+ * If @socket has a timeout set, and it is reached before @condition
+ * occurs, the source will then trigger anyway, reporting %G_IO_IN or
+ * %G_IO_OUT depending on @condition. However, @socket will have been
+ * marked as having had a timeout, and so the next #GSocket I/O method
+ * you call will then fail with a %G_IO_ERROR_TIMED_OUT.
  *
- * Returns: a newly allocated %GSource, free with g_source_unref().
+ * Returns: (transfer full): a newly allocated %GSource, free with g_source_unref().
  *
  * Since: 2.22
- **/
+ */
 GSource *
 g_socket_create_source (GSocket      *socket,
                        GIOCondition  condition,
                        GCancellable *cancellable)
 {
-  GSource *source;
   g_return_val_if_fail (G_IS_SOCKET (socket) && (cancellable == NULL || G_IS_CANCELLABLE (cancellable)), NULL);
 
-#ifdef G_OS_WIN32
-  source = winsock_source_new (socket, condition, cancellable);
-#else
-  source =_g_fd_source_new (socket->priv->fd, condition, cancellable);
-#endif
-  return source;
+  return socket_source_new (socket, condition, cancellable);
 }
 
 /**
@@ -2200,11 +2637,19 @@ g_socket_create_source (GSocket      *socket,
  * @socket: a #GSocket
  * @condition: a #GIOCondition mask to check
  *
- * Checks on the readiness of @socket to perform operations.  The
- * operations specified in @condition are checked for and masked
- * against the currently-satisfied conditions on @socket.  The result
+ * Checks on the readiness of @socket to perform operations.
+ * The operations specified in @condition are checked for and masked
+ * against the currently-satisfied conditions on @socket. The result
  * is returned.
  *
+ * Note that on Windows, it is possible for an operation to return
+ * %G_IO_ERROR_WOULD_BLOCK even immediately after
+ * g_socket_condition_check() has claimed that the socket is ready for
+ * writing. Rather than calling g_socket_condition_check() and then
+ * writing to the socket if it succeeds, it is generally better to
+ * simply try writing to the socket right away, and try again later if
+ * the initial attempt returns %G_IO_ERROR_WOULD_BLOCK.
+ *
  * It is meaningless to specify %G_IO_ERR or %G_IO_HUP in condition;
  * these conditions will always be set in the output if they are true.
  *
@@ -2213,10 +2658,10 @@ g_socket_create_source (GSocket      *socket,
  * Returns: the @GIOCondition mask of the current state
  *
  * Since: 2.22
- **/
+ */
 GIOCondition
-g_socket_condition_check (GSocket       *socket,
-                         GIOCondition   condition)
+g_socket_condition_check (GSocket      *socket,
+                         GIOCondition  condition)
 {
   if (!check_socket (socket, NULL))
     return 0;
@@ -2252,19 +2697,22 @@ g_socket_condition_check (GSocket       *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
- * becomes true, %TRUE is returned.
+ * Waits for @condition to become true on @socket. When the condition
+ * is met, %TRUE is returned.
  *
- * If @cancellable is cancelled before the condition becomes true then
- * %FALSE is returned and @error, if non-%NULL, is set to %G_IO_ERROR_CANCELLED.
+ * If @cancellable is cancelled before the condition is met, or if the
+ * socket has a timeout set and it is reached before the condition is
+ * met, then %FALSE is returned and @error, if non-%NULL, is set to
+ * the appropriate value (%G_IO_ERROR_CANCELLED or
+ * %G_IO_ERROR_TIMED_OUT).
  *
  * Returns: %TRUE if the condition was met, %FALSE otherwise
  *
  * Since: 2.22
- **/
+ */
 gboolean
 g_socket_condition_wait (GSocket       *socket,
                         GIOCondition   condition,
@@ -2281,7 +2729,7 @@ g_socket_condition_wait (GSocket       *socket,
   {
     GIOCondition current_condition;
     WSAEVENT events[2];
-    DWORD res;
+    DWORD res, timeout;
     GPollFD cancel_fd;
     int num_events;
 
@@ -2293,17 +2741,19 @@ g_socket_condition_wait (GSocket       *socket,
     num_events = 0;
     events[num_events++] = socket->priv->event;
 
-    if (cancellable)
-      {
-       g_cancellable_make_pollfd (cancellable, &cancel_fd);
-       events[num_events++] = (WSAEVENT)cancel_fd.fd;
-      }
+    if (g_cancellable_make_pollfd (cancellable, &cancel_fd))
+      events[num_events++] = (WSAEVENT)cancel_fd.fd;
+
+    if (socket->priv->timeout)
+      timeout = socket->priv->timeout * 1000;
+    else
+      timeout = WSA_INFINITE;
 
     current_condition = update_condition (socket);
     while ((condition & current_condition) == 0)
       {
        res = WSAWaitForMultipleEvents(num_events, events,
-                                      FALSE, WSA_INFINITE, FALSE);
+                                      FALSE, timeout, FALSE);
        if (res == WSA_WAIT_FAILED)
          {
            int errsv = get_socket_errno ();
@@ -2314,6 +2764,12 @@ g_socket_condition_wait (GSocket       *socket,
                         socket_strerror (errsv));
            break;
          }
+       else if (res == WSA_WAIT_TIMEOUT)
+         {
+           g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+                                _("Socket I/O timed out"));
+           break;
+         }
 
        if (g_cancellable_set_error_if_cancelled (cancellable, error))
          break;
@@ -2321,6 +2777,8 @@ g_socket_condition_wait (GSocket       *socket,
        current_condition = update_condition (socket);
       }
     remove_condition_watch (socket, &condition);
+    if (num_events > 1)
+      g_cancellable_release_fd (cancellable);
 
     return (condition & current_condition) != 0;
   }
@@ -2329,37 +2787,50 @@ g_socket_condition_wait (GSocket       *socket,
     GPollFD poll_fd[2];
     gint result;
     gint num;
+    gint timeout;
 
     poll_fd[0].fd = socket->priv->fd;
     poll_fd[0].events = condition;
     num = 1;
 
-    if (cancellable)
-      {
-       g_cancellable_make_pollfd (cancellable, &poll_fd[1]);
-       num++;
-      }
+    if (g_cancellable_make_pollfd (cancellable, &poll_fd[1]))
+      num++;
+
+    if (socket->priv->timeout)
+      timeout = socket->priv->timeout * 1000;
+    else
+      timeout = -1;
 
     do
-      result = g_poll (poll_fd, num, -1);
+      result = g_poll (poll_fd, num, timeout);
     while (result == -1 && get_socket_errno () == EINTR);
+    
+    if (num > 1)
+      g_cancellable_release_fd (cancellable);
+
+    if (result == 0)
+      {
+       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+                            _("Socket I/O timed out"));
+       return FALSE;
+      }
 
-    return cancellable == NULL ||
-      !g_cancellable_set_error_if_cancelled (cancellable, error);
+    return !g_cancellable_set_error_if_cancelled (cancellable, error);
   }
   #endif
 }
 
 /**
- * g_socket_send_to:
+ * 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: (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
@@ -2369,12 +2840,14 @@ g_socket_condition_wait (GSocket       *socket,
  * If @address is %NULL then the message is sent to the default receiver
  * (set by g_socket_connect()).
  *
- * @vector must point to an array of #GOutputVector structs and
- * @num_vectors must be the length of this array.  These structs
- * describe the buffers that the sent data will be gathered from.
- * If @num_vector is -1, then @vector is assumed to be terminated
- * by a #GOutputVector with a %NULL buffer pointer.
- *
+ * @vectors must point to an array of #GOutputVector structs and
+ * @num_vectors must be the length of this array. (If @num_vectors is -1,
+ * then @vectors is assumed to be terminated by a #GOutputVector with a
+ * %NULL buffer pointer.) The #GOutputVector structs describe the buffers
+ * that the sent data will be gathered from. Using multiple
+ * #GOutputVector<!-- -->s is more memory-efficient than manually copying
+ * data from multiple sources into a single buffer, and more
+ * network-efficient than making multiple calls to g_socket_send().
  *
  * @messages, if non-%NULL, is taken to point to an array of @num_messages
  * #GSocketControlMessage instances. These correspond to the control
@@ -2382,28 +2855,27 @@ g_socket_condition_wait (GSocket       *socket,
  * If @num_messages is -1 then @messages is treated as a %NULL-terminated
  * array.
  *
- * @flags modify how the message sent. The commonly available arguments
- * for this is available in the #GSocketMsgFlags enum, but the
+ * @flags modify how the message is sent. The commonly available arguments
+ * for this are available in the #GSocketMsgFlags enum, but the
  * values there are the same as the system values, and the flags
- * are passed in as-is, so you can pass in system specific flags too.
+ * are passed in as-is, so you can pass in system-specific flags too.
  *
  * If the socket is in blocking mode the call will block until there is
  * space for the data in the socket queue. If there is no space available
  * and the socket is in non-blocking mode a %G_IO_ERROR_WOULD_BLOCK error
- * will be returned. To be notified of available space, wait for the %G_IO_OUT
- * condition.
- *
- * Note that on Windows you can't rely on a %G_IO_OUT condition
- * not producing a %G_IO_ERROR_WOULD_BLOCK error, as this is how Winsock
- * write notification works. However, robust apps should always be able to
- * handle this since it can easily appear in other cases too.
+ * will be returned. To be notified when space is available, wait for the
+ * %G_IO_OUT condition. Note though that you may still receive
+ * %G_IO_ERROR_WOULD_BLOCK from g_socket_send() even if you were previously
+ * notified of a %G_IO_OUT condition. (On Windows in particular, this is
+ * very common due to the way the underlying APIs work.)
  *
  * On error -1 is returned and @error is set accordingly.
  *
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes written (which may be less than @size), or -1
+ * on error
  *
  * Since: 2.22
- **/
+ */
 gssize
 g_socket_send_message (GSocket                *socket,
                       GSocketAddress         *address,
@@ -2412,6 +2884,7 @@ g_socket_send_message (GSocket                *socket,
                       GSocketControlMessage **messages,
                       gint                    num_messages,
                       gint                    flags,
+                      GCancellable           *cancellable,
                       GError                **error)
 {
   GOutputVector one_vector;
@@ -2420,6 +2893,9 @@ g_socket_send_message (GSocket                *socket,
   if (!check_socket (socket, error))
     return -1;
 
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return -1;
+
   if (num_vectors == -1)
     {
       for (num_vectors = 0;
@@ -2451,12 +2927,20 @@ g_socket_send_message (GSocket                *socket,
     struct msghdr msg;
     gssize result;
 
+   msg.msg_flags = 0;
+
     /* name */
     if (address)
       {
        msg.msg_namelen = g_socket_address_get_native_size (address);
        msg.msg_name = g_alloca (msg.msg_namelen);
-       g_socket_address_to_native (address, msg.msg_name, msg.msg_namelen);
+       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 */
@@ -2498,7 +2982,13 @@ g_socket_send_message (GSocket                *socket,
       for (i = 0; i < num_messages; i++)
        msg.msg_controllen += CMSG_SPACE (g_socket_control_message_get_size (messages[i]));
 
-      msg.msg_control = g_alloca (msg.msg_controllen);
+      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++)
@@ -2517,10 +3007,10 @@ g_socket_send_message (GSocket                *socket,
       {
        if (socket->priv->blocking &&
            !g_socket_condition_wait (socket,
-                                     G_IO_OUT, NULL, error))
+                                     G_IO_OUT, cancellable, error))
          return -1;
 
-       result = sendmsg (socket->priv->fd, &msg, flags);
+       result = sendmsg (socket->priv->fd, &msg, flags | G_SOCKET_DEFAULT_SEND_FLAGS);
        if (result < 0)
          {
            int errsv = get_socket_errno ();
@@ -2559,8 +3049,8 @@ g_socket_send_message (GSocket                *socket,
        seem very useful */
     if (num_messages != 0)
       {
-       g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                    _("GSocketControlMessage not supported on windows"));
+        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                             _("GSocketControlMessage not supported on windows"));
        return -1;
       }
 
@@ -2573,17 +3063,19 @@ g_socket_send_message (GSocket                *socket,
       }
 
     /* name */
+    addrlen = 0; /* Avoid warning */
     if (address)
       {
        addrlen = g_socket_address_get_native_size (address);
-       g_socket_address_to_native (address, &addr, sizeof addr);
+       if (!g_socket_address_to_native (address, &addr, sizeof addr, error))
+         return -1;
       }
 
     while (1)
       {
        if (socket->priv->blocking &&
            !g_socket_condition_wait (socket,
-                                     G_IO_OUT, NULL, error))
+                                     G_IO_OUT, cancellable, error))
          return -1;
 
        if (address)
@@ -2630,13 +3122,14 @@ g_socket_send_message (GSocket                *socket,
  * 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 will 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: (allow-none): a %GCancellable or %NULL
  * @error: a #GError pointer, or %NULL
  *
  * Receive data from a socket.  This is the most complicated and
@@ -2650,21 +3143,22 @@ g_socket_send_message (GSocket                *socket,
  * @vector must point to an array of #GInputVector structs and
  * @num_vectors must be the length of this array.  These structs
  * describe the buffers that received data will be scattered into.
- * If @num_vector is -1, then @vector is assumed to be terminated
+ * If @num_vectors is -1, then @vectors is assumed to be terminated
  * by a #GInputVector with a %NULL buffer pointer.
  *
- * As a special case, if the size of the array is zero (in which case,
- * @vectors may of course be %NULL), then a single byte is received
- * and discarded.  This is to facilitate the common practice of
- * sending a single '\0' byte for the purposes of transferring
- * ancillary data.
+ * As a special case, if @num_vectors is 0 (in which case, @vectors
+ * may of course be %NULL), then a single byte is received and
+ * discarded. This is to facilitate the common practice of sending a
+ * single '\0' byte for the purposes of transferring ancillary data.
  *
- * @messages, if non-%NULL, is taken to point to a pointer that will
- * be set to point to a newly-allocated array of
- * #GSocketControlMessage instances.  These correspond to the control
- * messages received from the kernel, one #GSocketControlMessage per
- * message from the kernel.  This array is %NULL-terminated and must be
- * freed by the caller using g_free().
+ * @messages, if non-%NULL, will be set to point to a newly-allocated
+ * array of #GSocketControlMessage instances or %NULL if no such
+ * messages was received. These correspond to the control messages
+ * received from the kernel, one #GSocketControlMessage per message
+ * from the kernel. This array is %NULL-terminated and must be freed
+ * by the caller using g_free() after calling g_object_unref() on each
+ * element. If @messages is %NULL, any control messages received will
+ * be discarded.
  *
  * @num_messages, if non-%NULL, will be set to the number of control
  * messages received.
@@ -2674,22 +3168,31 @@ g_socket_send_message (GSocket                *socket,
  * in @messages (ie: not including the %NULL terminator).
  *
  * @flags is an in/out parameter. The commonly available arguments
- * for this is available in the #GSocketMsgFlags enum, but the
+ * for this are available in the #GSocketMsgFlags enum, but the
  * values there are the same as the system values, and the flags
- * are passed in as-is, so you can pass in system specific flags too.
- *
- * 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 of available data, wait for the %G_IO_IN
- * condition.
+ * are passed in as-is, so you can pass in system-specific flags too
+ * (and g_socket_receive_message() may pass system-specific flags out).
+ *
+ * As with g_socket_receive(), data may be discarded if @socket is
+ * %G_SOCKET_TYPE_DATAGRAM or %G_SOCKET_TYPE_SEQPACKET and you do not
+ * provide enough buffer space to read a complete message. You can pass
+ * %G_SOCKET_MSG_PEEK in @flags to peek at the current message without
+ * removing it from the receive queue, but there is no portable way to find
+ * out the length of the message other than by reading it into a
+ * 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.
  *
  * On error -1 is returned and @error is set accordingly.
  *
  * Returns: Number of bytes read, or -1 on error
  *
  * Since: 2.22
- **/
+ */
 gssize
 g_socket_receive_message (GSocket                 *socket,
                          GSocketAddress         **address,
@@ -2698,6 +3201,7 @@ g_socket_receive_message (GSocket                 *socket,
                          GSocketControlMessage ***messages,
                          gint                    *num_messages,
                          gint                    *flags,
+                         GCancellable            *cancellable,
                          GError                 **error)
 {
   GInputVector one_vector;
@@ -2706,6 +3210,9 @@ g_socket_receive_message (GSocket                 *socket,
   if (!check_socket (socket, error))
     return -1;
 
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return -1;
+
   if (num_vectors == -1)
     {
       for (num_vectors = 0;
@@ -2783,7 +3290,7 @@ g_socket_receive_message (GSocket                 *socket,
       {
        if (socket->priv->blocking &&
            !g_socket_condition_wait (socket,
-                                     G_IO_IN, NULL, error))
+                                     G_IO_IN, cancellable, error))
          return -1;
 
        result = recvmsg (socket->priv->fd, &msg, msg.msg_flags);
@@ -2821,14 +3328,8 @@ g_socket_receive_message (GSocket                 *socket,
 
     /* decode control messages */
     {
-      GSocketControlMessage **my_messages = NULL;
-      gint allocated = 0, index = 0;
-      const gchar *scm_pointer;
+      GPtrArray *my_messages = NULL;
       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))
        {
@@ -2843,36 +3344,39 @@ g_socket_receive_message (GSocket                 *socket,
               deserialization code, so just continue */
            continue;
 
-         if (index == allocated)
+         if (messages == NULL)
            {
-             /* estimated 99% case: exactly 1 control message */
-             allocated = MIN (allocated * 2, 1);
-             my_messages = g_new (GSocketControlMessage *, (allocated + 1));
-             allocated = 1;
+             /* 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);
            }
-
-         my_messages[index++] = message;
        }
 
       if (num_messages)
-       *num_messages = index;
+       *num_messages = my_messages != NULL ? my_messages->len : 0;
 
       if (messages)
        {
-         my_messages[index++] = NULL;
-         *messages = my_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
        {
-         gint i;
-
-         /* free all those messages we just constructed.
-          * we have to do it this way if the user ignores the
-          * messages so that we will close any received fds.
-          */
-         for (i = 0; i < index; i++)
-           g_object_unref (my_messages[i]);
-         g_free (my_messages);
+         g_assert (my_messages == NULL);
        }
     }
 
@@ -2911,7 +3415,7 @@ g_socket_receive_message (GSocket                 *socket,
       {
        if (socket->priv->blocking &&
            !g_socket_condition_wait (socket,
-                                     G_IO_IN, NULL, error))
+                                     G_IO_IN, cancellable, error))
          return -1;
 
        addrlen = sizeof addr;
@@ -2962,10 +3466,82 @@ g_socket_receive_message (GSocket                 *socket,
     if (flags != NULL)
       *flags = win_flags;
 
+    if (messages != NULL)
+      *messages = NULL;
+    if (num_messages != NULL)
+      *num_messages = 0;
+
     return bytes_received;
   }
 #endif
 }
 
-#define __G_SOCKET_C__
-#include "gioaliasdef.c"
+/**
+ * g_socket_get_credentials:
+ * @socket: a #GSocket.
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Returns the credentials of the foreign process connected to this
+ * socket, if any (e.g. it is only supported for %G_SOCKET_FAMILY_UNIX
+ * sockets).
+ *
+ * If this operation isn't supported on the OS, the method fails with
+ * the %G_IO_ERROR_NOT_SUPPORTED error. On Linux this is implemented
+ * by reading the %SO_PEERCRED option on the underlying socket.
+ *
+ * Other ways to obtain credentials from a foreign peer includes the
+ * #GUnixCredentialsMessage type and
+ * g_unix_connection_send_credentials() /
+ * g_unix_connection_receive_credentials() functions.
+ *
+ * Returns: (transfer full): %NULL if @error is set, otherwise a #GCredentials object
+ * that must be freed with g_object_unref().
+ *
+ * Since: 2.26
+ */
+GCredentials *
+g_socket_get_credentials (GSocket   *socket,
+                          GError   **error)
+{
+  GCredentials *ret;
+
+  g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  ret = NULL;
+
+#ifdef __linux__
+  {
+    struct ucred native_creds;
+    socklen_t optlen;
+    optlen = sizeof (struct ucred);
+    if (getsockopt (socket->priv->fd,
+                    SOL_SOCKET,
+                    SO_PEERCRED,
+                    (void *)&native_creds,
+                    &optlen) != 0)
+      {
+        int errsv = get_socket_errno ();
+        g_set_error (error,
+                     G_IO_ERROR,
+                     socket_io_error_from_errno (errsv),
+                     _("Unable to get pending error: %s"),
+                     socket_strerror (errsv));
+      }
+    else
+      {
+        ret = g_credentials_new ();
+        g_credentials_set_native (ret,
+                                  G_CREDENTIALS_TYPE_LINUX_UCRED,
+                                  &native_creds);
+      }
+  }
+#else
+  g_set_error_literal (error,
+                       G_IO_ERROR,
+                       G_IO_ERROR_NOT_SUPPORTED,
+                       _("g_socket_get_credentials not implemented for this OS"));
+#endif
+
+  return ret;
+}