1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-socket.c: Socket networking code.
5 * Copyright (C) 2000-2003, Ximian, Inc.
19 #include "soup-address.h"
20 #include "soup-socket.h"
21 #include "soup-marshal.h"
22 #include "soup-misc.h"
26 #include <sys/types.h>
30 * @short_description: A network socket
32 * #SoupSocket is libsoup's TCP socket type. While it is primarily
33 * intended for internal use, #SoupSocket<!-- -->s are exposed in the
34 * API in various places, and some of their methods (eg,
35 * soup_socket_get_remote_address()) may be useful to applications.
38 G_DEFINE_TYPE (SoupSocket, soup_socket, G_TYPE_OBJECT)
48 static guint signals[LAST_SIGNAL] = { 0 };
66 SoupAddress *local_addr, *remote_addr;
67 GIOChannel *iochannel;
73 GMainContext *async_context;
75 GSource *read_src, *write_src;
78 GMutex *iolock, *addrlock;
81 #define SOUP_SOCKET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SOCKET, SoupSocketPrivate))
84 #define soup_sockaddr_max sockaddr_in6
86 #define soup_sockaddr_max sockaddr_in
89 static void set_property (GObject *object, guint prop_id,
90 const GValue *value, GParamSpec *pspec);
91 static void get_property (GObject *object, guint prop_id,
92 GValue *value, GParamSpec *pspec);
95 #define SOUP_IS_SOCKET_ERROR(status) ((status) == SOCKET_ERROR)
96 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) == INVALID_SOCKET)
97 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (WSAGetLastError () == WSAEWOULDBLOCK)
98 #define SHUT_RDWR SD_BOTH
100 #define SOUP_IS_SOCKET_ERROR(status) ((status) == -1)
101 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) < 0)
102 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (errno == EINPROGRESS)
106 soup_socket_init (SoupSocket *sock)
108 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
111 priv->non_blocking = TRUE;
112 priv->addrlock = g_mutex_new ();
113 priv->iolock = g_mutex_new ();
118 disconnect_internal (SoupSocketPrivate *priv)
120 g_io_channel_unref (priv->iochannel);
121 priv->iochannel = NULL;
124 if (priv->read_src) {
125 g_source_destroy (priv->read_src);
126 priv->read_src = NULL;
128 if (priv->write_src) {
129 g_source_destroy (priv->write_src);
130 priv->write_src = NULL;
135 finalize (GObject *object)
137 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
140 disconnect_internal (priv);
142 if (priv->local_addr)
143 g_object_unref (priv->local_addr);
144 if (priv->remote_addr)
145 g_object_unref (priv->remote_addr);
148 g_source_destroy (priv->watch_src);
149 if (priv->async_context)
150 g_main_context_unref (priv->async_context);
153 g_byte_array_free (priv->read_buf, TRUE);
155 g_mutex_free (priv->addrlock);
156 g_mutex_free (priv->iolock);
158 G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
162 soup_socket_class_init (SoupSocketClass *socket_class)
164 GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
167 signal (SIGPIPE, SIG_IGN);
170 g_type_class_add_private (socket_class, sizeof (SoupSocketPrivate));
172 /* virtual method override */
173 object_class->finalize = finalize;
174 object_class->set_property = set_property;
175 object_class->get_property = get_property;
180 * SoupSocket::readable:
183 * Emitted when an async socket is readable. See
184 * soup_socket_read() and soup_socket_read_until().
187 g_signal_new ("readable",
188 G_OBJECT_CLASS_TYPE (object_class),
190 G_STRUCT_OFFSET (SoupSocketClass, readable),
192 soup_marshal_NONE__NONE,
196 * SoupSocket::writable:
199 * Emitted when an async socket is writable. See
200 * soup_socket_write().
203 g_signal_new ("writable",
204 G_OBJECT_CLASS_TYPE (object_class),
206 G_STRUCT_OFFSET (SoupSocketClass, writable),
208 soup_marshal_NONE__NONE,
212 * SoupSocket::disconnected:
215 * Emitted when the socket is disconnected, for whatever
218 signals[DISCONNECTED] =
219 g_signal_new ("disconnected",
220 G_OBJECT_CLASS_TYPE (object_class),
222 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
224 soup_marshal_NONE__NONE,
228 * SoupSocket::new-connection:
230 * @new: the new socket
232 * Emitted when a listening socket (set up with
233 * soup_socket_listen()) receives a new connection.
235 * You must ref the @new if you want to keep it; otherwise it
236 * will be destroyed after the signal is emitted.
238 signals[NEW_CONNECTION] =
239 g_signal_new ("new_connection",
240 G_OBJECT_CLASS_TYPE (object_class),
242 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
244 soup_marshal_NONE__OBJECT,
249 g_object_class_install_property (
250 object_class, PROP_LOCAL_ADDRESS,
251 g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
253 "Address of local end of socket",
255 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
256 g_object_class_install_property (
257 object_class, PROP_REMOTE_ADDRESS,
258 g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
260 "Address of remote end of socket",
262 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
263 g_object_class_install_property (
264 object_class, PROP_NON_BLOCKING,
265 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
267 "Whether or not the socket uses non-blocking I/O",
270 g_object_class_install_property (
271 object_class, PROP_IS_SERVER,
272 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
274 "Whether or not the socket is a server socket",
277 g_object_class_install_property (
278 object_class, PROP_SSL_CREDENTIALS,
279 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
281 "SSL credential information, passed from the session to the SSL implementation",
283 g_object_class_install_property (
284 object_class, PROP_ASYNC_CONTEXT,
285 g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
286 "Async GMainContext",
287 "The GMainContext to dispatch this socket's async I/O in",
288 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
290 g_object_class_install_property (
291 object_class, PROP_TIMEOUT,
292 g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
294 "Value in seconds to timeout a blocking I/O",
299 /* Make sure WSAStartup() gets called. */
300 soup_address_get_type ();
306 set_nonblocking (SoupSocketPrivate *priv)
314 if (priv->sockfd == -1)
318 flags = fcntl (priv->sockfd, F_GETFL, 0);
320 if (priv->non_blocking)
323 flags &= ~O_NONBLOCK;
324 fcntl (priv->sockfd, F_SETFL, flags);
327 val = priv->non_blocking ? 1 : 0;
328 ioctlsocket (priv->sockfd, FIONBIO, &val);
333 set_fdflags (SoupSocketPrivate *priv)
337 struct timeval timeout;
341 if (priv->sockfd == -1)
344 set_nonblocking (priv);
347 flags = fcntl (priv->sockfd, F_GETFD, 0);
350 fcntl (priv->sockfd, F_SETFD, flags);
355 setsockopt (priv->sockfd, IPPROTO_TCP,
356 TCP_NODELAY, (void *) &opt, sizeof (opt));
357 setsockopt (priv->sockfd, SOL_SOCKET,
358 SO_REUSEADDR, (void *) &opt, sizeof (opt));
361 timeout.tv_sec = priv->timeout;
363 setsockopt (priv->sockfd, SOL_SOCKET,
364 SO_RCVTIMEO, (void *) &timeout, sizeof (timeout));
366 timeout.tv_sec = priv->timeout;
368 setsockopt (priv->sockfd, SOL_SOCKET,
369 SO_SNDTIMEO, (void *) &timeout, sizeof (timeout));
371 if (priv->timeout < G_MAXINT / 1000)
372 opt = priv->timeout * 1000;
376 setsockopt (priv->sockfd, SOL_SOCKET,
377 SO_RCVTIMEO, (void *) &opt, sizeof (opt));
379 setsockopt (priv->sockfd, SOL_SOCKET,
380 SO_SNDTIMEO, (void *) &opt, sizeof (opt));
385 g_io_channel_unix_new (priv->sockfd);
388 g_io_channel_win32_new_socket (priv->sockfd);
390 g_io_channel_set_close_on_unref (priv->iochannel, TRUE);
391 g_io_channel_set_encoding (priv->iochannel, NULL, NULL);
392 g_io_channel_set_buffered (priv->iochannel, FALSE);
396 set_property (GObject *object, guint prop_id,
397 const GValue *value, GParamSpec *pspec)
399 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
402 case PROP_LOCAL_ADDRESS:
403 priv->local_addr = (SoupAddress *)g_value_dup_object (value);
405 case PROP_REMOTE_ADDRESS:
406 priv->remote_addr = (SoupAddress *)g_value_dup_object (value);
408 case PROP_NON_BLOCKING:
409 priv->non_blocking = g_value_get_boolean (value);
410 set_nonblocking (priv);
412 case PROP_SSL_CREDENTIALS:
413 priv->ssl_creds = g_value_get_pointer (value);
415 case PROP_ASYNC_CONTEXT:
416 priv->async_context = g_value_get_pointer (value);
417 if (priv->async_context)
418 g_main_context_ref (priv->async_context);
421 priv->timeout = g_value_get_uint (value);
424 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430 get_property (GObject *object, guint prop_id,
431 GValue *value, GParamSpec *pspec)
433 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
436 case PROP_LOCAL_ADDRESS:
437 g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
439 case PROP_REMOTE_ADDRESS:
440 g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
442 case PROP_NON_BLOCKING:
443 g_value_set_boolean (value, priv->non_blocking);
446 g_value_set_boolean (value, priv->is_server);
448 case PROP_SSL_CREDENTIALS:
449 g_value_set_pointer (value, priv->ssl_creds);
451 case PROP_ASYNC_CONTEXT:
452 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
455 g_value_set_uint (value, priv->timeout);
458 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
466 * @optname1: name of first property to set (or %NULL)
467 * @...: value of @optname1, followed by additional property/value pairs
469 * Creates a new (disconnected) socket
471 * Return value: the new socket
474 soup_socket_new (const char *optname1, ...)
479 va_start (ap, optname1);
480 sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
489 GCancellable *cancellable;
491 SoupSocketCallback callback;
493 } SoupSocketAsyncConnectData;
496 idle_connect_result (gpointer user_data)
498 SoupSocketAsyncConnectData *sacd = user_data;
499 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
502 priv->watch_src = NULL;
504 g_signal_handler_disconnect (sacd->cancellable, sacd->cancel_id);
506 if (priv->sockfd == -1) {
507 if (g_cancellable_is_cancelled (sacd->cancellable))
508 status = SOUP_STATUS_CANCELLED;
510 status = SOUP_STATUS_CANT_CONNECT;
512 status = SOUP_STATUS_OK;
514 sacd->callback (sacd->sock, status, sacd->user_data);
515 g_slice_free (SoupSocketAsyncConnectData, sacd);
520 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
522 SoupSocketAsyncConnectData *sacd = data;
523 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
525 int len = sizeof (error);
527 /* Remove the watch now in case we don't return immediately */
528 g_source_destroy (priv->watch_src);
529 priv->watch_src = NULL;
531 if ((condition & ~(G_IO_IN | G_IO_OUT)) ||
532 (getsockopt (priv->sockfd, SOL_SOCKET, SO_ERROR,
533 (void *)&error, (void *)&len) != 0) ||
535 disconnect_internal (priv);
537 return idle_connect_result (sacd);
541 got_address (SoupAddress *addr, guint status, gpointer user_data)
543 SoupSocketAsyncConnectData *sacd = user_data;
545 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
546 sacd->callback (sacd->sock, status, sacd->user_data);
547 g_slice_free (SoupSocketAsyncConnectData, sacd);
551 soup_socket_connect_async (sacd->sock, sacd->cancellable,
552 sacd->callback, sacd->user_data);
553 g_slice_free (SoupSocketAsyncConnectData, sacd);
557 async_cancel (GCancellable *cancellable, gpointer user_data)
559 SoupSocketAsyncConnectData *sacd = user_data;
560 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
563 g_source_destroy (priv->watch_src);
564 disconnect_internal (priv);
565 priv->watch_src = soup_add_completion (priv->async_context,
566 idle_connect_result, sacd);
570 socket_connect_internal (SoupSocket *sock)
572 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
576 sa = soup_address_get_sockaddr (priv->remote_addr, &len);
578 return SOUP_STATUS_CANT_RESOLVE;
580 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
581 if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
582 return SOUP_STATUS_CANT_CONNECT;
585 status = connect (priv->sockfd, sa, len);
587 if (SOUP_IS_SOCKET_ERROR (status)) {
588 if (SOUP_IS_CONNECT_STATUS_INPROGRESS ())
589 return SOUP_STATUS_CONTINUE;
591 disconnect_internal (priv);
592 return SOUP_STATUS_CANT_CONNECT;
594 return SOUP_STATUS_OK;
598 * SoupSocketCallback:
599 * @sock: the #SoupSocket
600 * @status: an HTTP status code indicating success or failure
601 * @user_data: the data passed to soup_socket_connect_async()
603 * The callback function passed to soup_socket_connect_async().
607 * soup_socket_connect_async:
608 * @sock: a client #SoupSocket (which must not already be connected)
609 * @cancellable: a #GCancellable, or %NULL
610 * @callback: callback to call after connecting
611 * @user_data: data to pass to @callback
613 * Begins asynchronously connecting to @sock's remote address. The
614 * socket will call @callback when it succeeds or fails (but not
615 * before returning from this function).
617 * If @cancellable is non-%NULL, it can be used to cancel the
618 * connection. @callback will still be invoked in this case, with a
619 * status of %SOUP_STATUS_CANCELLED.
622 soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
623 SoupSocketCallback callback, gpointer user_data)
625 SoupSocketPrivate *priv;
626 SoupSocketAsyncConnectData *sacd;
629 g_return_if_fail (SOUP_IS_SOCKET (sock));
630 priv = SOUP_SOCKET_GET_PRIVATE (sock);
631 g_return_if_fail (priv->remote_addr != NULL);
633 sacd = g_slice_new0 (SoupSocketAsyncConnectData);
635 sacd->cancellable = cancellable;
636 sacd->callback = callback;
637 sacd->user_data = user_data;
639 if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
640 soup_address_resolve_async (priv->remote_addr,
647 status = socket_connect_internal (sock);
648 if (status == SOUP_STATUS_CONTINUE) {
649 /* Wait for connect to succeed or fail */
651 soup_add_io_watch (priv->async_context,
654 G_IO_PRI | G_IO_ERR |
655 G_IO_HUP | G_IO_NVAL,
656 connect_watch, sacd);
659 g_signal_connect (cancellable, "cancelled",
660 G_CALLBACK (async_cancel),
664 priv->watch_src = soup_add_completion (priv->async_context,
665 idle_connect_result, sacd);
670 sync_cancel (GCancellable *cancellable, gpointer sock)
672 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
674 shutdown (priv->sockfd, SHUT_RDWR);
678 * soup_socket_connect_sync:
679 * @sock: a client #SoupSocket (which must not already be connected)
680 * @cancellable: a #GCancellable, or %NULL
682 * Attempt to synchronously connect @sock to its remote address.
684 * If @cancellable is non-%NULL, it can be used to cancel the
685 * connection, in which case soup_socket_connect_sync() will return
686 * %SOUP_STATUS_CANCELLED.
688 * Return value: a success or failure code.
691 soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
693 SoupSocketPrivate *priv;
694 guint status, cancel_id;
696 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
697 priv = SOUP_SOCKET_GET_PRIVATE (sock);
698 g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
699 g_return_val_if_fail (priv->sockfd == -1, SOUP_STATUS_MALFORMED);
700 g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
702 if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
703 status = soup_address_resolve_sync (priv->remote_addr,
705 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
710 cancel_id = g_signal_connect (cancellable, "cancelled",
711 G_CALLBACK (sync_cancel), sock);
714 status = socket_connect_internal (sock);
717 if (status != SOUP_STATUS_OK &&
718 g_cancellable_is_cancelled (cancellable)) {
719 status = SOUP_STATUS_CANCELLED;
720 disconnect_internal (priv);
722 g_signal_handler_disconnect (cancellable, cancel_id);
729 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
731 SoupSocket *sock = data, *new;
732 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock), *new_priv;
733 struct soup_sockaddr_max sa;
736 if (condition & (G_IO_HUP | G_IO_ERR)) {
737 g_source_destroy (priv->watch_src);
738 priv->watch_src = NULL;
742 sa_len = sizeof (sa);
743 sockfd = accept (priv->sockfd, (struct sockaddr *)&sa, (void *)&sa_len);
744 if (SOUP_IS_INVALID_SOCKET (sockfd))
747 new = g_object_new (SOUP_TYPE_SOCKET, NULL);
748 new_priv = SOUP_SOCKET_GET_PRIVATE (new);
749 new_priv->sockfd = sockfd;
750 if (priv->async_context)
751 new_priv->async_context = g_main_context_ref (priv->async_context);
752 new_priv->non_blocking = priv->non_blocking;
753 new_priv->is_server = TRUE;
754 new_priv->ssl_creds = priv->ssl_creds;
755 set_fdflags (new_priv);
757 new_priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
759 if (new_priv->ssl_creds) {
760 if (!soup_socket_start_ssl (new, NULL)) {
761 g_object_unref (new);
766 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
767 g_object_unref (new);
773 * soup_socket_listen:
774 * @sock: a server #SoupSocket (which must not already be connected or
777 * Makes @sock start listening on its local address. When connections
778 * come in, @sock will emit %new_connection.
780 * Return value: whether or not @sock is now listening.
783 soup_socket_listen (SoupSocket *sock)
786 SoupSocketPrivate *priv;
790 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
791 priv = SOUP_SOCKET_GET_PRIVATE (sock);
792 g_return_val_if_fail (priv->sockfd == -1, FALSE);
793 g_return_val_if_fail (priv->local_addr != NULL, FALSE);
795 priv->is_server = TRUE;
797 /* @local_addr may have its port set to 0. So we intentionally
798 * don't store it in priv->local_addr, so that if the
799 * caller calls soup_socket_get_local_address() later, we'll
800 * have to make a new addr by calling getsockname(), which
801 * will have the right port number.
803 sa = soup_address_get_sockaddr (priv->local_addr, &sa_len);
804 g_return_val_if_fail (sa != NULL, FALSE);
806 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
807 if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
812 if (bind (priv->sockfd, sa, sa_len) != 0)
814 /* Force local_addr to be re-resolved now */
815 g_object_unref (priv->local_addr);
816 priv->local_addr = NULL;
819 if (listen (priv->sockfd, 10) != 0)
822 priv->watch_src = soup_add_io_watch (priv->async_context,
824 G_IO_IN | G_IO_ERR | G_IO_HUP,
830 disconnect_internal (priv);
836 * soup_socket_start_ssl:
838 * @cancellable: a #GCancellable
840 * Starts using SSL on @socket.
842 * Return value: success or failure
845 soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
847 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
849 return soup_socket_start_proxy_ssl (sock, soup_address_get_name (priv->remote_addr), cancellable);
853 * soup_socket_start_proxy_ssl:
855 * @ssl_host: hostname of the SSL server
856 * @cancellable: a #GCancellable
858 * Starts using SSL on @socket, expecting to find a host named
861 * Return value: success or failure
864 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
865 GCancellable *cancellable)
867 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
868 GIOChannel *ssl_chan;
869 GIOChannel *real_chan;
871 real_chan = priv->iochannel;
872 ssl_chan = soup_ssl_wrap_iochannel (
873 real_chan, priv->non_blocking, priv->is_server ?
874 SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
875 ssl_host, priv->ssl_creds);
880 priv->iochannel = ssl_chan;
881 g_io_channel_unref (real_chan);
887 * soup_socket_is_ssl:
888 * @sock: a #SoupSocket
890 * Tests if @sock is set up to do SSL. Note that this simply means
891 * that the %SOUP_SOCKET_SSL_CREDENTIALS property has been set; it
892 * does not mean that soup_socket_start_ssl() has been called.
894 * Return value: %TRUE if @sock has SSL credentials set
897 soup_socket_is_ssl (SoupSocket *sock)
899 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
901 return priv->ssl_creds != NULL;
905 * soup_socket_disconnect:
906 * @sock: a #SoupSocket
908 * Disconnects @sock. Any further read or write attempts on it will
912 soup_socket_disconnect (SoupSocket *sock)
914 SoupSocketPrivate *priv;
915 gboolean already_disconnected = FALSE;
917 g_return_if_fail (SOUP_IS_SOCKET (sock));
918 priv = SOUP_SOCKET_GET_PRIVATE (sock);
920 if (g_mutex_trylock (priv->iolock)) {
922 disconnect_internal (priv);
924 already_disconnected = TRUE;
925 g_mutex_unlock (priv->iolock);
929 /* Another thread is currently doing IO, so
930 * we can't close the iochannel. So just shutdown
931 * the file descriptor to force the I/O to fail.
932 * (It will actually be closed when the socket is
935 sockfd = priv->sockfd;
939 already_disconnected = TRUE;
941 shutdown (sockfd, SHUT_RDWR);
944 if (already_disconnected)
947 /* Give all readers a chance to notice the connection close */
948 g_signal_emit (sock, signals[READABLE], 0);
950 /* FIXME: can't disconnect until all data is read */
952 /* Then let everyone know we're disconnected */
953 g_signal_emit (sock, signals[DISCONNECTED], 0);
957 * soup_socket_is_connected:
958 * @sock: a #SoupSocket
960 * Tests if @sock is connected to another host
962 * Return value: %TRUE or %FALSE.
965 soup_socket_is_connected (SoupSocket *sock)
967 SoupSocketPrivate *priv;
969 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
970 priv = SOUP_SOCKET_GET_PRIVATE (sock);
972 return priv->iochannel != NULL;
976 * soup_socket_get_local_address:
977 * @sock: a #SoupSocket
979 * Returns the #SoupAddress corresponding to the local end of @sock.
981 * Return value: the #SoupAddress
984 soup_socket_get_local_address (SoupSocket *sock)
986 SoupSocketPrivate *priv;
988 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
989 priv = SOUP_SOCKET_GET_PRIVATE (sock);
991 g_mutex_lock (priv->addrlock);
992 if (!priv->local_addr) {
993 struct soup_sockaddr_max bound_sa;
996 sa_len = sizeof (bound_sa);
997 getsockname (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
998 priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
1000 g_mutex_unlock (priv->addrlock);
1002 return priv->local_addr;
1006 * soup_socket_get_remote_address:
1007 * @sock: a #SoupSocket
1009 * Returns the #SoupAddress corresponding to the remote end of @sock.
1011 * Return value: the #SoupAddress
1014 soup_socket_get_remote_address (SoupSocket *sock)
1016 SoupSocketPrivate *priv;
1018 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1019 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1021 g_mutex_lock (priv->addrlock);
1022 if (!priv->remote_addr) {
1023 struct soup_sockaddr_max bound_sa;
1026 sa_len = sizeof (bound_sa);
1027 getpeername (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
1028 priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
1030 g_mutex_unlock (priv->addrlock);
1032 return priv->remote_addr;
1039 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1041 SoupSocket *sock = user_data;
1042 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1044 priv->read_src = NULL;
1046 if (cond & (G_IO_ERR | G_IO_HUP))
1047 soup_socket_disconnect (sock);
1049 g_signal_emit (sock, signals[READABLE], 0);
1054 static SoupSocketIOStatus
1055 read_from_network (SoupSocket *sock, gpointer buffer, gsize len,
1056 gsize *nread, GError **error)
1058 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1060 GIOCondition cond = G_IO_IN;
1061 GError *my_err = NULL;
1065 if (!priv->iochannel)
1066 return SOUP_SOCKET_EOF;
1068 status = g_io_channel_read_chars (priv->iochannel,
1069 buffer, len, nread, &my_err);
1071 if (my_err->domain == SOUP_SSL_ERROR &&
1072 my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE)
1074 g_propagate_error (error, my_err);
1078 case G_IO_STATUS_NORMAL:
1079 case G_IO_STATUS_AGAIN:
1081 g_clear_error (error);
1082 return SOUP_SOCKET_OK;
1085 /* If the socket is sync and we get EAGAIN, then it is
1086 * a socket timeout and should be treated as an error
1089 if (!priv->non_blocking)
1090 return SOUP_SOCKET_ERROR;
1092 if (!priv->read_src) {
1094 soup_add_io_watch (priv->async_context,
1096 cond | G_IO_HUP | G_IO_ERR,
1097 socket_read_watch, sock);
1099 g_clear_error (error);
1100 return SOUP_SOCKET_WOULD_BLOCK;
1102 case G_IO_STATUS_EOF:
1103 g_clear_error (error);
1104 return SOUP_SOCKET_EOF;
1107 return SOUP_SOCKET_ERROR;
1111 static SoupSocketIOStatus
1112 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
1114 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1115 GByteArray *read_buf = priv->read_buf;
1117 *nread = MIN (read_buf->len, len);
1118 memcpy (buffer, read_buf->data, *nread);
1120 if (*nread == read_buf->len) {
1121 g_byte_array_free (read_buf, TRUE);
1122 priv->read_buf = NULL;
1124 memmove (read_buf->data, read_buf->data + *nread,
1125 read_buf->len - *nread);
1126 g_byte_array_set_size (read_buf, read_buf->len - *nread);
1129 return SOUP_SOCKET_OK;
1133 * SoupSocketIOStatus:
1134 * @SOUP_SOCKET_OK: Success
1135 * @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time
1136 * @SOUP_SOCKET_EOF: End of file
1137 * @SOUP_SOCKET_ERROR: Other error
1139 * Return value from the #SoupSocket IO methods.
1145 * @buffer: buffer to read into
1146 * @len: size of @buffer in bytes
1147 * @nread: on return, the number of bytes read into @buffer
1148 * @cancellable: a #GCancellable, or %NULL
1149 * @error: error pointer
1151 * Attempts to read up to @len bytes from @sock into @buffer. If some
1152 * data is successfully read, soup_socket_read() will return
1153 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
1156 * If @sock is non-blocking, and no data is available, the return
1157 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
1158 * can connect to the %readable signal to know when there is more data
1159 * to read. (NB: You MUST read all available data off the socket
1160 * first. The %readable signal will only be emitted after
1161 * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
1163 * Return value: a #SoupSocketIOStatus, as described above (or
1164 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
1165 * %SOUP_SOCKET_ERROR on any other error, in which case @error will
1169 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
1170 gsize *nread, GCancellable *cancellable, GError **error)
1172 SoupSocketPrivate *priv;
1173 SoupSocketIOStatus status;
1175 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1176 g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1178 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1180 g_mutex_lock (priv->iolock);
1182 status = read_from_buf (sock, buffer, len, nread);
1184 status = read_from_network (sock, buffer, len, nread, error);
1185 g_mutex_unlock (priv->iolock);
1191 * soup_socket_read_until:
1193 * @buffer: buffer to read into
1194 * @len: size of @buffer in bytes
1195 * @boundary: boundary to read until
1196 * @boundary_len: length of @boundary in bytes
1197 * @nread: on return, the number of bytes read into @buffer
1198 * @got_boundary: on return, whether or not the data in @buffer
1199 * ends with the boundary string
1200 * @cancellable: a #GCancellable, or %NULL
1201 * @error: error pointer
1203 * Like soup_socket_read(), but reads no further than the first
1204 * occurrence of @boundary. (If the boundary is found, it will be
1205 * included in the returned data, and *@got_boundary will be set to
1206 * %TRUE.) Any data after the boundary will returned in future reads.
1208 * Return value: as for soup_socket_read()
1211 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1212 gconstpointer boundary, gsize boundary_len,
1213 gsize *nread, gboolean *got_boundary,
1214 GCancellable *cancellable, GError **error)
1216 SoupSocketPrivate *priv;
1217 SoupSocketIOStatus status;
1218 GByteArray *read_buf;
1219 guint match_len, prev_len;
1222 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1223 g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1224 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1226 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1228 g_mutex_lock (priv->iolock);
1230 *got_boundary = FALSE;
1232 if (!priv->read_buf)
1233 priv->read_buf = g_byte_array_new ();
1234 read_buf = priv->read_buf;
1236 if (read_buf->len < boundary_len) {
1237 prev_len = read_buf->len;
1238 g_byte_array_set_size (read_buf, len);
1239 status = read_from_network (sock,
1240 read_buf->data + prev_len,
1241 len - prev_len, nread, error);
1242 read_buf->len = prev_len + *nread;
1244 if (status != SOUP_SOCKET_OK) {
1245 g_mutex_unlock (priv->iolock);
1250 /* Scan for the boundary */
1251 end = read_buf->data + read_buf->len;
1252 for (p = read_buf->data; p <= end - boundary_len; p++) {
1253 if (!memcmp (p, boundary, boundary_len)) {
1255 *got_boundary = TRUE;
1260 /* Return everything up to 'p' (which is either just after the
1261 * boundary, or @boundary_len - 1 bytes before the end of the
1264 match_len = p - read_buf->data;
1265 status = read_from_buf (sock, buffer, MIN (len, match_len), nread);
1267 g_mutex_unlock (priv->iolock);
1272 socket_write_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1274 SoupSocket *sock = user_data;
1275 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1277 priv->write_src = NULL;
1279 if (cond & (G_IO_ERR | G_IO_HUP))
1280 soup_socket_disconnect (sock);
1282 g_signal_emit (sock, signals[WRITABLE], 0);
1288 * soup_socket_write:
1290 * @buffer: data to write
1291 * @len: size of @buffer, in bytes
1292 * @nwrote: on return, number of bytes written
1293 * @cancellable: a #GCancellable, or %NULL
1294 * @error: error pointer
1296 * Attempts to write @len bytes from @buffer to @sock. If some data is
1297 * successfully written, the resturn status will be
1298 * %SOUP_SOCKET_OK, and *@nwrote will contain the number of bytes
1301 * If @sock is non-blocking, and no data could be written right away,
1302 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1303 * the caller can connect to the %writable signal to know when more
1304 * data can be written. (NB: %writable is only emitted after a
1305 * %SOUP_SOCKET_WOULD_BLOCK.)
1307 * Return value: a #SoupSocketIOStatus, as described above (or
1308 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the
1309 * return value is %SOUP_SOCKET_ERROR.)
1312 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1313 gsize len, gsize *nwrote,
1314 GCancellable *cancellable, GError **error)
1316 SoupSocketPrivate *priv;
1318 GIOCondition cond = G_IO_OUT;
1319 GError *my_err = NULL;
1321 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1322 g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR);
1324 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1326 g_mutex_lock (priv->iolock);
1328 if (!priv->iochannel) {
1329 g_mutex_unlock (priv->iolock);
1330 return SOUP_SOCKET_EOF;
1332 if (priv->write_src) {
1333 g_mutex_unlock (priv->iolock);
1334 return SOUP_SOCKET_WOULD_BLOCK;
1337 status = g_io_channel_write_chars (priv->iochannel,
1338 buffer, len, nwrote, &my_err);
1340 if (my_err->domain == SOUP_SSL_ERROR &&
1341 my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ)
1343 g_propagate_error (error, my_err);
1346 /* If the socket is sync and we get EAGAIN, then it is a
1347 * socket timeout and should be treated as an error condition.
1349 if (!priv->non_blocking && status == G_IO_STATUS_AGAIN) {
1350 g_mutex_unlock (priv->iolock);
1351 return SOUP_SOCKET_ERROR;
1354 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
1355 g_mutex_unlock (priv->iolock);
1356 return SOUP_SOCKET_ERROR;
1359 g_clear_error (error);
1362 g_mutex_unlock (priv->iolock);
1363 return SOUP_SOCKET_OK;
1367 soup_add_io_watch (priv->async_context,
1369 cond | G_IO_HUP | G_IO_ERR,
1370 socket_write_watch, sock);
1371 g_mutex_unlock (priv->iolock);
1372 return SOUP_SOCKET_WOULD_BLOCK;