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-private.h"
20 #include "soup-socket.h"
21 #include "soup-marshal.h"
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <netinet/tcp.h>
29 #define PARENT_TYPE G_TYPE_OBJECT
30 static GObjectClass *parent_class;
41 static guint signals[LAST_SIGNAL] = { 0 };
43 struct SoupSocketPrivate {
45 SoupAddress *local_addr, *remote_addr;
46 GIOChannel *iochannel;
51 guint read_tag, write_tag, error_tag;
56 init (GObject *object)
58 SoupSocket *sock = SOUP_SOCKET (object);
60 sock->priv = g_new0 (SoupSocketPrivate, 1);
61 sock->priv->sockfd = -1;
65 disconnect_internal (SoupSocket *sock)
67 g_io_channel_unref (sock->priv->iochannel);
68 sock->priv->iochannel = NULL;
70 if (sock->priv->read_tag) {
71 g_source_remove (sock->priv->read_tag);
72 sock->priv->read_tag = 0;
74 if (sock->priv->write_tag) {
75 g_source_remove (sock->priv->write_tag);
76 sock->priv->write_tag = 0;
78 if (sock->priv->error_tag) {
79 g_source_remove (sock->priv->error_tag);
80 sock->priv->error_tag = 0;
85 finalize (GObject *object)
87 SoupSocket *sock = SOUP_SOCKET (object);
89 if (sock->priv->iochannel)
90 disconnect_internal (sock);
92 if (sock->priv->local_addr)
93 g_object_unref (sock->priv->local_addr);
94 if (sock->priv->remote_addr)
95 g_object_unref (sock->priv->remote_addr);
97 if (sock->priv->watch)
98 g_source_remove (sock->priv->watch);
102 G_OBJECT_CLASS (parent_class)->finalize (object);
106 class_init (GObjectClass *object_class)
108 parent_class = g_type_class_ref (PARENT_TYPE);
110 /* virtual method override */
111 object_class->finalize = finalize;
114 signals[CONNECT_RESULT] =
115 g_signal_new ("connect_result",
116 G_OBJECT_CLASS_TYPE (object_class),
118 G_STRUCT_OFFSET (SoupSocketClass, connect_result),
120 soup_marshal_NONE__INT,
124 g_signal_new ("readable",
125 G_OBJECT_CLASS_TYPE (object_class),
127 G_STRUCT_OFFSET (SoupSocketClass, readable),
129 soup_marshal_NONE__NONE,
132 g_signal_new ("writable",
133 G_OBJECT_CLASS_TYPE (object_class),
135 G_STRUCT_OFFSET (SoupSocketClass, writable),
137 soup_marshal_NONE__NONE,
139 signals[DISCONNECTED] =
140 g_signal_new ("disconnected",
141 G_OBJECT_CLASS_TYPE (object_class),
143 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
145 soup_marshal_NONE__NONE,
147 signals[NEW_CONNECTION] =
148 g_signal_new ("new_connection",
149 G_OBJECT_CLASS_TYPE (object_class),
151 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
153 soup_marshal_NONE__OBJECT,
158 SOUP_MAKE_TYPE (soup_socket, SoupSocket, class_init, init, PARENT_TYPE)
164 * Return value: a new (disconnected) socket
167 soup_socket_new (void)
169 return g_object_new (SOUP_TYPE_SOCKET, NULL);
173 soup_socket_set_flag (SoupSocket *sock, SoupSocketFlag flag, gboolean value)
177 g_return_if_fail (SOUP_IS_SOCKET (sock));
178 g_return_if_fail (sock->priv->sockfd != -1);
181 case SOUP_SOCKET_FLAG_NONBLOCKING:
182 fdflags = fcntl (sock->priv->sockfd, F_GETFL, 0);
183 g_return_if_fail (fdflags != -1);
186 fdflags |= O_NONBLOCK;
188 fdflags &= ~O_NONBLOCK;
190 fcntl (sock->priv->sockfd, F_SETFL, fdflags);
193 case SOUP_SOCKET_FLAG_NODELAY:
194 opt = (value != FALSE);
195 setsockopt (sock->priv->sockfd, IPPROTO_TCP, TCP_NODELAY,
199 case SOUP_SOCKET_FLAG_REUSEADDR:
200 opt = (value != FALSE);
201 setsockopt (sock->priv->sockfd, SOL_SOCKET, SO_REUSEADDR,
208 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
210 SoupSocket *sock = data;
212 int len = sizeof (error);
214 /* Remove the watch now in case we don't return immediately */
215 g_source_remove (sock->priv->watch);
216 sock->priv->watch = 0;
218 if (condition & ~(G_IO_IN | G_IO_OUT))
221 if (getsockopt (sock->priv->sockfd, SOL_SOCKET, SO_ERROR,
228 soup_socket_start_ssl (sock);
230 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_ERROR_OK);
234 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_ERROR_CANT_CONNECT);
239 idle_connect_result (gpointer user_data)
241 SoupSocket *sock = user_data;
243 sock->priv->watch = 0;
245 g_signal_emit (sock, signals[CONNECT_RESULT], 0,
246 sock->priv->sockfd != -1 ? SOUP_ERROR_OK : SOUP_ERROR_CANT_CONNECT);
251 got_address (SoupAddress *addr, SoupKnownErrorCode status, gpointer user_data)
253 SoupSocket *sock = user_data;
255 if (!SOUP_ERROR_IS_SUCCESSFUL (status)) {
256 g_signal_emit (sock, signals[CONNECT_RESULT], 0, status);
260 soup_socket_connect (sock, addr);
261 /* soup_socket_connect re-reffed addr */
262 g_object_unref (addr);
266 * soup_socket_connect:
267 * @sock: a #SoupSocket (which must not be connected or listening)
268 * @remote_addr: address to connect to
270 * Starts connecting to the indicated remote address and port. The
271 * socket will emit %connect_result when it succeeds or fails (but
272 * not before returning from this function).
275 soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
277 struct sockaddr *sa = NULL;
280 g_return_if_fail (SOUP_IS_SOCKET (sock));
281 g_return_if_fail (SOUP_IS_ADDRESS (remote_addr));
282 g_return_if_fail (sock->priv->sockfd == -1);
284 sock->priv->remote_addr = g_object_ref (remote_addr);
285 sa = soup_address_get_sockaddr (sock->priv->remote_addr, &len);
287 soup_address_resolve (sock->priv->remote_addr,
292 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
293 if (sock->priv->sockfd < 0)
295 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_NONBLOCKING, TRUE);
296 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_NODELAY, TRUE);
298 /* Connect (non-blocking) */
299 status = connect (sock->priv->sockfd, sa, len);
304 /* Connect already succeeded */
305 sock->priv->watch = g_idle_add (idle_connect_result, sock);
308 if (errno != EINPROGRESS)
311 soup_socket_get_iochannel (sock);
312 sock->priv->watch = g_io_add_watch (sock->priv->iochannel,
313 (G_IO_IN | G_IO_OUT | G_IO_PRI |
314 G_IO_ERR | G_IO_HUP | G_IO_NVAL),
315 connect_watch, sock);
321 if (sock->priv->sockfd != -1) {
322 close (sock->priv->sockfd);
323 sock->priv->sockfd = -1;
325 sock->priv->watch = g_idle_add (idle_connect_result, sock);
329 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
331 SoupSocket *sock = data, *new;
332 struct soup_sockaddr_max sa;
335 if (condition & (G_IO_HUP | G_IO_ERR)) {
336 g_source_remove (sock->priv->watch);
337 sock->priv->watch = 0;
341 sa_len = sizeof (sa);
342 sockfd = accept (sock->priv->sockfd, (struct sockaddr *)&sa, &sa_len);
346 new = soup_socket_new ();
347 new->priv->sockfd = sockfd;
348 soup_socket_set_flag (new, SOUP_SOCKET_FLAG_NONBLOCKING, TRUE);
349 soup_socket_set_flag (new, SOUP_SOCKET_FLAG_NODELAY, TRUE);
351 new->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
353 new->priv->server = TRUE;
354 if (sock->priv->ssl) {
355 new->priv->ssl = TRUE;
356 soup_socket_start_ssl (new);
358 soup_socket_get_iochannel (new);
360 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
361 g_object_unref (new);
367 * soup_socket_listen:
368 * @sock: a #SoupSocket (which must not be connected or listening)
369 * @local_addr: Local address to bind to.
371 * Makes @sock start listening on the given interface and port. When
372 * connections come in, @sock will emit %new_connection.
374 * Return value: whether or not @sock is now listening.
377 soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
382 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
383 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), FALSE);
384 g_return_val_if_fail (sock->priv->sockfd == -1, FALSE);
386 /* @local_addr may have its port set to 0. So we intentionally
387 * don't store it in sock->priv->local_addr, so that if the
388 * caller calls soup_socket_get_local_address() later, we'll
389 * have to make a new addr by calling getsockname(), which
390 * will have the right port number.
392 sa = soup_address_get_sockaddr (local_addr, &sa_len);
393 g_return_val_if_fail (sa != NULL, FALSE);
395 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
396 if (sock->priv->sockfd < 0)
398 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_NONBLOCKING, TRUE);
399 soup_socket_set_flag (sock, SOUP_SOCKET_FLAG_REUSEADDR, TRUE);
402 if (bind (sock->priv->sockfd, sa, sa_len) != 0)
406 if (listen (sock->priv->sockfd, 10) != 0)
409 sock->priv->server = TRUE;
411 soup_socket_get_iochannel (sock);
412 sock->priv->watch = g_io_add_watch (sock->priv->iochannel,
413 G_IO_IN | G_IO_ERR | G_IO_HUP,
418 if (sock->priv->sockfd != -1) {
419 close (sock->priv->sockfd);
420 sock->priv->sockfd = -1;
428 * soup_socket_start_ssl:
429 * @socket: the socket
431 * Starts using SSL on @socket.
434 soup_socket_start_ssl (SoupSocket *sock)
438 chan = soup_socket_get_iochannel (sock);
439 sock->priv->iochannel = sock->priv->server ?
440 soup_ssl_get_server_iochannel (chan) :
441 soup_ssl_get_iochannel (chan);
442 sock->priv->ssl = TRUE;
447 * soup_socket_client_new:
448 * @hostname: remote machine to connect to
449 * @port: remote port to connect to
450 * @ssl: whether or not to use SSL
451 * @callback: callback to call when the socket is connected
452 * @user_data: data for @callback
454 * Creates a connection to @hostname and @port. @callback will be
455 * called when the connection completes (or fails).
457 * Return value: the new socket (not yet ready for use).
460 soup_socket_client_new (const char *hostname, guint port, gboolean ssl,
461 SoupSocketCallback callback, gpointer user_data)
465 g_return_val_if_fail (hostname != NULL, NULL);
467 sock = soup_socket_new ();
468 sock->priv->ssl = ssl;
469 soup_socket_connect (sock, soup_address_new (hostname, port));
472 soup_signal_connect_once (sock, "connect_result",
473 G_CALLBACK (callback), user_data);
479 * soup_socket_server_new:
480 * @local_addr: Local address to bind to. (Use soup_address_any_new() to
481 * accept connections on any local address)
482 * @ssl: Whether or not this is an SSL server.
483 * @callback: Callback to call when a client connects
484 * @user_data: data to pass to @callback.
486 * Create and open a new #SoupSocket listening on the specified
487 * address. @callback will be called each time a client connects,
488 * with a new #SoupSocket.
490 * Returns: a new #SoupSocket, or NULL if there was a failure.
493 soup_socket_server_new (SoupAddress *local_addr, gboolean ssl,
494 SoupSocketListenerCallback callback,
499 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), NULL);
501 sock = soup_socket_new ();
502 sock->priv->ssl = ssl;
504 if (!soup_socket_listen (sock, local_addr)) {
505 g_object_unref (sock);
510 g_signal_connect (sock, "new_connection",
511 G_CALLBACK (callback), user_data);
519 * soup_socket_get_iochannel:
520 * @sock: #SoupSocket to get #GIOChannel from.
522 * Get the #GIOChannel for the #SoupSocket.
524 * If you ref the iochannel, it will remain valid after @sock is
527 * Returns: A #GIOChannel; %NULL on failure.
530 soup_socket_get_iochannel (SoupSocket *sock)
532 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
534 if (!sock->priv->iochannel) {
535 sock->priv->iochannel =
536 g_io_channel_unix_new (sock->priv->sockfd);
537 g_io_channel_set_close_on_unref (sock->priv->iochannel, TRUE);
538 g_io_channel_set_encoding (sock->priv->iochannel, NULL, NULL);
539 g_io_channel_set_buffered (sock->priv->iochannel, FALSE);
541 return sock->priv->iochannel;
545 soup_socket_disconnect (SoupSocket *sock)
547 g_return_if_fail (SOUP_IS_SOCKET (sock));
549 if (!sock->priv->iochannel)
552 disconnect_internal (sock);
554 /* Give all readers a chance to notice the connection close */
555 g_signal_emit (sock, signals[READABLE], 0);
557 /* FIXME: can't disconnect until all data is read */
559 /* Then let everyone know we're disconnected */
560 g_signal_emit (sock, signals[DISCONNECTED], 0);
564 soup_socket_is_connected (SoupSocket *sock)
566 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
568 return sock->priv->iochannel != NULL;
573 soup_socket_get_local_address (SoupSocket *sock)
575 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
577 if (!sock->priv->local_addr) {
578 struct soup_sockaddr_max bound_sa;
581 sa_len = sizeof (bound_sa);
582 getsockname (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
583 sock->priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
586 return sock->priv->local_addr;
590 soup_socket_get_remote_address (SoupSocket *sock)
592 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
594 if (!sock->priv->local_addr) {
595 struct soup_sockaddr_max bound_sa;
598 sa_len = sizeof (bound_sa);
599 getpeername (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
600 sock->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
603 return sock->priv->remote_addr;
610 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
612 SoupSocket *sock = user_data;
614 sock->priv->read_tag = 0;
615 g_signal_emit (sock, signals[READABLE], 0);
620 static SoupSocketIOStatus
621 read_from_network (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
625 if (!sock->priv->iochannel)
626 return SOUP_SOCKET_EOF;
628 status = g_io_channel_read_chars (sock->priv->iochannel,
629 buffer, len, nread, NULL);
631 case G_IO_STATUS_NORMAL:
632 case G_IO_STATUS_AGAIN:
634 return SOUP_SOCKET_OK;
636 if (!sock->priv->read_tag) {
637 sock->priv->read_tag =
638 g_io_add_watch (sock->priv->iochannel, G_IO_IN,
639 socket_read_watch, sock);
641 return SOUP_SOCKET_WOULD_BLOCK;
643 case G_IO_STATUS_EOF:
644 return SOUP_SOCKET_EOF;
647 soup_socket_disconnect (sock);
648 return SOUP_SOCKET_ERROR;
652 static SoupSocketIOStatus
653 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
655 GByteArray *read_buf = sock->priv->read_buf;
657 *nread = MIN (read_buf->len, len);
658 memcpy (buffer, read_buf->data, *nread);
660 if (*nread == read_buf->len) {
661 g_byte_array_free (read_buf, TRUE);
662 sock->priv->read_buf = NULL;
664 memcpy (read_buf->data, read_buf->data + *nread,
665 read_buf->len - *nread);
666 g_byte_array_set_size (read_buf, read_buf->len - *nread);
669 return SOUP_SOCKET_OK;
675 * @buffer: buffer to read into
676 * @len: size of @buffer in bytes
677 * @nread: on return, the number of bytes read into @buffer
679 * Attempts to read up to @len bytes from @sock into @buffer. If some
680 * data is successfully read, soup_socket_read() will return
681 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
684 * If @sock is non-blocking, and no data is available, the return
685 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
686 * can connect to the %readable signal to know when there is more data
687 * to read. (NB: You MUST read all available data off the socket
688 * first. The %readable signal will only be emitted after
689 * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
691 * Return value: a #SoupSocketIOStatus, as described above (or
692 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
693 * %SOUP_SOCKET_ERROR on any other error).
696 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
698 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
700 if (sock->priv->read_buf)
701 return read_from_buf (sock, buffer, len, nread);
703 return read_from_network (sock, buffer, len, nread);
707 * soup_socket_read_until:
709 * @buffer: buffer to read into
710 * @len: size of @buffer in bytes
711 * @boundary: boundary to read until
712 * @boundary_len: length of @boundary in bytes
713 * @nread: on return, the number of bytes read into @buffer
714 * @got_boundary: on return, whether or not the data in @buffer
715 * ends with the boundary string
717 * Like soup_socket_read(), but reads no further than the first
718 * occurrence of @boundary. (If the boundary is found, it will be
719 * included in the returned data, and *@got_boundary will be set to
720 * %TRUE.) Any data after the boundary will returned in future reads.
722 * Return value: as for soup_socket_read()
725 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
726 gconstpointer boundary, gsize boundary_len,
727 gsize *nread, gboolean *got_boundary)
729 SoupSocketIOStatus status;
730 GByteArray *read_buf;
731 guint match_len, prev_len;
734 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
735 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
737 *got_boundary = FALSE;
739 if (!sock->priv->read_buf)
740 sock->priv->read_buf = g_byte_array_new ();
741 read_buf = sock->priv->read_buf;
743 if (read_buf->len < boundary_len) {
744 prev_len = read_buf->len;
745 g_byte_array_set_size (read_buf, len);
746 status = read_from_network (sock,
747 read_buf->data + prev_len,
748 len - prev_len, nread);
749 read_buf->len = prev_len + *nread;
751 if (status != SOUP_SOCKET_OK)
755 /* Scan for the boundary */
756 end = read_buf->data + read_buf->len;
757 for (p = read_buf->data; p <= end - boundary_len; p++) {
758 if (!memcmp (p, boundary, boundary_len)) {
760 *got_boundary = TRUE;
765 /* Return everything up to 'p' (which is either just after the
766 * boundary, or @boundary_len - 1 bytes before the end of the
769 match_len = p - read_buf->data;
770 return read_from_buf (sock, buffer, MIN (len, match_len), nread);
774 socket_write_watch (GIOChannel *chan, GIOCondition condition, gpointer user_data)
776 SoupSocket *sock = user_data;
778 sock->priv->write_tag = 0;
779 g_signal_emit (sock, signals[WRITABLE], 0);
787 * @buffer: data to write
788 * @len: size of @buffer, in bytes
789 * @nwrite: on return, number of bytes written
791 * Attempts to write @len bytes from @buffer to @sock. If some data is
792 * successfully written, the resturn status will be
793 * %SOUP_SOCKET_SUCCESS, and *@nwrote will contain the number of bytes
796 * If @sock is non-blocking, and no data could be written right away,
797 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
798 * the caller can connect to the %writable signal to know when more
799 * data can be written. (NB: %writable is only emitted after a
800 * %SOUP_SOCKET_WOULD_BLOCK.)
802 * Return value: a #SoupSocketIOStatus, as described above (or
803 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR).
806 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
807 gsize len, gsize *nwrote)
810 gpointer pipe_handler;
812 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
814 if (!sock->priv->iochannel)
815 return SOUP_SOCKET_EOF;
816 if (sock->priv->write_tag)
817 return SOUP_SOCKET_WOULD_BLOCK;
819 pipe_handler = signal (SIGPIPE, SIG_IGN);
820 status = g_io_channel_write_chars (sock->priv->iochannel,
821 buffer, len, nwrote, NULL);
822 signal (SIGPIPE, pipe_handler);
823 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
824 soup_socket_disconnect (sock);
825 return SOUP_SOCKET_ERROR;
829 return SOUP_SOCKET_OK;
831 sock->priv->write_tag =
832 g_io_add_watch (sock->priv->iochannel, G_IO_OUT,
833 socket_write_watch, sock);
834 return SOUP_SOCKET_WOULD_BLOCK;