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>
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 };
55 struct SoupSocketPrivate {
57 SoupAddress *local_addr, *remote_addr;
58 GIOChannel *iochannel;
67 guint read_tag, write_tag, error_tag;
72 #define soup_sockaddr_max sockaddr_in6
74 #define soup_sockaddr_max sockaddr_in
77 static void set_property (GObject *object, guint prop_id,
78 const GValue *value, GParamSpec *pspec);
79 static void get_property (GObject *object, guint prop_id,
80 GValue *value, GParamSpec *pspec);
83 init (GObject *object)
85 SoupSocket *sock = SOUP_SOCKET (object);
87 sock->priv = g_new0 (SoupSocketPrivate, 1);
88 sock->priv->sockfd = -1;
89 sock->priv->non_blocking = sock->priv->nodelay = TRUE;
90 sock->priv->reuseaddr = TRUE;
94 disconnect_internal (SoupSocket *sock)
96 GIOChannel *iochannel;
98 /* If we close the socket from one thread while
99 * reading/writing from another, it's possible that the other
100 * thread will get an I/O error and try to close the socket
101 * while we're still in this function. So we clear
102 * sock->priv->iochannel early to make sure that the other
103 * thread's attempt to close the socket becomes a no-op.
105 iochannel = sock->priv->iochannel;
106 sock->priv->iochannel = NULL;
107 if (iochannel == NULL)
110 g_io_channel_unref (iochannel);
112 if (sock->priv->read_tag) {
113 g_source_remove (sock->priv->read_tag);
114 sock->priv->read_tag = 0;
116 if (sock->priv->write_tag) {
117 g_source_remove (sock->priv->write_tag);
118 sock->priv->write_tag = 0;
120 if (sock->priv->error_tag) {
121 g_source_remove (sock->priv->error_tag);
122 sock->priv->error_tag = 0;
129 finalize (GObject *object)
131 SoupSocket *sock = SOUP_SOCKET (object);
133 if (sock->priv->iochannel)
134 disconnect_internal (sock);
136 if (sock->priv->local_addr)
137 g_object_unref (sock->priv->local_addr);
138 if (sock->priv->remote_addr)
139 g_object_unref (sock->priv->remote_addr);
141 if (sock->priv->watch)
142 g_source_remove (sock->priv->watch);
146 G_OBJECT_CLASS (parent_class)->finalize (object);
150 class_init (GObjectClass *object_class)
152 parent_class = g_type_class_ref (PARENT_TYPE);
154 /* virtual method override */
155 object_class->finalize = finalize;
156 object_class->set_property = set_property;
157 object_class->get_property = get_property;
160 signals[CONNECT_RESULT] =
161 g_signal_new ("connect_result",
162 G_OBJECT_CLASS_TYPE (object_class),
164 G_STRUCT_OFFSET (SoupSocketClass, connect_result),
166 soup_marshal_NONE__INT,
170 g_signal_new ("readable",
171 G_OBJECT_CLASS_TYPE (object_class),
173 G_STRUCT_OFFSET (SoupSocketClass, readable),
175 soup_marshal_NONE__NONE,
178 g_signal_new ("writable",
179 G_OBJECT_CLASS_TYPE (object_class),
181 G_STRUCT_OFFSET (SoupSocketClass, writable),
183 soup_marshal_NONE__NONE,
185 signals[DISCONNECTED] =
186 g_signal_new ("disconnected",
187 G_OBJECT_CLASS_TYPE (object_class),
189 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
191 soup_marshal_NONE__NONE,
193 signals[NEW_CONNECTION] =
194 g_signal_new ("new_connection",
195 G_OBJECT_CLASS_TYPE (object_class),
197 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
199 soup_marshal_NONE__OBJECT,
204 g_object_class_install_property (
205 object_class, PROP_NON_BLOCKING,
206 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
208 "Whether or not the socket uses non-blocking I/O",
211 g_object_class_install_property (
212 object_class, PROP_NODELAY,
213 g_param_spec_boolean (SOUP_SOCKET_FLAG_NODELAY,
215 "Whether or not the socket uses TCP NODELAY",
218 g_object_class_install_property (
219 object_class, PROP_REUSEADDR,
220 g_param_spec_boolean (SOUP_SOCKET_FLAG_REUSEADDR,
222 "Whether or not the socket uses the TCP REUSEADDR flag",
225 g_object_class_install_property (
226 object_class, PROP_IS_SERVER,
227 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
229 "Whether or not the socket is a server socket",
232 g_object_class_install_property (
233 object_class, PROP_SSL_CREDENTIALS,
234 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
236 "SSL credential information, passed from the session to the SSL implementation",
240 SOUP_MAKE_TYPE (soup_socket, SoupSocket, class_init, init, PARENT_TYPE)
244 update_fdflags (SoupSocket *sock)
248 if (!sock->priv->sockfd)
251 flags = fcntl (sock->priv->sockfd, F_GETFL, 0);
253 if (sock->priv->non_blocking)
256 flags &= ~O_NONBLOCK;
257 fcntl (sock->priv->sockfd, F_SETFL, flags);
260 opt = (sock->priv->nodelay != 0);
261 setsockopt (sock->priv->sockfd, IPPROTO_TCP,
262 TCP_NODELAY, &opt, sizeof (opt));
264 opt = (sock->priv->reuseaddr != 0);
265 setsockopt (sock->priv->sockfd, SOL_SOCKET,
266 SO_REUSEADDR, &opt, sizeof (opt));
270 set_property (GObject *object, guint prop_id,
271 const GValue *value, GParamSpec *pspec)
273 SoupSocket *sock = SOUP_SOCKET (object);
276 case PROP_NON_BLOCKING:
277 sock->priv->non_blocking = g_value_get_boolean (value);
278 update_fdflags (sock);
281 sock->priv->nodelay = g_value_get_boolean (value);
282 update_fdflags (sock);
285 sock->priv->reuseaddr = g_value_get_boolean (value);
286 update_fdflags (sock);
288 case PROP_SSL_CREDENTIALS:
289 sock->priv->ssl_creds = g_value_get_pointer (value);
297 get_property (GObject *object, guint prop_id,
298 GValue *value, GParamSpec *pspec)
300 SoupSocket *sock = SOUP_SOCKET (object);
303 case PROP_NON_BLOCKING:
304 g_value_set_boolean (value, sock->priv->non_blocking);
307 g_value_set_boolean (value, sock->priv->nodelay);
310 g_value_set_boolean (value, sock->priv->reuseaddr);
313 g_value_set_boolean (value, sock->priv->is_server);
315 case PROP_SSL_CREDENTIALS:
316 g_value_set_pointer (value, sock->priv->ssl_creds);
326 * @optname1: name of first property to set (or %NULL)
327 * @...: value of @optname1, followed by additional property/value pairs
329 * Return value: a new (disconnected) socket
332 soup_socket_new (const char *optname1, ...)
337 va_start (ap, optname1);
338 sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
346 get_iochannel (SoupSocket *sock)
348 if (!sock->priv->iochannel) {
349 sock->priv->iochannel =
350 g_io_channel_unix_new (sock->priv->sockfd);
351 g_io_channel_set_close_on_unref (sock->priv->iochannel, TRUE);
352 g_io_channel_set_encoding (sock->priv->iochannel, NULL, NULL);
353 g_io_channel_set_buffered (sock->priv->iochannel, FALSE);
355 return sock->priv->iochannel;
359 idle_connect_result (gpointer user_data)
361 SoupSocket *sock = user_data;
363 sock->priv->watch = 0;
365 g_signal_emit (sock, signals[CONNECT_RESULT], 0,
366 sock->priv->sockfd != -1 ? SOUP_STATUS_OK : SOUP_STATUS_CANT_CONNECT);
371 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
373 SoupSocket *sock = data;
375 int len = sizeof (error);
377 /* Remove the watch now in case we don't return immediately */
378 g_source_remove (sock->priv->watch);
379 sock->priv->watch = 0;
381 if (condition & ~(G_IO_IN | G_IO_OUT))
384 if (getsockopt (sock->priv->sockfd, SOL_SOCKET, SO_ERROR,
390 return idle_connect_result (sock);
393 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_STATUS_CANT_CONNECT);
398 got_address (SoupAddress *addr, guint status, gpointer user_data)
400 SoupSocket *sock = user_data;
402 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
403 g_signal_emit (sock, signals[CONNECT_RESULT], 0, status);
404 g_object_unref (sock);
408 soup_socket_connect (sock, sock->priv->remote_addr);
409 /* soup_socket_connect re-reffed addr */
410 g_object_unref (addr);
412 g_object_unref (sock);
416 * soup_socket_connect:
417 * @sock: a client #SoupSocket (which must not already be connected)
418 * @remote_addr: address to connect to
420 * If %SOUP_SOCKET_FLAG_NONBLOCKING has been set on the socket, this
421 * begins asynchronously connecting to the given address. The socket
422 * will emit %connect_result when it succeeds or fails (but not before
423 * returning from this function).
425 * If %SOUP_SOCKET_FLAG_NONBLOCKING has not been set, this will
426 * attempt to synchronously connect.
428 * Return value: %SOUP_STATUS_CONTINUE if connecting asynchronously,
429 * otherwise a success or failure code.
432 soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
437 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
438 g_return_val_if_fail (!sock->priv->is_server, SOUP_STATUS_MALFORMED);
439 g_return_val_if_fail (sock->priv->sockfd == -1, SOUP_STATUS_MALFORMED);
440 g_return_val_if_fail (SOUP_IS_ADDRESS (remote_addr), SOUP_STATUS_MALFORMED);
442 sock->priv->remote_addr = g_object_ref (remote_addr);
443 if (!sock->priv->non_blocking) {
444 status = soup_address_resolve_sync (remote_addr);
445 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
449 sa = soup_address_get_sockaddr (sock->priv->remote_addr, &len);
451 if (!sock->priv->non_blocking)
452 return SOUP_STATUS_CANT_RESOLVE;
455 soup_address_resolve_async (remote_addr, got_address, sock);
456 return SOUP_STATUS_CONTINUE;
459 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
460 if (sock->priv->sockfd == -1) {
464 update_fdflags (sock);
466 status = connect (sock->priv->sockfd, sa, len);
470 if (errno == EINPROGRESS) {
471 /* Wait for connect to succeed or fail */
473 g_io_add_watch (get_iochannel (sock),
475 G_IO_PRI | G_IO_ERR |
476 G_IO_HUP | G_IO_NVAL,
477 connect_watch, sock);
478 return SOUP_STATUS_CONTINUE;
480 close (sock->priv->sockfd);
481 sock->priv->sockfd = -1;
486 if (sock->priv->non_blocking) {
487 sock->priv->watch = g_idle_add (idle_connect_result, sock);
488 return SOUP_STATUS_CONTINUE;
489 } else if (sock->priv->sockfd == -1)
490 return SOUP_STATUS_CANT_CONNECT;
492 get_iochannel (sock);
493 return SOUP_STATUS_OK;
498 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
500 SoupSocket *sock = data, *new;
501 struct soup_sockaddr_max sa;
504 if (condition & (G_IO_HUP | G_IO_ERR)) {
505 g_source_remove (sock->priv->watch);
506 sock->priv->watch = 0;
510 sa_len = sizeof (sa);
511 sockfd = accept (sock->priv->sockfd, (struct sockaddr *)&sa, &sa_len);
515 new = g_object_new (SOUP_TYPE_SOCKET, NULL);
516 new->priv->sockfd = sockfd;
517 new->priv->non_blocking = sock->priv->non_blocking;
518 new->priv->nodelay = sock->priv->nodelay;
519 new->priv->is_server = TRUE;
520 new->priv->ssl_creds = sock->priv->ssl_creds;
521 update_fdflags (new);
523 new->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
525 if (new->priv->ssl_creds) {
526 if (!soup_socket_start_ssl (new)) {
527 g_object_unref (new);
533 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
534 g_object_unref (new);
540 * soup_socket_listen:
541 * @sock: a server #SoupSocket (which must not already be connected or
543 * @local_addr: Local address to bind to.
545 * Makes @sock start listening on the given interface and port. When
546 * connections come in, @sock will emit %new_connection.
548 * Return value: whether or not @sock is now listening.
551 soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
556 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
557 g_return_val_if_fail (sock->priv->is_server, FALSE);
558 g_return_val_if_fail (sock->priv->sockfd == -1, FALSE);
559 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), FALSE);
561 /* @local_addr may have its port set to 0. So we intentionally
562 * don't store it in sock->priv->local_addr, so that if the
563 * caller calls soup_socket_get_local_address() later, we'll
564 * have to make a new addr by calling getsockname(), which
565 * will have the right port number.
567 sa = soup_address_get_sockaddr (local_addr, &sa_len);
568 g_return_val_if_fail (sa != NULL, FALSE);
570 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
571 if (sock->priv->sockfd < 0)
573 update_fdflags (sock);
576 if (bind (sock->priv->sockfd, sa, sa_len) != 0)
580 if (listen (sock->priv->sockfd, 10) != 0)
583 sock->priv->watch = g_io_add_watch (get_iochannel (sock),
584 G_IO_IN | G_IO_ERR | G_IO_HUP,
589 if (sock->priv->sockfd != -1) {
590 close (sock->priv->sockfd);
591 sock->priv->sockfd = -1;
599 * soup_socket_start_ssl:
602 * Starts using SSL on @socket.
604 * Return value: success or failure
607 soup_socket_start_ssl (SoupSocket *sock)
609 GIOChannel *ssl_chan;
611 get_iochannel (sock);
612 ssl_chan = soup_ssl_wrap_iochannel (
613 sock->priv->iochannel, sock->priv->is_server ?
614 SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
615 soup_address_get_name (sock->priv->remote_addr),
616 sock->priv->ssl_creds);
621 sock->priv->iochannel = ssl_chan;
627 * soup_socket_client_new_async:
628 * @hostname: remote machine to connect to
629 * @port: remote port to connect to
630 * @ssl_creds: SSL credentials structure, or %NULL if not SSL
631 * @callback: callback to call when the socket is connected
632 * @user_data: data for @callback
634 * Creates a connection to @hostname and @port. @callback will be
635 * called when the connection completes (or fails).
637 * Return value: the new socket (not yet ready for use).
640 soup_socket_client_new_async (const char *hostname, guint port,
642 SoupSocketCallback callback, gpointer user_data)
646 g_return_val_if_fail (hostname != NULL, NULL);
648 sock = g_object_new (SOUP_TYPE_SOCKET,
649 SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
651 soup_socket_connect (sock, soup_address_new (hostname, port));
654 soup_signal_connect_once (sock, "connect_result",
655 G_CALLBACK (callback), user_data);
661 * soup_socket_client_new_sync:
662 * @hostname: remote machine to connect to
663 * @port: remote port to connect to
664 * @ssl_creds: SSL credentials structure, or %NULL if not SSL
665 * @status_ret: pointer to return the soup status in
667 * Creates a connection to @hostname and @port. If @status_ret is not
668 * %NULL, it will contain a status code on return.
670 * Return value: the new socket, or %NULL if it could not connect.
673 soup_socket_client_new_sync (const char *hostname, guint port,
674 gpointer ssl_creds, guint *status_ret)
679 g_return_val_if_fail (hostname != NULL, NULL);
681 sock = g_object_new (SOUP_TYPE_SOCKET,
682 SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
684 sock->priv->non_blocking = FALSE;
685 status = soup_socket_connect (sock, soup_address_new (hostname, port));
687 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
688 g_object_unref (sock);
693 *status_ret = status;
698 * soup_socket_server_new:
699 * @local_addr: Local address to bind to. (Use soup_address_any_new() to
700 * accept connections on any local address)
701 * @ssl_creds: SSL credentials, or %NULL if this is not an SSL server
702 * @callback: Callback to call when a client connects
703 * @user_data: data to pass to @callback.
705 * Create and open a new #SoupSocket listening on the specified
706 * address. @callback will be called each time a client connects,
707 * with a new #SoupSocket.
709 * Returns: a new #SoupSocket, or NULL if there was a failure.
712 soup_socket_server_new (SoupAddress *local_addr, gpointer ssl_creds,
713 SoupSocketListenerCallback callback,
718 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), NULL);
720 sock = g_object_new (SOUP_TYPE_SOCKET,
721 SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
723 sock->priv->is_server = TRUE;
724 if (!soup_socket_listen (sock, local_addr)) {
725 g_object_unref (sock);
730 g_signal_connect (sock, "new_connection",
731 G_CALLBACK (callback), user_data);
739 soup_socket_disconnect (SoupSocket *sock)
741 g_return_if_fail (SOUP_IS_SOCKET (sock));
743 if (!disconnect_internal (sock))
746 /* Give all readers a chance to notice the connection close */
747 g_signal_emit (sock, signals[READABLE], 0);
749 /* FIXME: can't disconnect until all data is read */
751 /* Then let everyone know we're disconnected */
752 g_signal_emit (sock, signals[DISCONNECTED], 0);
756 soup_socket_is_connected (SoupSocket *sock)
758 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
760 return sock->priv->iochannel != NULL;
765 soup_socket_get_local_address (SoupSocket *sock)
767 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
769 if (!sock->priv->local_addr) {
770 struct soup_sockaddr_max bound_sa;
773 sa_len = sizeof (bound_sa);
774 getsockname (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
775 sock->priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
778 return sock->priv->local_addr;
782 soup_socket_get_remote_address (SoupSocket *sock)
784 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
786 if (!sock->priv->local_addr) {
787 struct soup_sockaddr_max bound_sa;
790 sa_len = sizeof (bound_sa);
791 getpeername (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
792 sock->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
795 return sock->priv->remote_addr;
802 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
804 SoupSocket *sock = user_data;
806 sock->priv->read_tag = 0;
807 g_signal_emit (sock, signals[READABLE], 0);
812 static SoupSocketIOStatus
813 read_from_network (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
817 if (!sock->priv->iochannel)
818 return SOUP_SOCKET_EOF;
820 status = g_io_channel_read_chars (sock->priv->iochannel,
821 buffer, len, nread, NULL);
823 case G_IO_STATUS_NORMAL:
824 case G_IO_STATUS_AGAIN:
826 return SOUP_SOCKET_OK;
828 if (!sock->priv->read_tag) {
829 sock->priv->read_tag =
830 g_io_add_watch (sock->priv->iochannel, G_IO_IN,
831 socket_read_watch, sock);
833 return SOUP_SOCKET_WOULD_BLOCK;
835 case G_IO_STATUS_EOF:
836 return SOUP_SOCKET_EOF;
839 return SOUP_SOCKET_ERROR;
843 static SoupSocketIOStatus
844 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
846 GByteArray *read_buf = sock->priv->read_buf;
848 *nread = MIN (read_buf->len, len);
849 memcpy (buffer, read_buf->data, *nread);
851 if (*nread == read_buf->len) {
852 g_byte_array_free (read_buf, TRUE);
853 sock->priv->read_buf = NULL;
855 memcpy (read_buf->data, read_buf->data + *nread,
856 read_buf->len - *nread);
857 g_byte_array_set_size (read_buf, read_buf->len - *nread);
860 return SOUP_SOCKET_OK;
866 * @buffer: buffer to read into
867 * @len: size of @buffer in bytes
868 * @nread: on return, the number of bytes read into @buffer
870 * Attempts to read up to @len bytes from @sock into @buffer. If some
871 * data is successfully read, soup_socket_read() will return
872 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
875 * If @sock is non-blocking, and no data is available, the return
876 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
877 * can connect to the %readable signal to know when there is more data
878 * to read. (NB: You MUST read all available data off the socket
879 * first. The %readable signal will only be emitted after
880 * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
882 * Return value: a #SoupSocketIOStatus, as described above (or
883 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
884 * %SOUP_SOCKET_ERROR on any other error).
887 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
889 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
891 if (sock->priv->read_buf)
892 return read_from_buf (sock, buffer, len, nread);
894 return read_from_network (sock, buffer, len, nread);
898 * soup_socket_read_until:
900 * @buffer: buffer to read into
901 * @len: size of @buffer in bytes
902 * @boundary: boundary to read until
903 * @boundary_len: length of @boundary in bytes
904 * @nread: on return, the number of bytes read into @buffer
905 * @got_boundary: on return, whether or not the data in @buffer
906 * ends with the boundary string
908 * Like soup_socket_read(), but reads no further than the first
909 * occurrence of @boundary. (If the boundary is found, it will be
910 * included in the returned data, and *@got_boundary will be set to
911 * %TRUE.) Any data after the boundary will returned in future reads.
913 * Return value: as for soup_socket_read()
916 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
917 gconstpointer boundary, gsize boundary_len,
918 gsize *nread, gboolean *got_boundary)
920 SoupSocketIOStatus status;
921 GByteArray *read_buf;
922 guint match_len, prev_len;
925 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
926 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
928 *got_boundary = FALSE;
930 if (!sock->priv->read_buf)
931 sock->priv->read_buf = g_byte_array_new ();
932 read_buf = sock->priv->read_buf;
934 if (read_buf->len < boundary_len) {
935 prev_len = read_buf->len;
936 g_byte_array_set_size (read_buf, len);
937 status = read_from_network (sock,
938 read_buf->data + prev_len,
939 len - prev_len, nread);
940 read_buf->len = prev_len + *nread;
942 if (status != SOUP_SOCKET_OK)
946 /* Scan for the boundary */
947 end = read_buf->data + read_buf->len;
948 for (p = read_buf->data; p <= end - boundary_len; p++) {
949 if (!memcmp (p, boundary, boundary_len)) {
951 *got_boundary = TRUE;
956 /* Return everything up to 'p' (which is either just after the
957 * boundary, or @boundary_len - 1 bytes before the end of the
960 match_len = p - read_buf->data;
961 return read_from_buf (sock, buffer, MIN (len, match_len), nread);
965 socket_write_watch (GIOChannel *chan, GIOCondition condition, gpointer user_data)
967 SoupSocket *sock = user_data;
969 sock->priv->write_tag = 0;
970 g_signal_emit (sock, signals[WRITABLE], 0);
978 * @buffer: data to write
979 * @len: size of @buffer, in bytes
980 * @nwrote: on return, number of bytes written
982 * Attempts to write @len bytes from @buffer to @sock. If some data is
983 * successfully written, the resturn status will be
984 * %SOUP_SOCKET_SUCCESS, and *@nwrote will contain the number of bytes
987 * If @sock is non-blocking, and no data could be written right away,
988 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
989 * the caller can connect to the %writable signal to know when more
990 * data can be written. (NB: %writable is only emitted after a
991 * %SOUP_SOCKET_WOULD_BLOCK.)
993 * Return value: a #SoupSocketIOStatus, as described above (or
994 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR).
997 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
998 gsize len, gsize *nwrote)
1001 gpointer pipe_handler;
1003 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1005 if (!sock->priv->iochannel)
1006 return SOUP_SOCKET_EOF;
1007 if (sock->priv->write_tag)
1008 return SOUP_SOCKET_WOULD_BLOCK;
1010 pipe_handler = signal (SIGPIPE, SIG_IGN);
1011 status = g_io_channel_write_chars (sock->priv->iochannel,
1012 buffer, len, nwrote, NULL);
1013 signal (SIGPIPE, pipe_handler);
1014 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN)
1015 return SOUP_SOCKET_ERROR;
1018 return SOUP_SOCKET_OK;
1020 sock->priv->write_tag =
1021 g_io_add_watch (sock->priv->iochannel, G_IO_OUT,
1022 socket_write_watch, sock);
1023 return SOUP_SOCKET_WOULD_BLOCK;