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;
74 GMainContext *async_context;
76 GSource *read_src, *write_src;
77 GSource *read_timeout, *write_timeout;
78 GSource *connect_timeout;
81 GMutex *iolock, *addrlock;
84 #define SOUP_SOCKET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SOCKET, SoupSocketPrivate))
87 #define soup_sockaddr_max sockaddr_in6
89 #define soup_sockaddr_max sockaddr_in
92 static void set_property (GObject *object, guint prop_id,
93 const GValue *value, GParamSpec *pspec);
94 static void get_property (GObject *object, guint prop_id,
95 GValue *value, GParamSpec *pspec);
98 #define SOUP_IS_SOCKET_ERROR(status) ((status) == SOCKET_ERROR)
99 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) == INVALID_SOCKET)
100 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (WSAGetLastError () == WSAEWOULDBLOCK)
101 #define SHUT_RDWR SD_BOTH
103 #define SOUP_IS_SOCKET_ERROR(status) ((status) == -1)
104 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) < 0)
105 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (errno == EINPROGRESS)
109 soup_socket_init (SoupSocket *sock)
111 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
114 priv->non_blocking = TRUE;
115 priv->addrlock = g_mutex_new ();
116 priv->iolock = g_mutex_new ();
121 disconnect_internal (SoupSocketPrivate *priv)
123 g_io_channel_unref (priv->iochannel);
124 priv->iochannel = NULL;
127 if (priv->read_src) {
128 g_source_destroy (priv->read_src);
129 priv->read_src = NULL;
131 if (priv->write_src) {
132 g_source_destroy (priv->write_src);
133 priv->write_src = NULL;
135 if (priv->read_timeout) {
136 g_source_destroy (priv->read_timeout);
137 priv->read_timeout = NULL;
139 if (priv->write_timeout) {
140 g_source_destroy (priv->write_timeout);
141 priv->write_timeout = NULL;
146 finalize (GObject *object)
148 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
151 disconnect_internal (priv);
153 if (priv->local_addr)
154 g_object_unref (priv->local_addr);
155 if (priv->remote_addr)
156 g_object_unref (priv->remote_addr);
159 g_source_destroy (priv->watch_src);
160 if (priv->connect_timeout)
161 g_source_destroy (priv->connect_timeout);
162 if (priv->async_context)
163 g_main_context_unref (priv->async_context);
166 g_byte_array_free (priv->read_buf, TRUE);
168 g_mutex_free (priv->addrlock);
169 g_mutex_free (priv->iolock);
171 G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
175 soup_socket_class_init (SoupSocketClass *socket_class)
177 GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
180 signal (SIGPIPE, SIG_IGN);
183 g_type_class_add_private (socket_class, sizeof (SoupSocketPrivate));
185 /* virtual method override */
186 object_class->finalize = finalize;
187 object_class->set_property = set_property;
188 object_class->get_property = get_property;
193 * SoupSocket::readable:
196 * Emitted when an async socket is readable. See
197 * soup_socket_read(), soup_socket_read_until() and
198 * #SoupSocket:non-blocking.
201 g_signal_new ("readable",
202 G_OBJECT_CLASS_TYPE (object_class),
204 G_STRUCT_OFFSET (SoupSocketClass, readable),
206 soup_marshal_NONE__NONE,
210 * SoupSocket::writable:
213 * Emitted when an async socket is writable. See
214 * soup_socket_write() and #SoupSocket:non-blocking.
217 g_signal_new ("writable",
218 G_OBJECT_CLASS_TYPE (object_class),
220 G_STRUCT_OFFSET (SoupSocketClass, writable),
222 soup_marshal_NONE__NONE,
226 * SoupSocket::disconnected:
229 * Emitted when the socket is disconnected, for whatever
232 signals[DISCONNECTED] =
233 g_signal_new ("disconnected",
234 G_OBJECT_CLASS_TYPE (object_class),
236 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
238 soup_marshal_NONE__NONE,
242 * SoupSocket::new-connection:
244 * @new: the new socket
246 * Emitted when a listening socket (set up with
247 * soup_socket_listen()) receives a new connection.
249 * You must ref the @new if you want to keep it; otherwise it
250 * will be destroyed after the signal is emitted.
252 signals[NEW_CONNECTION] =
253 g_signal_new ("new_connection",
254 G_OBJECT_CLASS_TYPE (object_class),
256 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
258 soup_marshal_NONE__OBJECT,
264 * SOUP_SOCKET_LOCAL_ADDRESS:
266 * Alias for the #SoupSocket:local-address property. (Address
267 * of local end of socket.)
269 g_object_class_install_property (
270 object_class, PROP_LOCAL_ADDRESS,
271 g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
273 "Address of local end of socket",
275 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
277 * SOUP_SOCKET_REMOTE_ADDRESS:
279 * Alias for the #SoupSocket:remote-address property. (Address
280 * of remote end of socket.)
282 g_object_class_install_property (
283 object_class, PROP_REMOTE_ADDRESS,
284 g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
286 "Address of remote end of socket",
288 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
290 * SoupSocket:non-blocking:
292 * Whether or not the socket uses non-blocking I/O.
294 * #SoupSocket's I/O methods are designed around the idea of
295 * using a single codepath for both synchronous and
296 * asynchronous I/O. If you want to read off a #SoupSocket,
297 * the "correct" way to do it is to call soup_socket_read() or
298 * soup_socket_read_until() repeatedly until you have read
299 * everything you want. If it returns %SOUP_SOCKET_WOULD_BLOCK
300 * at any point, stop reading and wait for it to emit the
301 * #SoupSocket::readable signal. Then go back to the
302 * reading-as-much-as-you-can loop. Likewise, for writing to a
303 * #SoupSocket, you should call soup_socket_write() either
304 * until you have written everything, or it returns
305 * %SOUP_SOCKET_WOULD_BLOCK (in which case you wait for
306 * #SoupSocket::writable and then go back into the loop).
308 * Code written this way will work correctly with both
309 * blocking and non-blocking sockets; blocking sockets will
310 * simply never return %SOUP_SOCKET_WOULD_BLOCK, and so the
311 * code that handles that case just won't get used for them.
314 * SOUP_SOCKET_FLAG_NONBLOCKING:
316 * Alias for the #SoupSocket:non-blocking property. (Whether
317 * or not the socket uses non-blocking I/O.)
319 g_object_class_install_property (
320 object_class, PROP_NON_BLOCKING,
321 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
323 "Whether or not the socket uses non-blocking I/O",
327 * SOUP_SOCKET_IS_SERVER:
329 * Alias for the #SoupSocket:is-server property. (Whether or
330 * not the socket is a server socket.)
332 g_object_class_install_property (
333 object_class, PROP_IS_SERVER,
334 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
336 "Whether or not the socket is a server socket",
340 * SOUP_SOCKET_SSL_CREDENTIALS:
342 * Alias for the #SoupSocket:ssl-credentials property.
343 * (SSL credential information.)
345 g_object_class_install_property (
346 object_class, PROP_SSL_CREDENTIALS,
347 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
349 "SSL credential information, passed from the session to the SSL implementation",
352 * SOUP_SOCKET_ASYNC_CONTEXT:
354 * Alias for the #SoupSocket:async-context property. (The
355 * socket's #GMainContext.)
357 g_object_class_install_property (
358 object_class, PROP_ASYNC_CONTEXT,
359 g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
360 "Async GMainContext",
361 "The GMainContext to dispatch this socket's async I/O in",
362 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
365 * SOUP_SOCKET_TIMEOUT:
367 * Alias for the #SoupSocket:timeout property. (The timeout
368 * in seconds for blocking socket I/O operations.)
370 g_object_class_install_property (
371 object_class, PROP_TIMEOUT,
372 g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
374 "Value in seconds to timeout a blocking I/O",
379 /* Make sure WSAStartup() gets called. */
380 soup_address_get_type ();
386 set_nonblocking (SoupSocketPrivate *priv)
394 if (priv->sockfd == -1)
398 flags = fcntl (priv->sockfd, F_GETFL, 0);
400 if (priv->non_blocking)
403 flags &= ~O_NONBLOCK;
404 fcntl (priv->sockfd, F_SETFL, flags);
407 val = priv->non_blocking ? 1 : 0;
408 ioctlsocket (priv->sockfd, FIONBIO, &val);
413 set_fdflags (SoupSocketPrivate *priv)
417 struct timeval timeout;
421 if (priv->sockfd == -1)
424 set_nonblocking (priv);
427 flags = fcntl (priv->sockfd, F_GETFD, 0);
430 fcntl (priv->sockfd, F_SETFD, flags);
435 setsockopt (priv->sockfd, IPPROTO_TCP,
436 TCP_NODELAY, (void *) &opt, sizeof (opt));
437 setsockopt (priv->sockfd, SOL_SOCKET,
438 SO_REUSEADDR, (void *) &opt, sizeof (opt));
441 timeout.tv_sec = priv->timeout;
443 setsockopt (priv->sockfd, SOL_SOCKET,
444 SO_RCVTIMEO, (void *) &timeout, sizeof (timeout));
446 timeout.tv_sec = priv->timeout;
448 setsockopt (priv->sockfd, SOL_SOCKET,
449 SO_SNDTIMEO, (void *) &timeout, sizeof (timeout));
451 if (priv->timeout < G_MAXINT / 1000)
452 opt = priv->timeout * 1000;
456 setsockopt (priv->sockfd, SOL_SOCKET,
457 SO_RCVTIMEO, (void *) &opt, sizeof (opt));
459 setsockopt (priv->sockfd, SOL_SOCKET,
460 SO_SNDTIMEO, (void *) &opt, sizeof (opt));
465 g_io_channel_unix_new (priv->sockfd);
468 g_io_channel_win32_new_socket (priv->sockfd);
470 g_io_channel_set_close_on_unref (priv->iochannel, TRUE);
471 g_io_channel_set_encoding (priv->iochannel, NULL, NULL);
472 g_io_channel_set_buffered (priv->iochannel, FALSE);
476 set_property (GObject *object, guint prop_id,
477 const GValue *value, GParamSpec *pspec)
479 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
482 case PROP_LOCAL_ADDRESS:
483 priv->local_addr = (SoupAddress *)g_value_dup_object (value);
485 case PROP_REMOTE_ADDRESS:
486 priv->remote_addr = (SoupAddress *)g_value_dup_object (value);
488 case PROP_NON_BLOCKING:
489 priv->non_blocking = g_value_get_boolean (value);
490 set_nonblocking (priv);
492 case PROP_SSL_CREDENTIALS:
493 priv->ssl_creds = g_value_get_pointer (value);
495 case PROP_ASYNC_CONTEXT:
496 priv->async_context = g_value_get_pointer (value);
497 if (priv->async_context)
498 g_main_context_ref (priv->async_context);
501 priv->timeout = g_value_get_uint (value);
504 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
510 get_property (GObject *object, guint prop_id,
511 GValue *value, GParamSpec *pspec)
513 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
516 case PROP_LOCAL_ADDRESS:
517 g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
519 case PROP_REMOTE_ADDRESS:
520 g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
522 case PROP_NON_BLOCKING:
523 g_value_set_boolean (value, priv->non_blocking);
526 g_value_set_boolean (value, priv->is_server);
528 case PROP_SSL_CREDENTIALS:
529 g_value_set_pointer (value, priv->ssl_creds);
531 case PROP_ASYNC_CONTEXT:
532 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
535 g_value_set_uint (value, priv->timeout);
538 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
546 * @optname1: name of first property to set (or %NULL)
547 * @...: value of @optname1, followed by additional property/value pairs
549 * Creates a new (disconnected) socket
551 * Return value: the new socket
554 soup_socket_new (const char *optname1, ...)
559 va_start (ap, optname1);
560 sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
569 GCancellable *cancellable;
571 SoupSocketCallback callback;
573 } SoupSocketAsyncConnectData;
576 idle_connect_result (gpointer user_data)
578 SoupSocketAsyncConnectData *sacd = user_data;
579 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
582 priv->watch_src = NULL;
584 g_signal_handler_disconnect (sacd->cancellable, sacd->cancel_id);
586 if (priv->sockfd == -1) {
587 if (g_cancellable_is_cancelled (sacd->cancellable))
588 status = SOUP_STATUS_CANCELLED;
590 status = SOUP_STATUS_CANT_CONNECT;
592 status = SOUP_STATUS_OK;
594 sacd->callback (sacd->sock, status, sacd->user_data);
595 g_slice_free (SoupSocketAsyncConnectData, sacd);
600 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
602 SoupSocketAsyncConnectData *sacd = data;
603 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
605 int len = sizeof (error);
607 /* Remove the watch now in case we don't return immediately */
608 g_source_destroy (priv->watch_src);
609 priv->watch_src = NULL;
610 if (priv->connect_timeout) {
611 g_source_destroy (priv->connect_timeout);
612 priv->connect_timeout = NULL;
615 if ((condition & ~(G_IO_IN | G_IO_OUT)) ||
616 (getsockopt (priv->sockfd, SOL_SOCKET, SO_ERROR,
617 (void *)&error, (void *)&len) != 0) ||
619 disconnect_internal (priv);
621 return idle_connect_result (sacd);
625 connect_timeout (gpointer data)
627 SoupSocketAsyncConnectData *sacd = data;
628 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
630 /* Remove the watch now in case we don't return immediately */
631 g_source_destroy (priv->watch_src);
632 priv->watch_src = NULL;
633 g_source_destroy (priv->connect_timeout);
634 priv->connect_timeout = NULL;
636 disconnect_internal (priv);
637 return idle_connect_result (sacd);
641 got_address (SoupAddress *addr, guint status, gpointer user_data)
643 SoupSocketAsyncConnectData *sacd = user_data;
645 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
646 sacd->callback (sacd->sock, status, sacd->user_data);
647 g_slice_free (SoupSocketAsyncConnectData, sacd);
651 soup_socket_connect_async (sacd->sock, sacd->cancellable,
652 sacd->callback, sacd->user_data);
653 g_slice_free (SoupSocketAsyncConnectData, sacd);
657 async_cancel (GCancellable *cancellable, gpointer user_data)
659 SoupSocketAsyncConnectData *sacd = user_data;
660 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
663 g_source_destroy (priv->watch_src);
664 disconnect_internal (priv);
665 priv->watch_src = soup_add_completion (priv->async_context,
666 idle_connect_result, sacd);
670 socket_connect_internal (SoupSocket *sock)
672 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
676 sa = soup_address_get_sockaddr (priv->remote_addr, &len);
678 return SOUP_STATUS_CANT_RESOLVE;
680 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
681 if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
682 return SOUP_STATUS_CANT_CONNECT;
685 status = connect (priv->sockfd, sa, len);
687 if (SOUP_IS_SOCKET_ERROR (status)) {
688 if (SOUP_IS_CONNECT_STATUS_INPROGRESS ())
689 return SOUP_STATUS_CONTINUE;
691 disconnect_internal (priv);
692 return SOUP_STATUS_CANT_CONNECT;
694 return SOUP_STATUS_OK;
698 * SoupSocketCallback:
699 * @sock: the #SoupSocket
700 * @status: an HTTP status code indicating success or failure
701 * @user_data: the data passed to soup_socket_connect_async()
703 * The callback function passed to soup_socket_connect_async().
707 * soup_socket_connect_async:
708 * @sock: a client #SoupSocket (which must not already be connected)
709 * @cancellable: a #GCancellable, or %NULL
710 * @callback: callback to call after connecting
711 * @user_data: data to pass to @callback
713 * Begins asynchronously connecting to @sock's remote address. The
714 * socket will call @callback when it succeeds or fails (but not
715 * before returning from this function).
717 * If @cancellable is non-%NULL, it can be used to cancel the
718 * connection. @callback will still be invoked in this case, with a
719 * status of %SOUP_STATUS_CANCELLED.
722 soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
723 SoupSocketCallback callback, gpointer user_data)
725 SoupSocketPrivate *priv;
726 SoupSocketAsyncConnectData *sacd;
729 g_return_if_fail (SOUP_IS_SOCKET (sock));
730 priv = SOUP_SOCKET_GET_PRIVATE (sock);
731 g_return_if_fail (priv->remote_addr != NULL);
733 sacd = g_slice_new0 (SoupSocketAsyncConnectData);
735 sacd->cancellable = cancellable;
736 sacd->callback = callback;
737 sacd->user_data = user_data;
739 if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
740 soup_address_resolve_async (priv->remote_addr,
747 status = socket_connect_internal (sock);
748 if (status == SOUP_STATUS_CONTINUE) {
749 /* Wait for connect to succeed or fail */
751 soup_add_io_watch (priv->async_context,
754 G_IO_PRI | G_IO_ERR |
755 G_IO_HUP | G_IO_NVAL,
756 connect_watch, sacd);
758 priv->connect_timeout =
759 soup_add_timeout (priv->async_context,
760 priv->timeout * 1000,
761 connect_timeout, sacd);
765 g_signal_connect (cancellable, "cancelled",
766 G_CALLBACK (async_cancel),
770 priv->watch_src = soup_add_completion (priv->async_context,
771 idle_connect_result, sacd);
776 sync_cancel (GCancellable *cancellable, gpointer sock)
778 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
780 shutdown (priv->sockfd, SHUT_RDWR);
784 * soup_socket_connect_sync:
785 * @sock: a client #SoupSocket (which must not already be connected)
786 * @cancellable: a #GCancellable, or %NULL
788 * Attempt to synchronously connect @sock to its remote address.
790 * If @cancellable is non-%NULL, it can be used to cancel the
791 * connection, in which case soup_socket_connect_sync() will return
792 * %SOUP_STATUS_CANCELLED.
794 * Return value: a success or failure code.
797 soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
799 SoupSocketPrivate *priv;
800 guint status, cancel_id;
802 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
803 priv = SOUP_SOCKET_GET_PRIVATE (sock);
804 g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
805 g_return_val_if_fail (priv->sockfd == -1, SOUP_STATUS_MALFORMED);
806 g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
808 if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
809 status = soup_address_resolve_sync (priv->remote_addr,
811 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
816 cancel_id = g_signal_connect (cancellable, "cancelled",
817 G_CALLBACK (sync_cancel), sock);
820 status = socket_connect_internal (sock);
823 if (status != SOUP_STATUS_OK &&
824 g_cancellable_is_cancelled (cancellable)) {
825 status = SOUP_STATUS_CANCELLED;
826 disconnect_internal (priv);
828 g_signal_handler_disconnect (cancellable, cancel_id);
835 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
837 SoupSocket *sock = data, *new;
838 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock), *new_priv;
839 struct soup_sockaddr_max sa;
842 if (condition & (G_IO_HUP | G_IO_ERR)) {
843 g_source_destroy (priv->watch_src);
844 priv->watch_src = NULL;
848 sa_len = sizeof (sa);
849 sockfd = accept (priv->sockfd, (struct sockaddr *)&sa, (void *)&sa_len);
850 if (SOUP_IS_INVALID_SOCKET (sockfd))
853 new = g_object_new (SOUP_TYPE_SOCKET, NULL);
854 new_priv = SOUP_SOCKET_GET_PRIVATE (new);
855 new_priv->sockfd = sockfd;
856 if (priv->async_context)
857 new_priv->async_context = g_main_context_ref (priv->async_context);
858 new_priv->non_blocking = priv->non_blocking;
859 new_priv->is_server = TRUE;
860 new_priv->ssl_creds = priv->ssl_creds;
861 set_fdflags (new_priv);
863 new_priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
865 if (new_priv->ssl_creds) {
866 if (!soup_socket_start_ssl (new, NULL)) {
867 g_object_unref (new);
872 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
873 g_object_unref (new);
879 * soup_socket_listen:
880 * @sock: a server #SoupSocket (which must not already be connected or
883 * Makes @sock start listening on its local address. When connections
884 * come in, @sock will emit %new_connection.
886 * Return value: whether or not @sock is now listening.
889 soup_socket_listen (SoupSocket *sock)
892 SoupSocketPrivate *priv;
896 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
897 priv = SOUP_SOCKET_GET_PRIVATE (sock);
898 g_return_val_if_fail (priv->sockfd == -1, FALSE);
899 g_return_val_if_fail (priv->local_addr != NULL, FALSE);
901 priv->is_server = TRUE;
903 /* @local_addr may have its port set to 0. So we intentionally
904 * don't store it in priv->local_addr, so that if the
905 * caller calls soup_socket_get_local_address() later, we'll
906 * have to make a new addr by calling getsockname(), which
907 * will have the right port number.
909 sa = soup_address_get_sockaddr (priv->local_addr, &sa_len);
910 g_return_val_if_fail (sa != NULL, FALSE);
912 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
913 if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
918 if (bind (priv->sockfd, sa, sa_len) != 0)
920 /* Force local_addr to be re-resolved now */
921 g_object_unref (priv->local_addr);
922 priv->local_addr = NULL;
925 if (listen (priv->sockfd, 10) != 0)
928 priv->watch_src = soup_add_io_watch (priv->async_context,
930 G_IO_IN | G_IO_ERR | G_IO_HUP,
936 disconnect_internal (priv);
942 * soup_socket_start_ssl:
944 * @cancellable: a #GCancellable
946 * Starts using SSL on @socket.
948 * Return value: success or failure
951 soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
953 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
955 return soup_socket_start_proxy_ssl (sock, soup_address_get_name (priv->remote_addr), cancellable);
959 * soup_socket_start_proxy_ssl:
961 * @ssl_host: hostname of the SSL server
962 * @cancellable: a #GCancellable
964 * Starts using SSL on @socket, expecting to find a host named
967 * Return value: success or failure
970 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
971 GCancellable *cancellable)
973 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
974 GIOChannel *ssl_chan;
975 GIOChannel *real_chan;
977 real_chan = priv->iochannel;
978 ssl_chan = soup_ssl_wrap_iochannel (
979 real_chan, priv->non_blocking, priv->is_server ?
980 SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
981 ssl_host, priv->ssl_creds);
986 priv->iochannel = ssl_chan;
987 g_io_channel_unref (real_chan);
993 * soup_socket_is_ssl:
994 * @sock: a #SoupSocket
996 * Tests if @sock is set up to do SSL. Note that this simply means
997 * that the %SOUP_SOCKET_SSL_CREDENTIALS property has been set; it
998 * does not mean that soup_socket_start_ssl() has been called.
1000 * Return value: %TRUE if @sock has SSL credentials set
1003 soup_socket_is_ssl (SoupSocket *sock)
1005 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1007 return priv->ssl_creds != NULL;
1011 * soup_socket_disconnect:
1012 * @sock: a #SoupSocket
1014 * Disconnects @sock. Any further read or write attempts on it will
1018 soup_socket_disconnect (SoupSocket *sock)
1020 SoupSocketPrivate *priv;
1021 gboolean already_disconnected = FALSE;
1023 g_return_if_fail (SOUP_IS_SOCKET (sock));
1024 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1026 if (g_mutex_trylock (priv->iolock)) {
1027 if (priv->iochannel)
1028 disconnect_internal (priv);
1030 already_disconnected = TRUE;
1031 g_mutex_unlock (priv->iolock);
1035 /* Another thread is currently doing IO, so
1036 * we can't close the iochannel. So just shutdown
1037 * the file descriptor to force the I/O to fail.
1038 * (It will actually be closed when the socket is
1041 sockfd = priv->sockfd;
1045 already_disconnected = TRUE;
1047 shutdown (sockfd, SHUT_RDWR);
1050 if (already_disconnected)
1053 /* Give all readers a chance to notice the connection close */
1054 g_signal_emit (sock, signals[READABLE], 0);
1056 /* FIXME: can't disconnect until all data is read */
1058 /* Then let everyone know we're disconnected */
1059 g_signal_emit (sock, signals[DISCONNECTED], 0);
1063 * soup_socket_is_connected:
1064 * @sock: a #SoupSocket
1066 * Tests if @sock is connected to another host
1068 * Return value: %TRUE or %FALSE.
1071 soup_socket_is_connected (SoupSocket *sock)
1073 SoupSocketPrivate *priv;
1075 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1076 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1078 return priv->iochannel != NULL;
1082 * soup_socket_get_local_address:
1083 * @sock: a #SoupSocket
1085 * Returns the #SoupAddress corresponding to the local end of @sock.
1087 * Return value: the #SoupAddress
1090 soup_socket_get_local_address (SoupSocket *sock)
1092 SoupSocketPrivate *priv;
1094 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1095 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1097 g_mutex_lock (priv->addrlock);
1098 if (!priv->local_addr) {
1099 struct soup_sockaddr_max bound_sa;
1102 sa_len = sizeof (bound_sa);
1103 getsockname (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
1104 priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
1106 g_mutex_unlock (priv->addrlock);
1108 return priv->local_addr;
1112 * soup_socket_get_remote_address:
1113 * @sock: a #SoupSocket
1115 * Returns the #SoupAddress corresponding to the remote end of @sock.
1117 * Return value: the #SoupAddress
1120 soup_socket_get_remote_address (SoupSocket *sock)
1122 SoupSocketPrivate *priv;
1124 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1125 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1127 g_mutex_lock (priv->addrlock);
1128 if (!priv->remote_addr) {
1129 struct soup_sockaddr_max bound_sa;
1132 sa_len = sizeof (bound_sa);
1133 getpeername (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
1134 priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
1136 g_mutex_unlock (priv->addrlock);
1138 return priv->remote_addr;
1143 socket_timeout (gpointer sock)
1145 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1146 gboolean readable = FALSE, writable = FALSE;
1148 priv->timed_out = TRUE;
1149 if (priv->read_timeout) {
1150 priv->read_timeout = NULL;
1153 if (priv->write_timeout) {
1154 priv->write_timeout = NULL;
1159 g_signal_emit (sock, signals[READABLE], 0);
1161 g_signal_emit (sock, signals[WRITABLE], 0);
1167 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1169 SoupSocket *sock = user_data;
1170 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1172 priv->read_src = NULL;
1173 if (priv->read_timeout) {
1174 g_source_destroy (priv->read_timeout);
1175 priv->read_timeout = NULL;
1178 if (cond & (G_IO_ERR | G_IO_HUP))
1179 soup_socket_disconnect (sock);
1181 g_signal_emit (sock, signals[READABLE], 0);
1186 static SoupSocketIOStatus
1187 read_from_network (SoupSocket *sock, gpointer buffer, gsize len,
1188 gsize *nread, GError **error)
1190 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1192 GIOCondition cond = G_IO_IN;
1193 GError *my_err = NULL;
1197 if (!priv->iochannel)
1198 return SOUP_SOCKET_EOF;
1200 if (priv->timed_out)
1201 return SOUP_SOCKET_ERROR;
1203 status = g_io_channel_read_chars (priv->iochannel,
1204 buffer, len, nread, &my_err);
1206 if (my_err->domain == SOUP_SSL_ERROR &&
1207 my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE)
1209 g_propagate_error (error, my_err);
1213 case G_IO_STATUS_NORMAL:
1214 case G_IO_STATUS_AGAIN:
1216 g_clear_error (error);
1217 return SOUP_SOCKET_OK;
1220 /* If the socket is sync and we get EAGAIN, then it is
1221 * a socket timeout and should be treated as an error
1224 if (!priv->non_blocking)
1225 return SOUP_SOCKET_ERROR;
1227 if (!priv->read_src) {
1229 soup_add_io_watch (priv->async_context,
1231 cond | G_IO_HUP | G_IO_ERR,
1232 socket_read_watch, sock);
1233 if (priv->timeout) {
1234 priv->read_timeout =
1235 soup_add_timeout (priv->async_context,
1236 priv->timeout * 1000,
1237 socket_timeout, sock);
1240 g_clear_error (error);
1241 return SOUP_SOCKET_WOULD_BLOCK;
1243 case G_IO_STATUS_EOF:
1244 g_clear_error (error);
1245 return SOUP_SOCKET_EOF;
1248 return SOUP_SOCKET_ERROR;
1252 static SoupSocketIOStatus
1253 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
1255 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1256 GByteArray *read_buf = priv->read_buf;
1258 *nread = MIN (read_buf->len, len);
1259 memcpy (buffer, read_buf->data, *nread);
1261 if (*nread == read_buf->len) {
1262 g_byte_array_free (read_buf, TRUE);
1263 priv->read_buf = NULL;
1265 memmove (read_buf->data, read_buf->data + *nread,
1266 read_buf->len - *nread);
1267 g_byte_array_set_size (read_buf, read_buf->len - *nread);
1270 return SOUP_SOCKET_OK;
1274 * SoupSocketIOStatus:
1275 * @SOUP_SOCKET_OK: Success
1276 * @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time
1277 * @SOUP_SOCKET_EOF: End of file
1278 * @SOUP_SOCKET_ERROR: Other error
1280 * Return value from the #SoupSocket IO methods.
1286 * @buffer: buffer to read into
1287 * @len: size of @buffer in bytes
1288 * @nread: on return, the number of bytes read into @buffer
1289 * @cancellable: a #GCancellable, or %NULL
1290 * @error: error pointer
1292 * Attempts to read up to @len bytes from @sock into @buffer. If some
1293 * data is successfully read, soup_socket_read() will return
1294 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
1295 * actually read (which may be less than @len).
1297 * If @sock is non-blocking, and no data is available, the return
1298 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
1299 * can connect to the #SoupSocket::readable signal to know when there
1300 * is more data to read. (NB: You MUST read all available data off the
1301 * socket first. #SoupSocket::readable is only emitted after
1302 * soup_socket_read() returns %SOUP_SOCKET_WOULD_BLOCK, and it is only
1303 * emitted once. See the documentation for #SoupSocket:non-blocking.)
1305 * Return value: a #SoupSocketIOStatus, as described above (or
1306 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
1307 * %SOUP_SOCKET_ERROR on any other error, in which case @error will
1311 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
1312 gsize *nread, GCancellable *cancellable, GError **error)
1314 SoupSocketPrivate *priv;
1315 SoupSocketIOStatus status;
1317 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1318 g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1320 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1322 g_mutex_lock (priv->iolock);
1324 status = read_from_buf (sock, buffer, len, nread);
1326 status = read_from_network (sock, buffer, len, nread, error);
1327 g_mutex_unlock (priv->iolock);
1333 * soup_socket_read_until:
1335 * @buffer: buffer to read into
1336 * @len: size of @buffer in bytes
1337 * @boundary: boundary to read until
1338 * @boundary_len: length of @boundary in bytes
1339 * @nread: on return, the number of bytes read into @buffer
1340 * @got_boundary: on return, whether or not the data in @buffer
1341 * ends with the boundary string
1342 * @cancellable: a #GCancellable, or %NULL
1343 * @error: error pointer
1345 * Like soup_socket_read(), but reads no further than the first
1346 * occurrence of @boundary. (If the boundary is found, it will be
1347 * included in the returned data, and *@got_boundary will be set to
1348 * %TRUE.) Any data after the boundary will returned in future reads.
1350 * soup_socket_read_until() will almost always return fewer than @len
1351 * bytes: if the boundary is found, then it will only return the bytes
1352 * up until the end of the boundary, and if the boundary is not found,
1353 * then it will leave the last <literal>(boundary_len - 1)</literal>
1354 * bytes in its internal buffer, in case they form the start of the
1355 * boundary string. Thus, @len normally needs to be at least 1 byte
1356 * longer than @boundary_len if you want to make any progress at all.
1358 * Return value: as for soup_socket_read()
1361 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1362 gconstpointer boundary, gsize boundary_len,
1363 gsize *nread, gboolean *got_boundary,
1364 GCancellable *cancellable, GError **error)
1366 SoupSocketPrivate *priv;
1367 SoupSocketIOStatus status;
1368 GByteArray *read_buf;
1369 guint match_len, prev_len;
1372 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1373 g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1374 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1376 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1378 g_mutex_lock (priv->iolock);
1380 *got_boundary = FALSE;
1382 if (!priv->read_buf)
1383 priv->read_buf = g_byte_array_new ();
1384 read_buf = priv->read_buf;
1386 if (read_buf->len < boundary_len) {
1387 prev_len = read_buf->len;
1388 g_byte_array_set_size (read_buf, len);
1389 status = read_from_network (sock,
1390 read_buf->data + prev_len,
1391 len - prev_len, nread, error);
1392 read_buf->len = prev_len + *nread;
1394 if (status != SOUP_SOCKET_OK) {
1395 g_mutex_unlock (priv->iolock);
1400 /* Scan for the boundary */
1401 end = read_buf->data + read_buf->len;
1402 for (p = read_buf->data; p <= end - boundary_len; p++) {
1403 if (!memcmp (p, boundary, boundary_len)) {
1405 *got_boundary = TRUE;
1410 /* Return everything up to 'p' (which is either just after the
1411 * boundary, or @boundary_len - 1 bytes before the end of the
1414 match_len = p - read_buf->data;
1415 status = read_from_buf (sock, buffer, MIN (len, match_len), nread);
1417 g_mutex_unlock (priv->iolock);
1422 socket_write_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1424 SoupSocket *sock = user_data;
1425 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1427 priv->write_src = NULL;
1428 if (priv->write_timeout) {
1429 g_source_destroy (priv->write_timeout);
1430 priv->write_timeout = NULL;
1433 if (cond & (G_IO_ERR | G_IO_HUP))
1434 soup_socket_disconnect (sock);
1436 g_signal_emit (sock, signals[WRITABLE], 0);
1442 * soup_socket_write:
1444 * @buffer: data to write
1445 * @len: size of @buffer, in bytes
1446 * @nwrote: on return, number of bytes written
1447 * @cancellable: a #GCancellable, or %NULL
1448 * @error: error pointer
1450 * Attempts to write @len bytes from @buffer to @sock. If some data is
1451 * successfully written, the return status will be %SOUP_SOCKET_OK,
1452 * and *@nwrote will contain the number of bytes actually written
1453 * (which may be less than @len).
1455 * If @sock is non-blocking, and no data could be written right away,
1456 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1457 * the caller can connect to the #SoupSocket::writable signal to know
1458 * when more data can be written. (NB: #SoupSocket::writable is only
1459 * emitted after soup_socket_write() returns %SOUP_SOCKET_WOULD_BLOCK,
1460 * and it is only emitted once. See the documentation for
1461 * #SoupSocket:non-blocking.)
1463 * Return value: a #SoupSocketIOStatus, as described above (or
1464 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the
1465 * return value is %SOUP_SOCKET_ERROR.)
1468 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1469 gsize len, gsize *nwrote,
1470 GCancellable *cancellable, GError **error)
1472 SoupSocketPrivate *priv;
1474 GIOCondition cond = G_IO_OUT;
1475 GError *my_err = NULL;
1477 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1478 g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR);
1480 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1482 g_mutex_lock (priv->iolock);
1484 if (!priv->iochannel) {
1485 g_mutex_unlock (priv->iolock);
1486 return SOUP_SOCKET_EOF;
1488 if (priv->timed_out) {
1489 g_mutex_unlock (priv->iolock);
1490 return SOUP_SOCKET_ERROR;
1492 if (priv->write_src) {
1493 g_mutex_unlock (priv->iolock);
1494 return SOUP_SOCKET_WOULD_BLOCK;
1497 status = g_io_channel_write_chars (priv->iochannel,
1498 buffer, len, nwrote, &my_err);
1500 if (my_err->domain == SOUP_SSL_ERROR &&
1501 my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ)
1503 g_propagate_error (error, my_err);
1506 /* If the socket is sync and we get EAGAIN, then it is a
1507 * socket timeout and should be treated as an error condition.
1509 if (!priv->non_blocking && status == G_IO_STATUS_AGAIN) {
1510 g_mutex_unlock (priv->iolock);
1511 return SOUP_SOCKET_ERROR;
1514 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
1515 g_mutex_unlock (priv->iolock);
1516 return SOUP_SOCKET_ERROR;
1519 g_clear_error (error);
1522 g_mutex_unlock (priv->iolock);
1523 return SOUP_SOCKET_OK;
1527 soup_add_io_watch (priv->async_context,
1529 cond | G_IO_HUP | G_IO_ERR,
1530 socket_write_watch, sock);
1531 if (priv->timeout) {
1532 priv->write_timeout = soup_add_timeout (priv->async_context,
1533 priv->timeout * 1000,
1534 socket_timeout, sock);
1537 g_mutex_unlock (priv->iolock);
1538 return SOUP_SOCKET_WOULD_BLOCK;