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-private.h"
19 #include "soup-socket.h"
20 #include "soup-marshal.h"
23 #include <sys/socket.h>
24 #include <netinet/tcp.h>
26 #define PARENT_TYPE G_TYPE_OBJECT
27 static GObjectClass *parent_class;
38 static guint signals[LAST_SIGNAL] = { 0 };
40 struct SoupSocketPrivate {
42 SoupAddress *local_addr, *remote_addr;
43 GIOChannel *iochannel;
48 guint read_tag, write_tag, error_tag;
53 init (GObject *object)
55 SoupSocket *sock = SOUP_SOCKET (object);
57 sock->priv = g_new0 (SoupSocketPrivate, 1);
58 sock->priv->sockfd = -1;
62 disconnect_internal (SoupSocket *sock)
64 g_io_channel_unref (sock->priv->iochannel);
65 sock->priv->iochannel = NULL;
67 if (sock->priv->read_tag) {
68 g_source_remove (sock->priv->read_tag);
69 sock->priv->read_tag = 0;
71 if (sock->priv->write_tag) {
72 g_source_remove (sock->priv->write_tag);
73 sock->priv->write_tag = 0;
75 if (sock->priv->error_tag) {
76 g_source_remove (sock->priv->error_tag);
77 sock->priv->error_tag = 0;
82 finalize (GObject *object)
84 SoupSocket *sock = SOUP_SOCKET (object);
86 if (sock->priv->iochannel)
87 disconnect_internal (sock);
89 if (sock->priv->local_addr)
90 g_object_unref (sock->priv->local_addr);
91 if (sock->priv->remote_addr)
92 g_object_unref (sock->priv->remote_addr);
94 if (sock->priv->watch)
95 g_source_remove (sock->priv->watch);
99 G_OBJECT_CLASS (parent_class)->finalize (object);
103 class_init (GObjectClass *object_class)
105 parent_class = g_type_class_ref (PARENT_TYPE);
107 /* virtual method override */
108 object_class->finalize = finalize;
111 signals[CONNECT_RESULT] =
112 g_signal_new ("connect_result",
113 G_OBJECT_CLASS_TYPE (object_class),
115 G_STRUCT_OFFSET (SoupSocketClass, connect_result),
117 soup_marshal_NONE__INT,
121 g_signal_new ("readable",
122 G_OBJECT_CLASS_TYPE (object_class),
124 G_STRUCT_OFFSET (SoupSocketClass, readable),
126 soup_marshal_NONE__NONE,
129 g_signal_new ("writable",
130 G_OBJECT_CLASS_TYPE (object_class),
132 G_STRUCT_OFFSET (SoupSocketClass, writable),
134 soup_marshal_NONE__NONE,
136 signals[DISCONNECTED] =
137 g_signal_new ("disconnected",
138 G_OBJECT_CLASS_TYPE (object_class),
140 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
142 soup_marshal_NONE__NONE,
144 signals[NEW_CONNECTION] =
145 g_signal_new ("new_connection",
146 G_OBJECT_CLASS_TYPE (object_class),
148 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
150 soup_marshal_NONE__OBJECT,
155 SOUP_MAKE_TYPE (soup_socket, SoupSocket, class_init, init, PARENT_TYPE)
161 * Return value: a new (disconnected) socket
164 soup_socket_new (void)
166 return g_object_new (SOUP_TYPE_SOCKET, NULL);
170 soup_socket_set_flag (SoupSocket *sock, SoupSocketFlag flag, gboolean value)
174 g_return_if_fail (SOUP_IS_SOCKET (sock));
175 g_return_if_fail (sock->priv->sockfd != -1);
178 case SOUP_SOCKET_FLAG_NONBLOCKING:
179 fdflags = fcntl (sock->priv->sockfd, F_GETFL, 0);
180 g_return_if_fail (fdflags != -1);
183 fdflags |= O_NONBLOCK;
185 fdflags &= ~O_NONBLOCK;
187 fcntl (sock->priv->sockfd, F_SETFL, fdflags);
190 case SOUP_SOCKET_FLAG_NODELAY:
191 opt = (value != FALSE);
192 setsockopt (sock->priv->sockfd, IPPROTO_TCP, TCP_NODELAY,
196 case SOUP_SOCKET_FLAG_REUSEADDR:
197 opt = (value != FALSE);
198 setsockopt (sock->priv->sockfd, SOL_SOCKET, SO_REUSEADDR,
205 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
207 SoupSocket *sock = data;
209 int len = sizeof (error);
211 /* Remove the watch now in case we don't return immediately */
212 g_source_remove (sock->priv->watch);
213 sock->priv->watch = 0;
215 if (condition & ~(G_IO_IN | G_IO_OUT))
218 if (getsockopt (sock->priv->sockfd, SOL_SOCKET, SO_ERROR,
225 soup_socket_start_ssl (sock);
227 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_ERROR_OK);
231 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_ERROR_CANT_CONNECT);
236 idle_connect_result (gpointer user_data)
238 SoupSocket *sock = user_data;
240 sock->priv->watch = 0;
242 g_signal_emit (sock, signals[CONNECT_RESULT], 0,
243 sock->priv->sockfd != -1 ? SOUP_ERROR_OK : SOUP_ERROR_CANT_CONNECT);
248 got_address (SoupAddress *addr, SoupKnownErrorCode status, gpointer user_data)
250 SoupSocket *sock = user_data;
252 if (!SOUP_ERROR_IS_SUCCESSFUL (status)) {
253 g_signal_emit (sock, signals[CONNECT_RESULT], 0, status);
257 soup_socket_connect (sock, addr);
258 /* soup_socket_connect re-reffed addr */
259 g_object_unref (addr);
263 * soup_socket_connect:
264 * @sock: a #SoupSocket (which must not be connected or listening)
265 * @remote_addr: address to connect to
267 * Starts connecting to the indicated remote address and port. The
268 * socket will emit %connect_result when it succeeds or fails (but
269 * not before returning from this function).
272 soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
274 struct sockaddr *sa = NULL;
277 g_return_if_fail (SOUP_IS_SOCKET (sock));
278 g_return_if_fail (SOUP_IS_ADDRESS (remote_addr));
279 g_return_if_fail (sock->priv->sockfd == -1);
281 sock->priv->remote_addr = g_object_ref (remote_addr);
282 sa = soup_address_get_sockaddr (sock->priv->remote_addr, &len);
284 soup_address_resolve (sock->priv->remote_addr,
289 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
290 if (sock->priv->sockfd < 0)
292 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_NONBLOCKING, TRUE);
293 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_NODELAY, TRUE);
295 /* Connect (non-blocking) */
296 status = connect (sock->priv->sockfd, sa, len);
301 /* Connect already succeeded */
302 sock->priv->watch = g_idle_add (idle_connect_result, sock);
305 if (errno != EINPROGRESS)
308 soup_socket_get_iochannel (sock);
309 sock->priv->watch = g_io_add_watch (sock->priv->iochannel,
310 (G_IO_IN | G_IO_OUT | G_IO_PRI |
311 G_IO_ERR | G_IO_HUP | G_IO_NVAL),
312 connect_watch, sock);
318 if (sock->priv->sockfd != -1) {
319 close (sock->priv->sockfd);
320 sock->priv->sockfd = -1;
322 sock->priv->watch = g_idle_add (idle_connect_result, sock);
326 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
328 SoupSocket *sock = data, *new;
329 struct soup_sockaddr_max sa;
332 if (condition & (G_IO_HUP | G_IO_ERR)) {
333 g_source_remove (sock->priv->watch);
334 sock->priv->watch = 0;
338 sa_len = sizeof (sa);
339 sockfd = accept (sock->priv->sockfd, (struct sockaddr *)&sa, &sa_len);
343 new = soup_socket_new ();
344 new->priv->sockfd = sockfd;
345 soup_socket_set_flag (new, SOUP_SOCKET_FLAG_NONBLOCKING, TRUE);
346 soup_socket_set_flag (new, SOUP_SOCKET_FLAG_NODELAY, TRUE);
348 new->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
350 new->priv->server = TRUE;
351 if (sock->priv->ssl) {
352 new->priv->ssl = TRUE;
353 soup_socket_start_ssl (new);
355 soup_socket_get_iochannel (new);
357 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
358 g_object_unref (new);
364 * soup_socket_listen:
365 * @sock: a #SoupSocket (which must not be connected or listening)
366 * @local_addr: Local address to bind to.
368 * Makes @sock start listening on the given interface and port. When
369 * connections come in, @sock will emit %new_connection.
371 * Return value: whether or not @sock is now listening.
374 soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
379 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
380 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), FALSE);
381 g_return_val_if_fail (sock->priv->sockfd == -1, FALSE);
383 /* @local_addr may have its port set to 0. So we intentionally
384 * don't store it in sock->priv->local_addr, so that if the
385 * caller calls soup_socket_get_local_address() later, we'll
386 * have to make a new addr by calling getsockname(), which
387 * will have the right port number.
389 sa = soup_address_get_sockaddr (local_addr, &sa_len);
390 g_return_val_if_fail (sa != NULL, FALSE);
392 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
393 if (sock->priv->sockfd < 0)
395 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_NONBLOCKING, TRUE);
396 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_REUSEADDR, TRUE);
399 if (bind (sock->priv->sockfd, sa, sa_len) != 0)
403 if (listen (sock->priv->sockfd, 10) != 0)
406 sock->priv->server = TRUE;
408 soup_socket_get_iochannel (sock);
409 sock->priv->watch = g_io_add_watch (sock->priv->iochannel,
410 G_IO_IN | G_IO_ERR | G_IO_HUP,
415 if (sock->priv->sockfd != -1) {
416 close (sock->priv->sockfd);
417 sock->priv->sockfd = -1;
425 * soup_socket_start_ssl:
426 * @socket: the socket
428 * Starts using SSL on @socket.
431 soup_socket_start_ssl (SoupSocket *sock)
435 chan = soup_socket_get_iochannel (sock);
436 sock->priv->iochannel = sock->priv->server ?
437 soup_ssl_get_server_iochannel (chan) :
438 soup_ssl_get_iochannel (chan);
439 sock->priv->ssl = TRUE;
444 * soup_socket_client_new:
445 * @hostname: remote machine to connect to
446 * @port: remote port to connect to
447 * @ssl: whether or not to use SSL
448 * @callback: callback to call when the socket is connected
449 * @user_data: data for @callback
451 * Creates a connection to @hostname and @port. @callback will be
452 * called when the connection completes (or fails).
454 * Return value: the new socket (not yet ready for use).
457 soup_socket_client_new (const char *hostname, guint port, gboolean ssl,
458 SoupSocketCallback callback, gpointer user_data)
462 g_return_val_if_fail (hostname != NULL, NULL);
464 sock = soup_socket_new ();
465 sock->priv->ssl = ssl;
466 soup_socket_connect (sock, soup_address_new (hostname, port));
469 soup_signal_connect_once (sock, "connect_result",
470 G_CALLBACK (callback), user_data);
476 * soup_socket_server_new:
477 * @local_addr: Local address to bind to. (Use soup_address_any_new() to
478 * accept connections on any local address)
479 * @ssl: Whether or not this is an SSL server.
480 * @callback: Callback to call when a client connects
481 * @user_data: data to pass to @callback.
483 * Create and open a new #SoupSocket listening on the specified
484 * address. @callback will be called each time a client connects,
485 * with a new #SoupSocket.
487 * Returns: a new #SoupSocket, or NULL if there was a failure.
490 soup_socket_server_new (SoupAddress *local_addr, gboolean ssl,
491 SoupSocketListenerCallback callback,
496 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), NULL);
498 sock = soup_socket_new ();
499 sock->priv->ssl = ssl;
501 if (!soup_socket_listen (sock, local_addr)) {
502 g_object_unref (sock);
507 g_signal_connect (sock, "new_connection",
508 G_CALLBACK (callback), user_data);
516 * soup_socket_get_iochannel:
517 * @sock: #SoupSocket to get #GIOChannel from.
519 * Get the #GIOChannel for the #SoupSocket.
521 * If you ref the iochannel, it will remain valid after @sock is
524 * Returns: A #GIOChannel; %NULL on failure.
527 soup_socket_get_iochannel (SoupSocket *sock)
529 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
531 if (!sock->priv->iochannel) {
532 sock->priv->iochannel =
533 g_io_channel_unix_new (sock->priv->sockfd);
534 g_io_channel_set_close_on_unref (sock->priv->iochannel, TRUE);
535 g_io_channel_set_encoding (sock->priv->iochannel, NULL, NULL);
536 g_io_channel_set_buffered (sock->priv->iochannel, FALSE);
538 return sock->priv->iochannel;
542 soup_socket_disconnect (SoupSocket *sock)
544 g_return_if_fail (SOUP_IS_SOCKET (sock));
546 if (!sock->priv->iochannel)
549 disconnect_internal (sock);
551 /* Give all readers a chance to notice the connection close */
552 g_signal_emit (sock, signals[READABLE], 0);
554 /* FIXME: can't disconnect until all data is read */
556 /* Then let everyone know we're disconnected */
557 g_signal_emit (sock, signals[DISCONNECTED], 0);
561 soup_socket_is_connected (SoupSocket *sock)
563 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
565 return sock->priv->iochannel != NULL;
570 soup_socket_get_local_address (SoupSocket *sock)
572 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
574 if (!sock->priv->local_addr) {
575 struct soup_sockaddr_max bound_sa;
578 sa_len = sizeof (bound_sa);
579 getsockname (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
580 sock->priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
583 return sock->priv->local_addr;
587 soup_socket_get_remote_address (SoupSocket *sock)
589 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
591 if (!sock->priv->local_addr) {
592 struct soup_sockaddr_max bound_sa;
595 sa_len = sizeof (bound_sa);
596 getpeername (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
597 sock->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
600 return sock->priv->remote_addr;
607 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
609 SoupSocket *sock = user_data;
611 sock->priv->read_tag = 0;
612 g_signal_emit (sock, signals[READABLE], 0);
617 static SoupSocketIOStatus
618 read_from_network (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
622 if (!sock->priv->iochannel)
623 return SOUP_SOCKET_EOF;
625 status = g_io_channel_read_chars (sock->priv->iochannel,
626 buffer, len, nread, NULL);
628 case G_IO_STATUS_NORMAL:
629 case G_IO_STATUS_AGAIN:
631 return SOUP_SOCKET_OK;
633 if (!sock->priv->read_tag) {
634 sock->priv->read_tag =
635 g_io_add_watch (sock->priv->iochannel, G_IO_IN,
636 socket_read_watch, sock);
638 return SOUP_SOCKET_WOULD_BLOCK;
640 case G_IO_STATUS_EOF:
641 return SOUP_SOCKET_EOF;
644 soup_socket_disconnect (sock);
645 return SOUP_SOCKET_ERROR;
649 static SoupSocketIOStatus
650 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
652 GByteArray *read_buf = sock->priv->read_buf;
654 *nread = MIN (read_buf->len, len);
655 memcpy (buffer, read_buf->data, *nread);
657 if (*nread == read_buf->len) {
658 g_byte_array_free (read_buf, TRUE);
659 sock->priv->read_buf = NULL;
661 memcpy (read_buf->data, read_buf->data + *nread,
662 read_buf->len - *nread);
663 g_byte_array_set_size (read_buf, read_buf->len - *nread);
666 return SOUP_SOCKET_OK;
672 * @buffer: buffer to read into
673 * @len: size of @buffer in bytes
674 * @nread: on return, the number of bytes read into @buffer
676 * Attempts to read up to @len bytes from @sock into @buffer. If some
677 * data is successfully read, soup_socket_read() will return
678 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
681 * If @sock is non-blocking, and no data is available, the return
682 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
683 * can connect to the %readable signal to know when there is more data
684 * to read. (NB: You MUST read all available data off the socket
685 * first. The %readable signal will only be emitted after
686 * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
688 * Return value: a #SoupSocketIOStatus, as described above (or
689 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
690 * %SOUP_SOCKET_ERROR on any other error).
693 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
695 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
697 if (sock->priv->read_buf)
698 return read_from_buf (sock, buffer, len, nread);
700 return read_from_network (sock, buffer, len, nread);
704 * soup_socket_read_until:
706 * @buffer: buffer to read into
707 * @len: size of @buffer in bytes
708 * @boundary: boundary to read until
709 * @boundary_len: length of @boundary in bytes
710 * @nread: on return, the number of bytes read into @buffer
711 * @got_boundary: on return, whether or not the data in @buffer
712 * ends with the boundary string
714 * Like soup_socket_read(), but reads no further than the first
715 * occurrence of @boundary. (If the boundary is found, it will be
716 * included in the returned data, and *@got_boundary will be set to
717 * %TRUE.) Any data after the boundary will returned in future reads.
719 * Return value: as for soup_socket_read()
722 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
723 gconstpointer boundary, gsize boundary_len,
724 gsize *nread, gboolean *got_boundary)
726 SoupSocketIOStatus status;
727 GByteArray *read_buf;
728 guint match_len, prev_len;
731 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
732 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
734 *got_boundary = FALSE;
736 if (!sock->priv->read_buf)
737 sock->priv->read_buf = g_byte_array_new ();
738 read_buf = sock->priv->read_buf;
740 if (read_buf->len < boundary_len) {
741 prev_len = read_buf->len;
742 g_byte_array_set_size (read_buf, len);
743 status = read_from_network (sock,
744 read_buf->data + prev_len,
745 len - prev_len, nread);
746 read_buf->len = prev_len + *nread;
748 if (status != SOUP_SOCKET_OK)
752 /* Scan for the boundary */
753 end = read_buf->data + read_buf->len;
754 for (p = read_buf->data; p <= end - boundary_len; p++) {
755 if (!memcmp (p, boundary, boundary_len)) {
757 *got_boundary = TRUE;
762 /* Return everything up to 'p' (which is either just after the
763 * boundary, or @boundary_len - 1 bytes before the end of the
766 match_len = p - read_buf->data;
767 return read_from_buf (sock, buffer, MIN (len, match_len), nread);
771 socket_write_watch (GIOChannel *chan, GIOCondition condition, gpointer user_data)
773 SoupSocket *sock = user_data;
775 sock->priv->write_tag = 0;
776 g_signal_emit (sock, signals[WRITABLE], 0);
784 * @buffer: data to write
785 * @len: size of @buffer, in bytes
786 * @nwrite: on return, number of bytes written
788 * Attempts to write @len bytes from @buffer to @sock. If some data is
789 * successfully written, the resturn status will be
790 * %SOUP_SOCKET_SUCCESS, and *@nwrote will contain the number of bytes
793 * If @sock is non-blocking, and no data could be written right away,
794 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
795 * the caller can connect to the %writable signal to know when more
796 * data can be written. (NB: %writable is only emitted after a
797 * %SOUP_SOCKET_WOULD_BLOCK.)
799 * Return value: a #SoupSocketIOStatus, as described above (or
800 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR).
803 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
804 gsize len, gsize *nwrote)
807 gpointer pipe_handler;
809 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
811 if (!sock->priv->iochannel)
812 return SOUP_SOCKET_EOF;
813 if (sock->priv->write_tag)
814 return SOUP_SOCKET_WOULD_BLOCK;
816 pipe_handler = signal (SIGPIPE, SIG_IGN);
817 status = g_io_channel_write_chars (sock->priv->iochannel,
818 buffer, len, nwrote, NULL);
819 signal (SIGPIPE, pipe_handler);
820 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
821 soup_socket_disconnect (sock);
822 return SOUP_SOCKET_ERROR;
826 return SOUP_SOCKET_OK;
828 sock->priv->write_tag =
829 g_io_add_watch (sock->priv->iochannel, G_IO_OUT,
830 socket_write_watch, sock);
831 return SOUP_SOCKET_WOULD_BLOCK;