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"
24 #include <sys/types.h>
26 G_DEFINE_TYPE (SoupSocket, soup_socket, G_TYPE_OBJECT)
37 static guint signals[LAST_SIGNAL] = { 0 };
54 SoupAddress *local_addr, *remote_addr;
55 GIOChannel *iochannel;
65 guint read_tag, write_tag, error_tag;
68 GMutex *iolock, *addrlock;
70 #define SOUP_SOCKET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SOCKET, SoupSocketPrivate))
73 #define soup_sockaddr_max sockaddr_in6
75 #define soup_sockaddr_max sockaddr_in
78 static void set_property (GObject *object, guint prop_id,
79 const GValue *value, GParamSpec *pspec);
80 static void get_property (GObject *object, guint prop_id,
81 GValue *value, GParamSpec *pspec);
84 #define SOUP_CLOSE_SOCKET(socket) closesocket (socket)
85 #define SOUP_IS_SOCKET_ERROR(status) ((status) == SOCKET_ERROR)
86 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) == INVALID_SOCKET)
87 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (WSAGetLastError () == WSAEWOULDBLOCK)
89 #define SOUP_CLOSE_SOCKET(socket) close (socket)
90 #define SOUP_IS_SOCKET_ERROR(status) ((status) == -1)
91 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) < 0)
92 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (errno == EINPROGRESS)
96 soup_socket_init (SoupSocket *sock)
98 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
101 priv->non_blocking = priv->nodelay = TRUE;
102 priv->reuseaddr = TRUE;
103 priv->cloexec = FALSE;
104 priv->addrlock = g_mutex_new ();
105 priv->iolock = g_mutex_new ();
109 disconnect_internal (SoupSocketPrivate *priv)
111 g_io_channel_unref (priv->iochannel);
112 priv->iochannel = NULL;
115 if (priv->read_tag) {
116 g_source_remove (priv->read_tag);
119 if (priv->write_tag) {
120 g_source_remove (priv->write_tag);
123 if (priv->error_tag) {
124 g_source_remove (priv->error_tag);
130 finalize (GObject *object)
132 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
135 disconnect_internal (priv);
137 if (priv->local_addr)
138 g_object_unref (priv->local_addr);
139 if (priv->remote_addr)
140 g_object_unref (priv->remote_addr);
143 g_source_remove (priv->watch);
146 g_byte_array_free (priv->read_buf, TRUE);
148 g_mutex_free (priv->addrlock);
149 g_mutex_free (priv->iolock);
151 G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
155 soup_socket_class_init (SoupSocketClass *socket_class)
157 GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
159 g_type_class_add_private (socket_class, sizeof (SoupSocketPrivate));
161 /* virtual method override */
162 object_class->finalize = finalize;
163 object_class->set_property = set_property;
164 object_class->get_property = get_property;
169 * SoupSocket::connect-result:
171 * @status: the status
173 * Emitted when a connection attempt succeeds or fails. This
174 * is used internally by soup_socket_client_new_async().
176 signals[CONNECT_RESULT] =
177 g_signal_new ("connect_result",
178 G_OBJECT_CLASS_TYPE (object_class),
180 G_STRUCT_OFFSET (SoupSocketClass, connect_result),
182 soup_marshal_NONE__INT,
187 * SoupSocket::readable:
190 * Emitted when an async socket is readable. See
191 * soup_socket_read() and soup_socket_read_until().
194 g_signal_new ("readable",
195 G_OBJECT_CLASS_TYPE (object_class),
197 G_STRUCT_OFFSET (SoupSocketClass, readable),
199 soup_marshal_NONE__NONE,
203 * SoupSocket::writable:
206 * Emitted when an async socket is writable. See
207 * soup_socket_write().
210 g_signal_new ("writable",
211 G_OBJECT_CLASS_TYPE (object_class),
213 G_STRUCT_OFFSET (SoupSocketClass, writable),
215 soup_marshal_NONE__NONE,
219 * SoupSocket::disconnected:
222 * Emitted when the socket is disconnected, for whatever
225 signals[DISCONNECTED] =
226 g_signal_new ("disconnected",
227 G_OBJECT_CLASS_TYPE (object_class),
229 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
231 soup_marshal_NONE__NONE,
235 * SoupSocket::new-connection:
237 * @new: the new socket
239 * Emitted when a listening socket (set up with
240 * soup_socket_listen() or soup_socket_server_new()) receives a
243 signals[NEW_CONNECTION] =
244 g_signal_new ("new_connection",
245 G_OBJECT_CLASS_TYPE (object_class),
247 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
249 soup_marshal_NONE__OBJECT,
254 g_object_class_install_property (
255 object_class, PROP_NON_BLOCKING,
256 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
258 "Whether or not the socket uses non-blocking I/O",
261 g_object_class_install_property (
262 object_class, PROP_NODELAY,
263 g_param_spec_boolean (SOUP_SOCKET_FLAG_NODELAY,
265 "Whether or not the socket uses TCP NODELAY",
268 g_object_class_install_property (
269 object_class, PROP_REUSEADDR,
270 g_param_spec_boolean (SOUP_SOCKET_FLAG_REUSEADDR,
272 "Whether or not the socket uses the TCP REUSEADDR flag",
275 g_object_class_install_property (
276 object_class, PROP_CLOEXEC,
277 g_param_spec_boolean (SOUP_SOCKET_FLAG_CLOEXEC,
279 "Whether or not the socket will be closed automatically on exec()",
282 g_object_class_install_property (
283 object_class, PROP_IS_SERVER,
284 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
286 "Whether or not the socket is a server socket",
289 g_object_class_install_property (
290 object_class, PROP_SSL_CREDENTIALS,
291 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
293 "SSL credential information, passed from the session to the SSL implementation",
297 /* Make sure WSAStartup() gets called. */
298 soup_address_get_type ();
304 update_fdflags (SoupSocketPrivate *priv)
311 if (priv->sockfd == -1)
315 flags = fcntl (priv->sockfd, F_GETFL, 0);
317 if (priv->non_blocking)
320 flags &= ~O_NONBLOCK;
321 fcntl (priv->sockfd, F_SETFL, flags);
323 flags = fcntl (priv->sockfd, F_GETFD, 0);
328 flags &= ~FD_CLOEXEC;
329 fcntl (priv->sockfd, F_SETFD, flags);
333 if (priv->non_blocking) {
335 ioctlsocket (priv->sockfd, FIONBIO, &val);
338 ioctlsocket (priv->sockfd, FIONBIO, &val);
342 opt = (priv->nodelay != 0);
343 setsockopt (priv->sockfd, IPPROTO_TCP,
344 TCP_NODELAY, (void *) &opt, sizeof (opt));
346 opt = (priv->reuseaddr != 0);
347 setsockopt (priv->sockfd, SOL_SOCKET,
348 SO_REUSEADDR, (void *) &opt, sizeof (opt));
352 set_property (GObject *object, guint prop_id,
353 const GValue *value, GParamSpec *pspec)
355 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
358 case PROP_NON_BLOCKING:
359 priv->non_blocking = g_value_get_boolean (value);
360 update_fdflags (priv);
363 priv->nodelay = g_value_get_boolean (value);
364 update_fdflags (priv);
367 priv->reuseaddr = g_value_get_boolean (value);
368 update_fdflags (priv);
371 priv->cloexec = g_value_get_boolean (value);
372 update_fdflags (priv);
374 case PROP_SSL_CREDENTIALS:
375 priv->ssl_creds = g_value_get_pointer (value);
383 get_property (GObject *object, guint prop_id,
384 GValue *value, GParamSpec *pspec)
386 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
389 case PROP_NON_BLOCKING:
390 g_value_set_boolean (value, priv->non_blocking);
393 g_value_set_boolean (value, priv->nodelay);
396 g_value_set_boolean (value, priv->reuseaddr);
399 g_value_set_boolean (value, priv->cloexec);
402 g_value_set_boolean (value, priv->is_server);
404 case PROP_SSL_CREDENTIALS:
405 g_value_set_pointer (value, priv->ssl_creds);
415 * @optname1: name of first property to set (or %NULL)
416 * @...: value of @optname1, followed by additional property/value pairs
418 * Creates a new (disconnected) socket
420 * Return value: the new socket
423 soup_socket_new (const char *optname1, ...)
428 va_start (ap, optname1);
429 sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
437 get_iochannel (SoupSocketPrivate *priv)
439 g_mutex_lock (priv->iolock);
440 if (!priv->iochannel) {
443 g_io_channel_unix_new (priv->sockfd);
446 g_io_channel_win32_new_socket (priv->sockfd);
448 g_io_channel_set_close_on_unref (priv->iochannel, TRUE);
449 g_io_channel_set_encoding (priv->iochannel, NULL, NULL);
450 g_io_channel_set_buffered (priv->iochannel, FALSE);
452 g_mutex_unlock (priv->iolock);
453 return priv->iochannel;
457 idle_connect_result (gpointer user_data)
459 SoupSocket *sock = user_data;
460 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
464 g_signal_emit (sock, signals[CONNECT_RESULT], 0,
465 priv->sockfd != -1 ? SOUP_STATUS_OK : SOUP_STATUS_CANT_CONNECT);
470 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
472 SoupSocket *sock = data;
473 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
475 int len = sizeof (error);
477 /* Remove the watch now in case we don't return immediately */
478 g_source_remove (priv->watch);
481 if (condition & ~(G_IO_IN | G_IO_OUT))
484 if (getsockopt (priv->sockfd, SOL_SOCKET, SO_ERROR,
485 (void *) &error, &len) != 0)
490 return idle_connect_result (sock);
493 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_STATUS_CANT_CONNECT);
498 got_address (SoupAddress *addr, guint status, gpointer user_data)
500 SoupSocket *sock = user_data;
501 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
503 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
504 g_signal_emit (sock, signals[CONNECT_RESULT], 0, status);
505 g_object_unref (sock);
509 soup_socket_connect (sock, priv->remote_addr);
510 /* soup_socket_connect re-reffed addr */
511 g_object_unref (addr);
513 g_object_unref (sock);
517 * soup_socket_connect:
518 * @sock: a client #SoupSocket (which must not already be connected)
519 * @remote_addr: address to connect to
521 * If %SOUP_SOCKET_FLAG_NONBLOCKING has been set on the socket, this
522 * begins asynchronously connecting to the given address. The socket
523 * will emit %connect_result when it succeeds or fails (but not before
524 * returning from this function).
526 * If %SOUP_SOCKET_FLAG_NONBLOCKING has not been set, this will
527 * attempt to synchronously connect.
529 * Return value: %SOUP_STATUS_CONTINUE if connecting asynchronously,
530 * otherwise a success or failure code.
533 soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
535 SoupSocketPrivate *priv;
539 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
540 priv = SOUP_SOCKET_GET_PRIVATE (sock);
541 g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
542 g_return_val_if_fail (priv->sockfd == -1, SOUP_STATUS_MALFORMED);
543 g_return_val_if_fail (SOUP_IS_ADDRESS (remote_addr), SOUP_STATUS_MALFORMED);
545 priv->remote_addr = g_object_ref (remote_addr);
546 if (!priv->non_blocking) {
547 status = soup_address_resolve_sync (remote_addr);
548 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
552 sa = soup_address_get_sockaddr (priv->remote_addr, &len);
554 if (!priv->non_blocking)
555 return SOUP_STATUS_CANT_RESOLVE;
558 soup_address_resolve_async (remote_addr, got_address, sock);
559 return SOUP_STATUS_CONTINUE;
562 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
563 if (SOUP_IS_INVALID_SOCKET (priv->sockfd)) {
566 update_fdflags (priv);
568 status = connect (priv->sockfd, sa, len);
570 if (SOUP_IS_SOCKET_ERROR (status)) {
571 if (SOUP_IS_CONNECT_STATUS_INPROGRESS ()) {
572 /* Wait for connect to succeed or fail */
574 g_io_add_watch (get_iochannel (priv),
576 G_IO_PRI | G_IO_ERR |
577 G_IO_HUP | G_IO_NVAL,
578 connect_watch, sock);
579 return SOUP_STATUS_CONTINUE;
581 SOUP_CLOSE_SOCKET (priv->sockfd);
585 get_iochannel (priv);
588 if (priv->non_blocking) {
589 priv->watch = g_idle_add (idle_connect_result, sock);
590 return SOUP_STATUS_CONTINUE;
591 } else if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
592 return SOUP_STATUS_CANT_CONNECT;
594 return SOUP_STATUS_OK;
598 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
600 SoupSocket *sock = data, *new;
601 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock), *new_priv;
602 struct soup_sockaddr_max sa;
605 if (condition & (G_IO_HUP | G_IO_ERR)) {
606 g_source_remove (priv->watch);
611 sa_len = sizeof (sa);
612 sockfd = accept (priv->sockfd, (struct sockaddr *)&sa, &sa_len);
613 if (SOUP_IS_INVALID_SOCKET (sockfd))
616 new = g_object_new (SOUP_TYPE_SOCKET, NULL);
617 new_priv = SOUP_SOCKET_GET_PRIVATE (new);
618 new_priv->sockfd = sockfd;
619 new_priv->non_blocking = priv->non_blocking;
620 new_priv->nodelay = priv->nodelay;
621 new_priv->is_server = TRUE;
622 new_priv->ssl_creds = priv->ssl_creds;
623 update_fdflags (new_priv);
625 new_priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
627 if (new_priv->ssl_creds) {
628 if (!soup_socket_start_ssl (new)) {
629 g_object_unref (new);
633 get_iochannel (new_priv);
635 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
636 g_object_unref (new);
642 * soup_socket_listen:
643 * @sock: a server #SoupSocket (which must not already be connected or
645 * @local_addr: Local address to bind to.
647 * Makes @sock start listening on the given interface and port. When
648 * connections come in, @sock will emit %new_connection.
650 * Return value: whether or not @sock is now listening.
653 soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
655 SoupSocketPrivate *priv;
659 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
660 priv = SOUP_SOCKET_GET_PRIVATE (sock);
661 g_return_val_if_fail (priv->is_server, FALSE);
662 g_return_val_if_fail (priv->sockfd == -1, FALSE);
663 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), FALSE);
665 /* @local_addr may have its port set to 0. So we intentionally
666 * don't store it in priv->local_addr, so that if the
667 * caller calls soup_socket_get_local_address() later, we'll
668 * have to make a new addr by calling getsockname(), which
669 * will have the right port number.
671 sa = soup_address_get_sockaddr (local_addr, &sa_len);
672 g_return_val_if_fail (sa != NULL, FALSE);
674 priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
675 if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
677 update_fdflags (priv);
680 if (bind (priv->sockfd, sa, sa_len) != 0)
684 if (listen (priv->sockfd, 10) != 0)
687 priv->watch = g_io_add_watch (get_iochannel (priv),
688 G_IO_IN | G_IO_ERR | G_IO_HUP,
693 if (priv->sockfd != -1) {
694 SOUP_CLOSE_SOCKET (priv->sockfd);
702 * soup_socket_start_ssl:
705 * Starts using SSL on @socket.
707 * Return value: success or failure
710 soup_socket_start_ssl (SoupSocket *sock)
712 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
714 return soup_socket_start_proxy_ssl (sock, soup_address_get_name (priv->remote_addr));
718 * soup_socket_start_proxy_ssl:
720 * @ssl_host: hostname of the SSL server
722 * Starts using SSL on @socket, expecting to find a host named
725 * Return value: success or failure
728 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host)
730 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
731 GIOChannel *ssl_chan;
733 get_iochannel (priv);
734 ssl_chan = soup_ssl_wrap_iochannel (
735 priv->iochannel, priv->is_server ?
736 SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
737 ssl_host, priv->ssl_creds);
742 priv->iochannel = ssl_chan;
748 * soup_socket_client_new_async:
749 * @hostname: remote machine to connect to
750 * @port: remote port to connect to
751 * @ssl_creds: SSL credentials structure, or %NULL if not SSL
752 * @callback: callback to call when the socket is connected
753 * @user_data: data for @callback
755 * Creates a connection to @hostname and @port. @callback will be
756 * called when the connection completes (or fails).
758 * Return value: the new socket (not yet ready for use).
761 soup_socket_client_new_async (const char *hostname, guint port,
763 SoupSocketCallback callback, gpointer user_data)
767 g_return_val_if_fail (hostname != NULL, NULL);
769 sock = g_object_new (SOUP_TYPE_SOCKET,
770 SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
772 soup_socket_connect (sock, soup_address_new (hostname, port));
775 soup_signal_connect_once (sock, "connect_result",
776 G_CALLBACK (callback), user_data);
782 * soup_socket_client_new_sync:
783 * @hostname: remote machine to connect to
784 * @port: remote port to connect to
785 * @ssl_creds: SSL credentials structure, or %NULL if not SSL
786 * @status_ret: pointer to return the soup status in
788 * Creates a connection to @hostname and @port. If @status_ret is not
789 * %NULL, it will contain a status code on return.
791 * Return value: the new socket, or %NULL if it could not connect.
794 soup_socket_client_new_sync (const char *hostname, guint port,
795 gpointer ssl_creds, guint *status_ret)
798 SoupSocketPrivate *priv;
801 g_return_val_if_fail (hostname != NULL, NULL);
803 sock = g_object_new (SOUP_TYPE_SOCKET,
804 SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
806 priv = SOUP_SOCKET_GET_PRIVATE (sock);
807 priv->non_blocking = FALSE;
808 status = soup_socket_connect (sock, soup_address_new (hostname, port));
810 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
811 g_object_unref (sock);
816 *status_ret = status;
821 * soup_socket_server_new:
822 * @local_addr: Local address to bind to. (Use soup_address_any_new() to
823 * accept connections on any local address)
824 * @ssl_creds: SSL credentials, or %NULL if this is not an SSL server
825 * @callback: Callback to call when a client connects
826 * @user_data: data to pass to @callback.
828 * Create and open a new #SoupSocket listening on the specified
829 * address. @callback will be called each time a client connects,
830 * with a new #SoupSocket.
832 * Returns: a new #SoupSocket, or NULL if there was a failure.
835 soup_socket_server_new (SoupAddress *local_addr, gpointer ssl_creds,
836 SoupSocketListenerCallback callback,
840 SoupSocketPrivate *priv;
842 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), NULL);
844 sock = g_object_new (SOUP_TYPE_SOCKET,
845 SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
847 priv = SOUP_SOCKET_GET_PRIVATE (sock);
848 priv->is_server = TRUE;
849 if (!soup_socket_listen (sock, local_addr)) {
850 g_object_unref (sock);
855 g_signal_connect (sock, "new_connection",
856 G_CALLBACK (callback), user_data);
864 * soup_socket_disconnect:
865 * @sock: a #SoupSocket
867 * Disconnects @sock. Any further read or write attempts on it will
871 soup_socket_disconnect (SoupSocket *sock)
873 SoupSocketPrivate *priv;
874 gboolean already_disconnected = FALSE;
876 g_return_if_fail (SOUP_IS_SOCKET (sock));
877 priv = SOUP_SOCKET_GET_PRIVATE (sock);
879 if (g_mutex_trylock (priv->iolock)) {
881 disconnect_internal (priv);
883 already_disconnected = TRUE;
884 g_mutex_unlock (priv->iolock);
888 /* Another thread is currently doing IO, so
889 * we can't close the iochannel. So just kick
890 * the file descriptor out from under it.
893 sockfd = priv->sockfd;
896 already_disconnected = TRUE;
898 g_io_channel_set_close_on_unref (priv->iochannel,
900 SOUP_CLOSE_SOCKET (sockfd);
904 if (already_disconnected)
907 /* Give all readers a chance to notice the connection close */
908 g_signal_emit (sock, signals[READABLE], 0);
910 /* FIXME: can't disconnect until all data is read */
912 /* Then let everyone know we're disconnected */
913 g_signal_emit (sock, signals[DISCONNECTED], 0);
917 * soup_socket_is_connected:
918 * @sock: a #SoupSocket
920 * Tests if @sock is connected to another host
922 * Return value: %TRUE or %FALSE.
925 soup_socket_is_connected (SoupSocket *sock)
927 SoupSocketPrivate *priv;
929 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
930 priv = SOUP_SOCKET_GET_PRIVATE (sock);
932 return priv->iochannel != NULL;
936 * soup_socket_get_local_address:
937 * @sock: a #SoupSocket
939 * Returns the #SoupAddress corresponding to the local end of @sock.
941 * Return value: the #SoupAddress
944 soup_socket_get_local_address (SoupSocket *sock)
946 SoupSocketPrivate *priv;
948 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
949 priv = SOUP_SOCKET_GET_PRIVATE (sock);
951 g_mutex_lock (priv->addrlock);
952 if (!priv->local_addr) {
953 struct soup_sockaddr_max bound_sa;
956 sa_len = sizeof (bound_sa);
957 getsockname (priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
958 priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
960 g_mutex_unlock (priv->addrlock);
962 return priv->local_addr;
966 * soup_socket_get_remote_address:
967 * @sock: a #SoupSocket
969 * Returns the #SoupAddress corresponding to the remote end of @sock.
971 * Return value: the #SoupAddress
974 soup_socket_get_remote_address (SoupSocket *sock)
976 SoupSocketPrivate *priv;
978 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
979 priv = SOUP_SOCKET_GET_PRIVATE (sock);
981 g_mutex_lock (priv->addrlock);
982 if (!priv->remote_addr) {
983 struct soup_sockaddr_max bound_sa;
986 sa_len = sizeof (bound_sa);
987 getpeername (priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
988 priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
990 g_mutex_unlock (priv->addrlock);
992 return priv->remote_addr;
999 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1001 SoupSocket *sock = user_data;
1002 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1005 g_signal_emit (sock, signals[READABLE], 0);
1010 static SoupSocketIOStatus
1011 read_from_network (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
1013 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1015 GIOCondition cond = G_IO_IN;
1018 if (!priv->iochannel)
1019 return SOUP_SOCKET_EOF;
1021 status = g_io_channel_read_chars (priv->iochannel,
1022 buffer, len, nread, &err);
1024 if (err->domain == SOUP_SSL_ERROR &&
1025 err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE)
1027 g_object_set_data_full (G_OBJECT (sock),
1028 "SoupSocket-last_error",
1029 err, (GDestroyNotify)g_error_free);
1031 g_object_set_data (G_OBJECT (sock),
1032 "SoupSocket-last_error",
1037 case G_IO_STATUS_NORMAL:
1038 case G_IO_STATUS_AGAIN:
1040 return SOUP_SOCKET_OK;
1042 if (!priv->read_tag) {
1044 g_io_add_watch (priv->iochannel, cond,
1045 socket_read_watch, sock);
1047 return SOUP_SOCKET_WOULD_BLOCK;
1049 case G_IO_STATUS_EOF:
1050 return SOUP_SOCKET_EOF;
1053 return SOUP_SOCKET_ERROR;
1057 static SoupSocketIOStatus
1058 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
1060 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1061 GByteArray *read_buf = priv->read_buf;
1063 *nread = MIN (read_buf->len, len);
1064 memcpy (buffer, read_buf->data, *nread);
1066 if (*nread == read_buf->len) {
1067 g_byte_array_free (read_buf, TRUE);
1068 priv->read_buf = NULL;
1070 memmove (read_buf->data, read_buf->data + *nread,
1071 read_buf->len - *nread);
1072 g_byte_array_set_size (read_buf, read_buf->len - *nread);
1075 return SOUP_SOCKET_OK;
1081 * @buffer: buffer to read into
1082 * @len: size of @buffer in bytes
1083 * @nread: on return, the number of bytes read into @buffer
1085 * Attempts to read up to @len bytes from @sock into @buffer. If some
1086 * data is successfully read, soup_socket_read() will return
1087 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
1090 * If @sock is non-blocking, and no data is available, the return
1091 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
1092 * can connect to the %readable signal to know when there is more data
1093 * to read. (NB: You MUST read all available data off the socket
1094 * first. The %readable signal will only be emitted after
1095 * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
1097 * Return value: a #SoupSocketIOStatus, as described above (or
1098 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
1099 * %SOUP_SOCKET_ERROR on any other error).
1102 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
1104 SoupSocketPrivate *priv;
1105 SoupSocketIOStatus status;
1107 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1108 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1110 g_mutex_lock (priv->iolock);
1112 status = read_from_buf (sock, buffer, len, nread);
1114 status = read_from_network (sock, buffer, len, nread);
1115 g_mutex_unlock (priv->iolock);
1121 * soup_socket_read_until:
1123 * @buffer: buffer to read into
1124 * @len: size of @buffer in bytes
1125 * @boundary: boundary to read until
1126 * @boundary_len: length of @boundary in bytes
1127 * @nread: on return, the number of bytes read into @buffer
1128 * @got_boundary: on return, whether or not the data in @buffer
1129 * ends with the boundary string
1131 * Like soup_socket_read(), but reads no further than the first
1132 * occurrence of @boundary. (If the boundary is found, it will be
1133 * included in the returned data, and *@got_boundary will be set to
1134 * %TRUE.) Any data after the boundary will returned in future reads.
1136 * Return value: as for soup_socket_read()
1139 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1140 gconstpointer boundary, gsize boundary_len,
1141 gsize *nread, gboolean *got_boundary)
1143 SoupSocketPrivate *priv;
1144 SoupSocketIOStatus status;
1145 GByteArray *read_buf;
1146 guint match_len, prev_len;
1149 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1150 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1151 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1153 g_mutex_lock (priv->iolock);
1155 *got_boundary = FALSE;
1157 if (!priv->read_buf)
1158 priv->read_buf = g_byte_array_new ();
1159 read_buf = priv->read_buf;
1161 if (read_buf->len < boundary_len) {
1162 prev_len = read_buf->len;
1163 g_byte_array_set_size (read_buf, len);
1164 status = read_from_network (sock,
1165 read_buf->data + prev_len,
1166 len - prev_len, nread);
1167 read_buf->len = prev_len + *nread;
1169 if (status != SOUP_SOCKET_OK) {
1170 g_mutex_unlock (priv->iolock);
1175 /* Scan for the boundary */
1176 end = read_buf->data + read_buf->len;
1177 for (p = read_buf->data; p <= end - boundary_len; p++) {
1178 if (!memcmp (p, boundary, boundary_len)) {
1180 *got_boundary = TRUE;
1185 /* Return everything up to 'p' (which is either just after the
1186 * boundary, or @boundary_len - 1 bytes before the end of the
1189 match_len = p - read_buf->data;
1190 status = read_from_buf (sock, buffer, MIN (len, match_len), nread);
1192 g_mutex_unlock (priv->iolock);
1197 socket_write_watch (GIOChannel *chan, GIOCondition condition, gpointer user_data)
1199 SoupSocket *sock = user_data;
1200 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1202 priv->write_tag = 0;
1203 g_signal_emit (sock, signals[WRITABLE], 0);
1209 * soup_socket_write:
1211 * @buffer: data to write
1212 * @len: size of @buffer, in bytes
1213 * @nwrote: on return, number of bytes written
1215 * Attempts to write @len bytes from @buffer to @sock. If some data is
1216 * successfully written, the resturn status will be
1217 * %SOUP_SOCKET_SUCCESS, and *@nwrote will contain the number of bytes
1220 * If @sock is non-blocking, and no data could be written right away,
1221 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1222 * the caller can connect to the %writable signal to know when more
1223 * data can be written. (NB: %writable is only emitted after a
1224 * %SOUP_SOCKET_WOULD_BLOCK.)
1226 * Return value: a #SoupSocketIOStatus, as described above (or
1227 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR).
1230 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1231 gsize len, gsize *nwrote)
1233 SoupSocketPrivate *priv;
1236 gpointer pipe_handler;
1238 GIOCondition cond = G_IO_OUT;
1241 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1242 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1244 g_mutex_lock (priv->iolock);
1246 if (!priv->iochannel) {
1247 g_mutex_unlock (priv->iolock);
1248 return SOUP_SOCKET_EOF;
1250 if (priv->write_tag) {
1251 g_mutex_unlock (priv->iolock);
1252 return SOUP_SOCKET_WOULD_BLOCK;
1256 pipe_handler = signal (SIGPIPE, SIG_IGN);
1258 status = g_io_channel_write_chars (priv->iochannel,
1259 buffer, len, nwrote, &err);
1261 signal (SIGPIPE, pipe_handler);
1264 if (err->domain == SOUP_SSL_ERROR &&
1265 err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ)
1267 g_object_set_data_full (G_OBJECT (sock),
1268 "SoupSocket-last_error",
1269 err, (GDestroyNotify)g_error_free);
1271 g_object_set_data (G_OBJECT (sock),
1272 "SoupSocket-last_error",
1276 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
1277 g_mutex_unlock (priv->iolock);
1278 return SOUP_SOCKET_ERROR;
1282 g_mutex_unlock (priv->iolock);
1283 return SOUP_SOCKET_OK;
1287 g_io_add_watch (priv->iochannel, cond,
1288 socket_write_watch, sock);
1289 g_mutex_unlock (priv->iolock);
1290 return SOUP_SOCKET_WOULD_BLOCK;