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.
18 #include "soup-address.h"
19 #include "soup-socket.h"
20 #include "soup-marshal.h"
21 #include "soup-misc.h"
25 #include <sys/types.h>
29 * @short_description: A network socket
33 G_DEFINE_TYPE (SoupSocket, soup_socket, G_TYPE_OBJECT)
43 static guint signals[LAST_SIGNAL] = { 0 };
61 SoupAddress *local_addr, *remote_addr;
62 GIOChannel *iochannel;
68 GMainContext *async_context;
70 GSource *read_src, *write_src;
73 GMutex *iolock, *addrlock;
76 #define SOUP_SOCKET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SOCKET, SoupSocketPrivate))
79 #define soup_sockaddr_max sockaddr_in6
81 #define soup_sockaddr_max sockaddr_in
84 static void set_property (GObject *object, guint prop_id,
85 const GValue *value, GParamSpec *pspec);
86 static void get_property (GObject *object, guint prop_id,
87 GValue *value, GParamSpec *pspec);
90 #define SOUP_IS_SOCKET_ERROR(status) ((status) == SOCKET_ERROR)
91 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) == INVALID_SOCKET)
92 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (WSAGetLastError () == WSAEWOULDBLOCK)
94 #define SOUP_IS_SOCKET_ERROR(status) ((status) == -1)
95 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) < 0)
96 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (errno == EINPROGRESS)
100 soup_socket_init (SoupSocket *sock)
102 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
105 priv->non_blocking = TRUE;
106 priv->addrlock = g_mutex_new ();
107 priv->iolock = g_mutex_new ();
112 disconnect_internal (SoupSocketPrivate *priv)
114 g_io_channel_unref (priv->iochannel);
115 priv->iochannel = NULL;
118 if (priv->read_src) {
119 g_source_destroy (priv->read_src);
120 priv->read_src = NULL;
122 if (priv->write_src) {
123 g_source_destroy (priv->write_src);
124 priv->write_src = NULL;
129 finalize (GObject *object)
131 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
134 disconnect_internal (priv);
136 if (priv->local_addr)
137 g_object_unref (priv->local_addr);
138 if (priv->remote_addr)
139 g_object_unref (priv->remote_addr);
142 g_source_destroy (priv->watch_src);
143 if (priv->async_context)
144 g_main_context_unref (priv->async_context);
147 g_byte_array_free (priv->read_buf, TRUE);
149 g_mutex_free (priv->addrlock);
150 g_mutex_free (priv->iolock);
152 G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
156 soup_socket_class_init (SoupSocketClass *socket_class)
158 GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
160 g_type_class_add_private (socket_class, sizeof (SoupSocketPrivate));
162 /* virtual method override */
163 object_class->finalize = finalize;
164 object_class->set_property = set_property;
165 object_class->get_property = get_property;
170 * SoupSocket::readable:
173 * Emitted when an async socket is readable. See
174 * soup_socket_read() and soup_socket_read_until().
177 g_signal_new ("readable",
178 G_OBJECT_CLASS_TYPE (object_class),
180 G_STRUCT_OFFSET (SoupSocketClass, readable),
182 soup_marshal_NONE__NONE,
186 * SoupSocket::writable:
189 * Emitted when an async socket is writable. See
190 * soup_socket_write().
193 g_signal_new ("writable",
194 G_OBJECT_CLASS_TYPE (object_class),
196 G_STRUCT_OFFSET (SoupSocketClass, writable),
198 soup_marshal_NONE__NONE,
202 * SoupSocket::disconnected:
205 * Emitted when the socket is disconnected, for whatever
208 signals[DISCONNECTED] =
209 g_signal_new ("disconnected",
210 G_OBJECT_CLASS_TYPE (object_class),
212 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
214 soup_marshal_NONE__NONE,
218 * SoupSocket::new-connection:
220 * @new: the new socket
222 * Emitted when a listening socket (set up with
223 * soup_socket_listen()) receives a new connection.
225 * You must ref the @new if you want to keep it; otherwise it
226 * will be destroyed after the signal is emitted.
228 signals[NEW_CONNECTION] =
229 g_signal_new ("new_connection",
230 G_OBJECT_CLASS_TYPE (object_class),
232 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
234 soup_marshal_NONE__OBJECT,
239 g_object_class_install_property (
240 object_class, PROP_LOCAL_ADDRESS,
241 g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
243 "Address of local end of socket",
245 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
246 g_object_class_install_property (
247 object_class, PROP_REMOTE_ADDRESS,
248 g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
250 "Address of remote end of socket",
252 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
253 g_object_class_install_property (
254 object_class, PROP_NON_BLOCKING,
255 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
257 "Whether or not the socket uses non-blocking I/O",
260 g_object_class_install_property (
261 object_class, PROP_IS_SERVER,
262 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
264 "Whether or not the socket is a server socket",
267 g_object_class_install_property (
268 object_class, PROP_SSL_CREDENTIALS,
269 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
271 "SSL credential information, passed from the session to the SSL implementation",
273 g_object_class_install_property (
274 object_class, PROP_ASYNC_CONTEXT,
275 g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
276 "Async GMainContext",
277 "The GMainContext to dispatch this socket's async I/O in",
278 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
280 g_object_class_install_property (
281 object_class, PROP_TIMEOUT,
282 g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
284 "Value in seconds to timeout a blocking I/O",
289 /* Make sure WSAStartup() gets called. */
290 soup_address_get_type ();
296 set_nonblocking (SoupSocketPrivate *priv)
304 if (priv->sockfd == -1)
308 flags = fcntl (priv->sockfd, F_GETFL, 0);
310 if (priv->non_blocking)
313 flags &= ~O_NONBLOCK;
314 fcntl (priv->sockfd, F_SETFL, flags);
317 val = priv->non_blocking ? 1 : 0;
318 ioctlsocket (priv->sockfd, FIONBIO, &val);
323 set_fdflags (SoupSocketPrivate *priv)
326 struct timeval timeout;
331 if (priv->sockfd == -1)
334 set_nonblocking (priv);
337 flags = fcntl (priv->sockfd, F_GETFD, 0);
340 fcntl (priv->sockfd, F_SETFD, flags);
345 setsockopt (priv->sockfd, IPPROTO_TCP,
346 TCP_NODELAY, (void *) &opt, sizeof (opt));
347 setsockopt (priv->sockfd, SOL_SOCKET,
348 SO_REUSEADDR, (void *) &opt, sizeof (opt));
350 timeout.tv_sec = priv->timeout;
352 setsockopt (priv->sockfd, SOL_SOCKET,
353 SO_RCVTIMEO, (void *) &timeout, sizeof (timeout));
355 timeout.tv_sec = priv->timeout;
357 setsockopt (priv->sockfd, SOL_SOCKET,
358 SO_SNDTIMEO, (void *) &timeout, sizeof (timeout));
362 g_io_channel_unix_new (priv->sockfd);
365 g_io_channel_win32_new_socket (priv->sockfd);
367 g_io_channel_set_close_on_unref (priv->iochannel, TRUE);
368 g_io_channel_set_encoding (priv->iochannel, NULL, NULL);
369 g_io_channel_set_buffered (priv->iochannel, FALSE);
373 set_property (GObject *object, guint prop_id,
374 const GValue *value, GParamSpec *pspec)
376 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
379 case PROP_LOCAL_ADDRESS:
380 priv->local_addr = (SoupAddress *)g_value_dup_object (value);
382 case PROP_REMOTE_ADDRESS:
383 priv->remote_addr = (SoupAddress *)g_value_dup_object (value);
385 case PROP_NON_BLOCKING:
386 priv->non_blocking = g_value_get_boolean (value);
387 set_nonblocking (priv);
389 case PROP_SSL_CREDENTIALS:
390 priv->ssl_creds = g_value_get_pointer (value);
392 case PROP_ASYNC_CONTEXT:
393 priv->async_context = g_value_get_pointer (value);
394 if (priv->async_context)
395 g_main_context_ref (priv->async_context);
398 priv->timeout = g_value_get_uint (value);
406 get_property (GObject *object, guint prop_id,
407 GValue *value, GParamSpec *pspec)
409 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
412 case PROP_LOCAL_ADDRESS:
413 g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
415 case PROP_REMOTE_ADDRESS:
416 g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
418 case PROP_NON_BLOCKING:
419 g_value_set_boolean (value, priv->non_blocking);
422 g_value_set_boolean (value, priv->is_server);
424 case PROP_SSL_CREDENTIALS:
425 g_value_set_pointer (value, priv->ssl_creds);
427 case PROP_ASYNC_CONTEXT:
428 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
431 g_value_set_uint (value, priv->timeout);
441 * @optname1: name of first property to set (or %NULL)
442 * @...: value of @optname1, followed by additional property/value pairs
444 * Creates a new (disconnected) socket
446 * Return value: the new socket
449 soup_socket_new (const char *optname1, ...)
454 va_start (ap, optname1);
455 sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
464 GCancellable *cancellable;
466 SoupSocketCallback callback;
468 } SoupSocketAsyncConnectData;
471 idle_connect_result (gpointer user_data)
473 SoupSocketAsyncConnectData *sacd = user_data;
474 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
477 priv->watch_src = NULL;
479 g_signal_handler_disconnect (sacd->cancellable, sacd->cancel_id);
481 if (priv->sockfd == -1) {
482 if (g_cancellable_is_cancelled (sacd->cancellable))
483 status = SOUP_STATUS_CANCELLED;
485 status = SOUP_STATUS_CANT_CONNECT;
487 status = SOUP_STATUS_OK;
489 sacd->callback (sacd->sock, status, sacd->user_data);
490 g_slice_free (SoupSocketAsyncConnectData, sacd);
495 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
497 SoupSocketAsyncConnectData *sacd = data;
498 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
500 int len = sizeof (error);
502 /* Remove the watch now in case we don't return immediately */
503 g_source_destroy (priv->watch_src);
504 priv->watch_src = NULL;
506 if ((condition & ~(G_IO_IN | G_IO_OUT)) ||
507 (getsockopt (priv->sockfd, SOL_SOCKET, SO_ERROR,
508 (void *)&error, (void *)&len) != 0) ||
510 disconnect_internal (priv);
512 return idle_connect_result (sacd);
516 got_address (SoupAddress *addr, guint status, gpointer user_data)
518 SoupSocketAsyncConnectData *sacd = user_data;
520 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
521 sacd->callback (sacd->sock, status, sacd->user_data);
522 g_slice_free (SoupSocketAsyncConnectData, sacd);
526 soup_socket_connect_async (sacd->sock, sacd->cancellable,
527 sacd->callback, sacd->user_data);
528 g_slice_free (SoupSocketAsyncConnectData, sacd);
532 async_cancel (GCancellable *cancellable, gpointer user_data)
534 SoupSocketAsyncConnectData *sacd = user_data;
535 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
538 g_source_destroy (priv->watch_src);
539 disconnect_internal (priv);
540 priv->watch_src = soup_add_idle (priv->async_context,
541 idle_connect_result, sacd);
545 socket_connect_internal (SoupSocket *sock)
547 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
551 sa = soup_address_get_sockaddr (priv->remote_addr, &len);
553 return SOUP_STATUS_CANT_RESOLVE;
555 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
556 if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
557 return SOUP_STATUS_CANT_CONNECT;
560 status = connect (priv->sockfd, sa, len);
562 if (SOUP_IS_SOCKET_ERROR (status)) {
563 if (SOUP_IS_CONNECT_STATUS_INPROGRESS ())
564 return SOUP_STATUS_CONTINUE;
566 disconnect_internal (priv);
567 return SOUP_STATUS_CANT_CONNECT;
569 return SOUP_STATUS_OK;
573 * SoupSocketCallback:
574 * @sock: the #SoupSocket
575 * @status: an HTTP status code indicating success or failure
576 * @user_data: the data passed to soup_socket_connect_async()
578 * The callback function passed to soup_socket_connect_async().
582 * soup_socket_connect_async:
583 * @sock: a client #SoupSocket (which must not already be connected)
584 * @cancellable: a #GCancellable, or %NULL
585 * @callback: callback to call after connecting
586 * @user_data: data to pass to @callback
588 * Begins asynchronously connecting to @sock's remote address. The
589 * socket will call @callback when it succeeds or fails (but not
590 * before returning from this function).
592 * If @cancellable is non-%NULL, it can be used to cancel the
593 * connection. @callback will still be invoked in this case, with a
594 * status of %SOUP_STATUS_CANCELLED.
597 soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
598 SoupSocketCallback callback, gpointer user_data)
600 SoupSocketPrivate *priv;
601 SoupSocketAsyncConnectData *sacd;
604 g_return_if_fail (SOUP_IS_SOCKET (sock));
605 priv = SOUP_SOCKET_GET_PRIVATE (sock);
606 g_return_if_fail (priv->remote_addr != NULL);
608 sacd = g_slice_new0 (SoupSocketAsyncConnectData);
610 sacd->cancellable = cancellable;
611 sacd->callback = callback;
612 sacd->user_data = user_data;
614 if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
615 soup_address_resolve_async (priv->remote_addr,
622 status = socket_connect_internal (sock);
623 if (status == SOUP_STATUS_CONTINUE) {
624 /* Wait for connect to succeed or fail */
626 soup_add_io_watch (priv->async_context,
629 G_IO_PRI | G_IO_ERR |
630 G_IO_HUP | G_IO_NVAL,
631 connect_watch, sacd);
634 g_signal_connect (cancellable, "cancelled",
635 G_CALLBACK (async_cancel),
639 priv->watch_src = soup_add_idle (priv->async_context,
640 idle_connect_result, sacd);
645 sync_cancel (GCancellable *cancellable, gpointer sock)
647 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
649 shutdown (priv->sockfd, SHUT_RDWR);
653 * soup_socket_connect_sync:
654 * @sock: a client #SoupSocket (which must not already be connected)
655 * @cancellable: a #GCancellable, or %NULL
657 * Attempt to synchronously connect @sock to its remote address.
659 * If @cancellable is non-%NULL, it can be used to cancel the
660 * connection, in which case soup_socket_connect_sync() will return
661 * %SOUP_STATUS_CANCELLED.
663 * Return value: a success or failure code.
666 soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
668 SoupSocketPrivate *priv;
669 guint status, cancel_id;
671 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
672 priv = SOUP_SOCKET_GET_PRIVATE (sock);
673 g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
674 g_return_val_if_fail (priv->sockfd == -1, SOUP_STATUS_MALFORMED);
675 g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
677 if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
678 status = soup_address_resolve_sync (priv->remote_addr,
680 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
685 cancel_id = g_signal_connect (cancellable, "cancelled",
686 G_CALLBACK (sync_cancel), sock);
689 status = socket_connect_internal (sock);
692 if (status != SOUP_STATUS_OK &&
693 g_cancellable_is_cancelled (cancellable)) {
694 status = SOUP_STATUS_CANCELLED;
695 disconnect_internal (priv);
697 g_signal_handler_disconnect (cancellable, cancel_id);
704 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
706 SoupSocket *sock = data, *new;
707 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock), *new_priv;
708 struct soup_sockaddr_max sa;
711 if (condition & (G_IO_HUP | G_IO_ERR)) {
712 g_source_destroy (priv->watch_src);
713 priv->watch_src = NULL;
717 sa_len = sizeof (sa);
718 sockfd = accept (priv->sockfd, (struct sockaddr *)&sa, (void *)&sa_len);
719 if (SOUP_IS_INVALID_SOCKET (sockfd))
722 new = g_object_new (SOUP_TYPE_SOCKET, NULL);
723 new_priv = SOUP_SOCKET_GET_PRIVATE (new);
724 new_priv->sockfd = sockfd;
725 if (priv->async_context)
726 new_priv->async_context = g_main_context_ref (priv->async_context);
727 new_priv->non_blocking = priv->non_blocking;
728 new_priv->is_server = TRUE;
729 new_priv->ssl_creds = priv->ssl_creds;
730 set_fdflags (new_priv);
732 new_priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
734 if (new_priv->ssl_creds) {
735 if (!soup_socket_start_ssl (new, NULL)) {
736 g_object_unref (new);
741 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
742 g_object_unref (new);
748 * soup_socket_listen:
749 * @sock: a server #SoupSocket (which must not already be connected or
752 * Makes @sock start listening on its local address. When connections
753 * come in, @sock will emit %new_connection.
755 * Return value: whether or not @sock is now listening.
758 soup_socket_listen (SoupSocket *sock)
761 SoupSocketPrivate *priv;
765 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
766 priv = SOUP_SOCKET_GET_PRIVATE (sock);
767 g_return_val_if_fail (priv->sockfd == -1, FALSE);
768 g_return_val_if_fail (priv->local_addr != NULL, FALSE);
770 priv->is_server = TRUE;
772 /* @local_addr may have its port set to 0. So we intentionally
773 * don't store it in priv->local_addr, so that if the
774 * caller calls soup_socket_get_local_address() later, we'll
775 * have to make a new addr by calling getsockname(), which
776 * will have the right port number.
778 sa = soup_address_get_sockaddr (priv->local_addr, &sa_len);
779 g_return_val_if_fail (sa != NULL, FALSE);
781 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
782 if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
787 if (bind (priv->sockfd, sa, sa_len) != 0)
789 /* Force local_addr to be re-resolved now */
790 g_object_unref (priv->local_addr);
791 priv->local_addr = NULL;
794 if (listen (priv->sockfd, 10) != 0)
797 priv->watch_src = soup_add_io_watch (priv->async_context,
799 G_IO_IN | G_IO_ERR | G_IO_HUP,
805 disconnect_internal (priv);
811 * soup_socket_start_ssl:
813 * @cancellable: a #GCancellable
815 * Starts using SSL on @socket.
817 * Return value: success or failure
820 soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
822 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
824 return soup_socket_start_proxy_ssl (sock, soup_address_get_name (priv->remote_addr), cancellable);
828 * soup_socket_start_proxy_ssl:
830 * @ssl_host: hostname of the SSL server
831 * @cancellable: a #GCancellable
833 * Starts using SSL on @socket, expecting to find a host named
836 * Return value: success or failure
839 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
840 GCancellable *cancellable)
842 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
843 GIOChannel *ssl_chan;
844 GIOChannel *real_chan;
846 real_chan = priv->iochannel;
847 ssl_chan = soup_ssl_wrap_iochannel (
848 real_chan, priv->is_server ?
849 SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
850 ssl_host, priv->ssl_creds);
855 priv->iochannel = ssl_chan;
856 g_io_channel_unref (real_chan);
862 soup_socket_is_ssl (SoupSocket *sock)
864 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
866 return priv->ssl_creds != NULL;
870 * soup_socket_disconnect:
871 * @sock: a #SoupSocket
873 * Disconnects @sock. Any further read or write attempts on it will
877 soup_socket_disconnect (SoupSocket *sock)
879 SoupSocketPrivate *priv;
880 gboolean already_disconnected = FALSE;
882 g_return_if_fail (SOUP_IS_SOCKET (sock));
883 priv = SOUP_SOCKET_GET_PRIVATE (sock);
885 if (g_mutex_trylock (priv->iolock)) {
887 disconnect_internal (priv);
889 already_disconnected = TRUE;
890 g_mutex_unlock (priv->iolock);
894 /* Another thread is currently doing IO, so
895 * we can't close the iochannel. So just shutdown
896 * the file descriptor to force the I/O to fail.
897 * (It will actually be closed when the socket is
900 sockfd = priv->sockfd;
904 already_disconnected = TRUE;
906 shutdown (sockfd, SHUT_RDWR);
909 if (already_disconnected)
912 /* Give all readers a chance to notice the connection close */
913 g_signal_emit (sock, signals[READABLE], 0);
915 /* FIXME: can't disconnect until all data is read */
917 /* Then let everyone know we're disconnected */
918 g_signal_emit (sock, signals[DISCONNECTED], 0);
922 * soup_socket_is_connected:
923 * @sock: a #SoupSocket
925 * Tests if @sock is connected to another host
927 * Return value: %TRUE or %FALSE.
930 soup_socket_is_connected (SoupSocket *sock)
932 SoupSocketPrivate *priv;
934 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
935 priv = SOUP_SOCKET_GET_PRIVATE (sock);
937 return priv->iochannel != NULL;
941 * soup_socket_get_local_address:
942 * @sock: a #SoupSocket
944 * Returns the #SoupAddress corresponding to the local end of @sock.
946 * Return value: the #SoupAddress
949 soup_socket_get_local_address (SoupSocket *sock)
951 SoupSocketPrivate *priv;
953 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
954 priv = SOUP_SOCKET_GET_PRIVATE (sock);
956 g_mutex_lock (priv->addrlock);
957 if (!priv->local_addr) {
958 struct soup_sockaddr_max bound_sa;
961 sa_len = sizeof (bound_sa);
962 getsockname (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
963 priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
965 g_mutex_unlock (priv->addrlock);
967 return priv->local_addr;
971 * soup_socket_get_remote_address:
972 * @sock: a #SoupSocket
974 * Returns the #SoupAddress corresponding to the remote end of @sock.
976 * Return value: the #SoupAddress
979 soup_socket_get_remote_address (SoupSocket *sock)
981 SoupSocketPrivate *priv;
983 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
984 priv = SOUP_SOCKET_GET_PRIVATE (sock);
986 g_mutex_lock (priv->addrlock);
987 if (!priv->remote_addr) {
988 struct soup_sockaddr_max bound_sa;
991 sa_len = sizeof (bound_sa);
992 getpeername (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
993 priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
995 g_mutex_unlock (priv->addrlock);
997 return priv->remote_addr;
1004 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1006 SoupSocket *sock = user_data;
1007 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1009 priv->read_src = NULL;
1011 if (cond & (G_IO_ERR | G_IO_HUP))
1012 soup_socket_disconnect (sock);
1014 g_signal_emit (sock, signals[READABLE], 0);
1019 static SoupSocketIOStatus
1020 read_from_network (SoupSocket *sock, gpointer buffer, gsize len,
1021 gsize *nread, GError **error)
1023 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1025 GIOCondition cond = G_IO_IN;
1026 GError *my_err = NULL;
1028 if (!priv->iochannel)
1029 return SOUP_SOCKET_EOF;
1031 status = g_io_channel_read_chars (priv->iochannel,
1032 buffer, len, nread, &my_err);
1034 if (my_err->domain == SOUP_SSL_ERROR &&
1035 my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE)
1037 g_propagate_error (error, my_err);
1041 case G_IO_STATUS_NORMAL:
1042 case G_IO_STATUS_AGAIN:
1044 g_clear_error (error);
1045 return SOUP_SOCKET_OK;
1048 /* If the socket is sync and we get EAGAIN, then it is
1049 * a socket timeout and should be treated as an error
1052 if (!priv->non_blocking)
1053 return SOUP_SOCKET_ERROR;
1055 if (!priv->read_src) {
1057 soup_add_io_watch (priv->async_context,
1059 cond | G_IO_HUP | G_IO_ERR,
1060 socket_read_watch, sock);
1062 g_clear_error (error);
1063 return SOUP_SOCKET_WOULD_BLOCK;
1065 case G_IO_STATUS_EOF:
1066 g_clear_error (error);
1067 return SOUP_SOCKET_EOF;
1070 return SOUP_SOCKET_ERROR;
1074 static SoupSocketIOStatus
1075 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
1077 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1078 GByteArray *read_buf = priv->read_buf;
1080 *nread = MIN (read_buf->len, len);
1081 memcpy (buffer, read_buf->data, *nread);
1083 if (*nread == read_buf->len) {
1084 g_byte_array_free (read_buf, TRUE);
1085 priv->read_buf = NULL;
1087 memmove (read_buf->data, read_buf->data + *nread,
1088 read_buf->len - *nread);
1089 g_byte_array_set_size (read_buf, read_buf->len - *nread);
1092 return SOUP_SOCKET_OK;
1096 * SoupSocketIOStatus:
1097 * @SOUP_SOCKET_OK: Success
1098 * @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time
1099 * @SOUP_SOCKET_EOF: End of file
1100 * @SOUP_SOCKET_ERROR: Other error
1102 * Return value from the #SoupSocket IO methods.
1108 * @buffer: buffer to read into
1109 * @len: size of @buffer in bytes
1110 * @nread: on return, the number of bytes read into @buffer
1111 * @cancellable: a #GCancellable, or %NULL
1112 * @error: error pointer
1114 * Attempts to read up to @len bytes from @sock into @buffer. If some
1115 * data is successfully read, soup_socket_read() will return
1116 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
1119 * If @sock is non-blocking, and no data is available, the return
1120 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
1121 * can connect to the %readable signal to know when there is more data
1122 * to read. (NB: You MUST read all available data off the socket
1123 * first. The %readable signal will only be emitted after
1124 * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
1126 * Return value: a #SoupSocketIOStatus, as described above (or
1127 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
1128 * %SOUP_SOCKET_ERROR on any other error, in which case @error will
1132 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
1133 gsize *nread, GCancellable *cancellable, GError **error)
1135 SoupSocketPrivate *priv;
1136 SoupSocketIOStatus status;
1138 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1139 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1141 g_mutex_lock (priv->iolock);
1143 status = read_from_buf (sock, buffer, len, nread);
1145 status = read_from_network (sock, buffer, len, nread, error);
1146 g_mutex_unlock (priv->iolock);
1152 * soup_socket_read_until:
1154 * @buffer: buffer to read into
1155 * @len: size of @buffer in bytes
1156 * @boundary: boundary to read until
1157 * @boundary_len: length of @boundary in bytes
1158 * @nread: on return, the number of bytes read into @buffer
1159 * @got_boundary: on return, whether or not the data in @buffer
1160 * ends with the boundary string
1161 * @cancellable: a #GCancellable, or %NULL
1162 * @error: error pointer
1164 * Like soup_socket_read(), but reads no further than the first
1165 * occurrence of @boundary. (If the boundary is found, it will be
1166 * included in the returned data, and *@got_boundary will be set to
1167 * %TRUE.) Any data after the boundary will returned in future reads.
1169 * Return value: as for soup_socket_read()
1172 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1173 gconstpointer boundary, gsize boundary_len,
1174 gsize *nread, gboolean *got_boundary,
1175 GCancellable *cancellable, GError **error)
1177 SoupSocketPrivate *priv;
1178 SoupSocketIOStatus status;
1179 GByteArray *read_buf;
1180 guint match_len, prev_len;
1183 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1184 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1185 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1187 g_mutex_lock (priv->iolock);
1189 *got_boundary = FALSE;
1191 if (!priv->read_buf)
1192 priv->read_buf = g_byte_array_new ();
1193 read_buf = priv->read_buf;
1195 if (read_buf->len < boundary_len) {
1196 prev_len = read_buf->len;
1197 g_byte_array_set_size (read_buf, len);
1198 status = read_from_network (sock,
1199 read_buf->data + prev_len,
1200 len - prev_len, nread, error);
1201 read_buf->len = prev_len + *nread;
1203 if (status != SOUP_SOCKET_OK) {
1204 g_mutex_unlock (priv->iolock);
1209 /* Scan for the boundary */
1210 end = read_buf->data + read_buf->len;
1211 for (p = read_buf->data; p <= end - boundary_len; p++) {
1212 if (!memcmp (p, boundary, boundary_len)) {
1214 *got_boundary = TRUE;
1219 /* Return everything up to 'p' (which is either just after the
1220 * boundary, or @boundary_len - 1 bytes before the end of the
1223 match_len = p - read_buf->data;
1224 status = read_from_buf (sock, buffer, MIN (len, match_len), nread);
1226 g_mutex_unlock (priv->iolock);
1231 socket_write_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1233 SoupSocket *sock = user_data;
1234 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1236 priv->write_src = NULL;
1238 if (cond & (G_IO_ERR | G_IO_HUP))
1239 soup_socket_disconnect (sock);
1241 g_signal_emit (sock, signals[WRITABLE], 0);
1247 * soup_socket_write:
1249 * @buffer: data to write
1250 * @len: size of @buffer, in bytes
1251 * @nwrote: on return, number of bytes written
1252 * @cancellable: a #GCancellable, or %NULL
1253 * @error: error pointer
1255 * Attempts to write @len bytes from @buffer to @sock. If some data is
1256 * successfully written, the resturn status will be
1257 * %SOUP_SOCKET_SUCCESS, and *@nwrote will contain the number of bytes
1260 * If @sock is non-blocking, and no data could be written right away,
1261 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1262 * the caller can connect to the %writable signal to know when more
1263 * data can be written. (NB: %writable is only emitted after a
1264 * %SOUP_SOCKET_WOULD_BLOCK.)
1266 * Return value: a #SoupSocketIOStatus, as described above (or
1267 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the
1268 * return value is %SOUP_SOCKET_ERROR.)
1271 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1272 gsize len, gsize *nwrote,
1273 GCancellable *cancellable, GError **error)
1275 SoupSocketPrivate *priv;
1278 gpointer pipe_handler;
1280 GIOCondition cond = G_IO_OUT;
1281 GError *my_err = NULL;
1283 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1284 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1286 g_mutex_lock (priv->iolock);
1288 if (!priv->iochannel) {
1289 g_mutex_unlock (priv->iolock);
1290 return SOUP_SOCKET_EOF;
1292 if (priv->write_src) {
1293 g_mutex_unlock (priv->iolock);
1294 return SOUP_SOCKET_WOULD_BLOCK;
1298 pipe_handler = signal (SIGPIPE, SIG_IGN);
1300 status = g_io_channel_write_chars (priv->iochannel,
1301 buffer, len, nwrote, &my_err);
1303 signal (SIGPIPE, pipe_handler);
1306 if (my_err->domain == SOUP_SSL_ERROR &&
1307 my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ)
1309 g_propagate_error (error, my_err);
1312 /* If the socket is sync and we get EAGAIN, then it is a
1313 * socket timeout and should be treated as an error condition.
1315 if (!priv->non_blocking && status == G_IO_STATUS_AGAIN) {
1316 g_mutex_unlock (priv->iolock);
1317 return SOUP_SOCKET_ERROR;
1320 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
1321 g_mutex_unlock (priv->iolock);
1322 return SOUP_SOCKET_ERROR;
1325 g_clear_error (error);
1328 g_mutex_unlock (priv->iolock);
1329 return SOUP_SOCKET_OK;
1333 soup_add_io_watch (priv->async_context,
1335 cond | G_IO_HUP | G_IO_ERR,
1336 socket_write_watch, sock);
1337 g_mutex_unlock (priv->iolock);
1338 return SOUP_SOCKET_WOULD_BLOCK;