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;
55 #define SOUP_SOCKET_FLAG_SSL (1<<8)
57 #define SOUP_SOCKET_SET_FLAG(sock, flag) (sock)->priv->flags |= (flag)
58 #define SOUP_SOCKET_CLEAR_FLAG(sock, flag) (sock)->priv->flags &= ~(flag)
59 #define SOUP_SOCKET_CHECK_FLAG(sock, flag) ((sock)->priv->flags & (flag))
62 init (GObject *object)
64 SoupSocket *sock = SOUP_SOCKET (object);
66 sock->priv = g_new0 (SoupSocketPrivate, 1);
67 sock->priv->sockfd = -1;
71 disconnect_internal (SoupSocket *sock)
73 g_io_channel_unref (sock->priv->iochannel);
74 sock->priv->iochannel = NULL;
76 if (sock->priv->read_tag) {
77 g_source_remove (sock->priv->read_tag);
78 sock->priv->read_tag = 0;
80 if (sock->priv->write_tag) {
81 g_source_remove (sock->priv->write_tag);
82 sock->priv->write_tag = 0;
84 if (sock->priv->error_tag) {
85 g_source_remove (sock->priv->error_tag);
86 sock->priv->error_tag = 0;
91 finalize (GObject *object)
93 SoupSocket *sock = SOUP_SOCKET (object);
95 if (sock->priv->iochannel)
96 disconnect_internal (sock);
98 if (sock->priv->local_addr)
99 g_object_unref (sock->priv->local_addr);
100 if (sock->priv->remote_addr)
101 g_object_unref (sock->priv->remote_addr);
103 if (sock->priv->watch)
104 g_source_remove (sock->priv->watch);
108 G_OBJECT_CLASS (parent_class)->finalize (object);
112 class_init (GObjectClass *object_class)
114 parent_class = g_type_class_ref (PARENT_TYPE);
116 /* virtual method override */
117 object_class->finalize = finalize;
120 signals[CONNECT_RESULT] =
121 g_signal_new ("connect_result",
122 G_OBJECT_CLASS_TYPE (object_class),
124 G_STRUCT_OFFSET (SoupSocketClass, connect_result),
126 soup_marshal_NONE__INT,
130 g_signal_new ("readable",
131 G_OBJECT_CLASS_TYPE (object_class),
133 G_STRUCT_OFFSET (SoupSocketClass, readable),
135 soup_marshal_NONE__NONE,
138 g_signal_new ("writable",
139 G_OBJECT_CLASS_TYPE (object_class),
141 G_STRUCT_OFFSET (SoupSocketClass, writable),
143 soup_marshal_NONE__NONE,
145 signals[DISCONNECTED] =
146 g_signal_new ("disconnected",
147 G_OBJECT_CLASS_TYPE (object_class),
149 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
151 soup_marshal_NONE__NONE,
153 signals[NEW_CONNECTION] =
154 g_signal_new ("new_connection",
155 G_OBJECT_CLASS_TYPE (object_class),
157 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
159 soup_marshal_NONE__OBJECT,
164 SOUP_MAKE_TYPE (soup_socket, SoupSocket, class_init, init, PARENT_TYPE)
170 * Return value: a new (disconnected) socket
173 soup_socket_new (void)
175 return g_object_new (SOUP_TYPE_SOCKET, NULL);
179 update_fdflags (SoupSocket *sock, guint mask)
183 if (mask & SOUP_SOCKET_FLAG_NONBLOCKING) {
184 flags = fcntl (sock->priv->sockfd, F_GETFL, 0);
185 g_return_if_fail (flags != -1);
187 if (sock->priv->flags & SOUP_SOCKET_FLAG_NONBLOCKING)
190 flags &= ~O_NONBLOCK;
191 fcntl (sock->priv->sockfd, F_SETFL, flags);
193 if (mask & SOUP_SOCKET_FLAG_NODELAY) {
194 opt = (sock->priv->flags & SOUP_SOCKET_FLAG_NODELAY) != 0;
195 setsockopt (sock->priv->sockfd, IPPROTO_TCP,
196 TCP_NODELAY, &opt, sizeof (opt));
198 if (mask & SOUP_SOCKET_FLAG_REUSEADDR) {
199 opt = (sock->priv->flags & SOUP_SOCKET_FLAG_REUSEADDR) != 0;
200 setsockopt (sock->priv->sockfd, SOL_SOCKET,
201 SO_REUSEADDR, &opt, sizeof (opt));
206 soup_socket_set_flags (SoupSocket *sock, guint mask, guint flags)
208 g_return_if_fail (SOUP_IS_SOCKET (sock));
210 sock->priv->flags |= mask & flags;
211 sock->priv->flags &= ~(mask & ~flags);
213 if (sock->priv->sockfd)
214 update_fdflags (sock, mask);
218 get_iochannel (SoupSocket *sock)
220 if (!sock->priv->iochannel) {
221 sock->priv->iochannel =
222 g_io_channel_unix_new (sock->priv->sockfd);
223 g_io_channel_set_close_on_unref (sock->priv->iochannel, TRUE);
224 g_io_channel_set_encoding (sock->priv->iochannel, NULL, NULL);
225 g_io_channel_set_buffered (sock->priv->iochannel, FALSE);
227 return sock->priv->iochannel;
231 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
233 SoupSocket *sock = data;
235 int len = sizeof (error);
237 /* Remove the watch now in case we don't return immediately */
238 g_source_remove (sock->priv->watch);
239 sock->priv->watch = 0;
241 if (condition & ~(G_IO_IN | G_IO_OUT))
244 if (getsockopt (sock->priv->sockfd, SOL_SOCKET, SO_ERROR,
250 if (SOUP_SOCKET_CHECK_FLAG (sock, SOUP_SOCKET_FLAG_SSL))
251 soup_socket_start_ssl (sock);
253 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_STATUS_OK);
257 g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_STATUS_CANT_CONNECT);
262 idle_connect_result (gpointer user_data)
264 SoupSocket *sock = user_data;
266 sock->priv->watch = 0;
268 g_signal_emit (sock, signals[CONNECT_RESULT], 0,
269 sock->priv->sockfd != -1 ? SOUP_STATUS_OK : SOUP_STATUS_CANT_CONNECT);
274 got_address (SoupAddress *addr, guint status, gpointer user_data)
276 SoupSocket *sock = user_data;
278 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
279 g_signal_emit (sock, signals[CONNECT_RESULT], 0, status);
283 soup_socket_connect (sock, sock->priv->remote_addr);
284 /* soup_socket_connect re-reffed addr */
285 g_object_unref (addr);
289 * soup_socket_connect:
290 * @sock: a client #SoupSocket (which must not already be connected)
291 * @remote_addr: address to connect to
293 * If %SOUP_SOCKET_FLAG_NONBLOCKING has been set on the socket, this
294 * begins asynchronously connecting to the given address. The socket
295 * will emit %connect_result when it succeeds or fails (but not before
296 * returning from this function).
298 * If %SOUP_SOCKET_FLAG_NONBLOCKING has not been set, this will
299 * attempt to synchronously connect.
301 * Return value: %SOUP_STATUS_CONTINUE if connecting asynchronously,
302 * otherwise a success or failure code.
305 soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
311 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
312 g_return_val_if_fail (!SOUP_SOCKET_CHECK_FLAG (sock, SOUP_SOCKET_FLAG_SERVER), FALSE);
313 g_return_val_if_fail (sock->priv->sockfd == -1, SOUP_STATUS_MALFORMED);
314 g_return_val_if_fail (SOUP_IS_ADDRESS (remote_addr), SOUP_STATUS_MALFORMED);
316 sync = !(sock->priv->flags & SOUP_SOCKET_FLAG_NONBLOCKING);
318 sock->priv->remote_addr = g_object_ref (remote_addr);
320 status = soup_address_resolve_sync (remote_addr);
321 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
325 sa = soup_address_get_sockaddr (sock->priv->remote_addr, &len);
328 return SOUP_STATUS_CANT_RESOLVE;
330 soup_address_resolve_async (remote_addr, got_address, sock);
331 return SOUP_STATUS_CONTINUE;
334 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
335 if (sock->priv->sockfd == -1) {
339 update_fdflags (sock, SOUP_SOCKET_FLAG_ALL);
341 status = connect (sock->priv->sockfd, sa, len);
345 if (errno == EINPROGRESS) {
346 /* Wait for connect to succeed or fail */
348 g_io_add_watch (get_iochannel (sock),
350 G_IO_PRI | G_IO_ERR |
351 G_IO_HUP | G_IO_NVAL,
352 connect_watch, sock);
353 return SOUP_STATUS_CONTINUE;
355 close (sock->priv->sockfd);
356 sock->priv->sockfd = -1;
362 return sock->priv->sockfd != -1 ?
363 SOUP_STATUS_OK : SOUP_STATUS_CANT_CONNECT;
365 sock->priv->watch = g_idle_add (idle_connect_result, sock);
366 return SOUP_STATUS_CONTINUE;
371 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
373 SoupSocket *sock = data, *new;
374 struct soup_sockaddr_max sa;
377 if (condition & (G_IO_HUP | G_IO_ERR)) {
378 g_source_remove (sock->priv->watch);
379 sock->priv->watch = 0;
383 sa_len = sizeof (sa);
384 sockfd = accept (sock->priv->sockfd, (struct sockaddr *)&sa, &sa_len);
388 new = soup_socket_new ();
389 new->priv->sockfd = sockfd;
390 new->priv->flags = (SOUP_SOCKET_FLAG_NONBLOCKING |
391 SOUP_SOCKET_FLAG_NODELAY |
392 SOUP_SOCKET_FLAG_SERVER |
393 (sock->priv->flags & SOUP_SOCKET_FLAG_SSL));
394 update_fdflags (new, SOUP_SOCKET_FLAG_ALL);
396 new->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
398 if (SOUP_SOCKET_CHECK_FLAG (new, SOUP_SOCKET_FLAG_SSL))
399 soup_socket_start_ssl (new);
403 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
404 g_object_unref (new);
410 * soup_socket_listen:
411 * @sock: a server #SoupSocket (which must not already be connected or
413 * @local_addr: Local address to bind to.
415 * Makes @sock start listening on the given interface and port. When
416 * connections come in, @sock will emit %new_connection.
418 * Return value: whether or not @sock is now listening.
421 soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
426 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
427 g_return_val_if_fail (SOUP_SOCKET_CHECK_FLAG (sock, SOUP_SOCKET_FLAG_SERVER), FALSE);
428 g_return_val_if_fail (sock->priv->sockfd == -1, FALSE);
429 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), FALSE);
431 /* @local_addr may have its port set to 0. So we intentionally
432 * don't store it in sock->priv->local_addr, so that if the
433 * caller calls soup_socket_get_local_address() later, we'll
434 * have to make a new addr by calling getsockname(), which
435 * will have the right port number.
437 sa = soup_address_get_sockaddr (local_addr, &sa_len);
438 g_return_val_if_fail (sa != NULL, FALSE);
440 sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
441 if (sock->priv->sockfd < 0)
443 update_fdflags (sock, SOUP_SOCKET_FLAG_ALL);
446 if (bind (sock->priv->sockfd, sa, sa_len) != 0)
450 if (listen (sock->priv->sockfd, 10) != 0)
453 sock->priv->watch = g_io_add_watch (get_iochannel (sock),
454 G_IO_IN | G_IO_ERR | G_IO_HUP,
459 if (sock->priv->sockfd != -1) {
460 close (sock->priv->sockfd);
461 sock->priv->sockfd = -1;
469 * soup_socket_start_ssl:
470 * @socket: the socket
472 * Starts using SSL on @socket.
475 soup_socket_start_ssl (SoupSocket *sock)
479 chan = get_iochannel (sock);
480 sock->priv->iochannel =
481 SOUP_SOCKET_CHECK_FLAG (sock, SOUP_SOCKET_FLAG_SERVER) ?
482 soup_ssl_get_server_iochannel (chan) :
483 soup_ssl_get_iochannel (chan);
484 SOUP_SOCKET_SET_FLAG (sock, SOUP_SOCKET_FLAG_SSL);
489 * soup_socket_client_new_async:
490 * @hostname: remote machine to connect to
491 * @port: remote port to connect to
492 * @ssl: whether or not to use SSL
493 * @callback: callback to call when the socket is connected
494 * @user_data: data for @callback
496 * Creates a connection to @hostname and @port. @callback will be
497 * called when the connection completes (or fails).
499 * Return value: the new socket (not yet ready for use).
502 soup_socket_client_new_async (const char *hostname, guint port, gboolean ssl,
503 SoupSocketCallback callback, gpointer user_data)
507 g_return_val_if_fail (hostname != NULL, NULL);
509 sock = soup_socket_new ();
510 sock->priv->flags = (SOUP_SOCKET_FLAG_NONBLOCKING |
511 (ssl ? SOUP_SOCKET_FLAG_SSL : 0));
512 soup_socket_connect (sock, soup_address_new (hostname, port));
515 soup_signal_connect_once (sock, "connect_result",
516 G_CALLBACK (callback), user_data);
522 * soup_socket_client_new_sync:
523 * @hostname: remote machine to connect to
524 * @port: remote port to connect to
525 * @ssl: whether or not to use SSL
526 * @status_ret: pointer to return the soup status in
528 * Creates a connection to @hostname and @port. If @status_ret is not
529 * %NULL, it will contain a status code on return.
531 * Return value: the new socket, or %NULL if it could not connect.
534 soup_socket_client_new_sync (const char *hostname, guint port, gboolean ssl,
540 g_return_val_if_fail (hostname != NULL, NULL);
542 sock = soup_socket_new ();
543 sock->priv->flags = ssl ? SOUP_SOCKET_FLAG_SSL : 0;
544 status = soup_socket_connect (sock, soup_address_new (hostname, port));
546 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
547 g_object_unref (sock);
552 *status_ret = status;
557 * soup_socket_server_new:
558 * @local_addr: Local address to bind to. (Use soup_address_any_new() to
559 * accept connections on any local address)
560 * @ssl: Whether or not this is an SSL server.
561 * @callback: Callback to call when a client connects
562 * @user_data: data to pass to @callback.
564 * Create and open a new #SoupSocket listening on the specified
565 * address. @callback will be called each time a client connects,
566 * with a new #SoupSocket.
568 * Returns: a new #SoupSocket, or NULL if there was a failure.
571 soup_socket_server_new (SoupAddress *local_addr, gboolean ssl,
572 SoupSocketListenerCallback callback,
577 g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), NULL);
579 sock = soup_socket_new ();
580 sock->priv->flags = (SOUP_SOCKET_FLAG_SERVER |
581 SOUP_SOCKET_FLAG_NONBLOCKING |
582 (ssl ? SOUP_SOCKET_FLAG_SSL : 0));
583 if (!soup_socket_listen (sock, local_addr)) {
584 g_object_unref (sock);
589 g_signal_connect (sock, "new_connection",
590 G_CALLBACK (callback), user_data);
598 soup_socket_disconnect (SoupSocket *sock)
600 g_return_if_fail (SOUP_IS_SOCKET (sock));
602 if (!sock->priv->iochannel)
605 disconnect_internal (sock);
607 /* Give all readers a chance to notice the connection close */
608 g_signal_emit (sock, signals[READABLE], 0);
610 /* FIXME: can't disconnect until all data is read */
612 /* Then let everyone know we're disconnected */
613 g_signal_emit (sock, signals[DISCONNECTED], 0);
617 soup_socket_is_connected (SoupSocket *sock)
619 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
621 return sock->priv->iochannel != NULL;
626 soup_socket_get_local_address (SoupSocket *sock)
628 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
630 if (!sock->priv->local_addr) {
631 struct soup_sockaddr_max bound_sa;
634 sa_len = sizeof (bound_sa);
635 getsockname (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
636 sock->priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
639 return sock->priv->local_addr;
643 soup_socket_get_remote_address (SoupSocket *sock)
645 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
647 if (!sock->priv->local_addr) {
648 struct soup_sockaddr_max bound_sa;
651 sa_len = sizeof (bound_sa);
652 getpeername (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
653 sock->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
656 return sock->priv->remote_addr;
663 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
665 SoupSocket *sock = user_data;
667 sock->priv->read_tag = 0;
668 g_signal_emit (sock, signals[READABLE], 0);
673 static SoupSocketIOStatus
674 read_from_network (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
678 if (!sock->priv->iochannel)
679 return SOUP_SOCKET_EOF;
681 status = g_io_channel_read_chars (sock->priv->iochannel,
682 buffer, len, nread, NULL);
684 case G_IO_STATUS_NORMAL:
685 case G_IO_STATUS_AGAIN:
687 return SOUP_SOCKET_OK;
689 if (!sock->priv->read_tag) {
690 sock->priv->read_tag =
691 g_io_add_watch (sock->priv->iochannel, G_IO_IN,
692 socket_read_watch, sock);
694 return SOUP_SOCKET_WOULD_BLOCK;
696 case G_IO_STATUS_EOF:
697 return SOUP_SOCKET_EOF;
700 return SOUP_SOCKET_ERROR;
704 static SoupSocketIOStatus
705 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
707 GByteArray *read_buf = sock->priv->read_buf;
709 *nread = MIN (read_buf->len, len);
710 memcpy (buffer, read_buf->data, *nread);
712 if (*nread == read_buf->len) {
713 g_byte_array_free (read_buf, TRUE);
714 sock->priv->read_buf = NULL;
716 memcpy (read_buf->data, read_buf->data + *nread,
717 read_buf->len - *nread);
718 g_byte_array_set_size (read_buf, read_buf->len - *nread);
721 return SOUP_SOCKET_OK;
727 * @buffer: buffer to read into
728 * @len: size of @buffer in bytes
729 * @nread: on return, the number of bytes read into @buffer
731 * Attempts to read up to @len bytes from @sock into @buffer. If some
732 * data is successfully read, soup_socket_read() will return
733 * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
736 * If @sock is non-blocking, and no data is available, the return
737 * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
738 * can connect to the %readable signal to know when there is more data
739 * to read. (NB: You MUST read all available data off the socket
740 * first. The %readable signal will only be emitted after
741 * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
743 * Return value: a #SoupSocketIOStatus, as described above (or
744 * %SOUP_SOCKET_EOF if the socket is no longer connected, or
745 * %SOUP_SOCKET_ERROR on any other error).
748 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
750 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
752 if (sock->priv->read_buf)
753 return read_from_buf (sock, buffer, len, nread);
755 return read_from_network (sock, buffer, len, nread);
759 * soup_socket_read_until:
761 * @buffer: buffer to read into
762 * @len: size of @buffer in bytes
763 * @boundary: boundary to read until
764 * @boundary_len: length of @boundary in bytes
765 * @nread: on return, the number of bytes read into @buffer
766 * @got_boundary: on return, whether or not the data in @buffer
767 * ends with the boundary string
769 * Like soup_socket_read(), but reads no further than the first
770 * occurrence of @boundary. (If the boundary is found, it will be
771 * included in the returned data, and *@got_boundary will be set to
772 * %TRUE.) Any data after the boundary will returned in future reads.
774 * Return value: as for soup_socket_read()
777 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
778 gconstpointer boundary, gsize boundary_len,
779 gsize *nread, gboolean *got_boundary)
781 SoupSocketIOStatus status;
782 GByteArray *read_buf;
783 guint match_len, prev_len;
786 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
787 g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
789 *got_boundary = FALSE;
791 if (!sock->priv->read_buf)
792 sock->priv->read_buf = g_byte_array_new ();
793 read_buf = sock->priv->read_buf;
795 if (read_buf->len < boundary_len) {
796 prev_len = read_buf->len;
797 g_byte_array_set_size (read_buf, len);
798 status = read_from_network (sock,
799 read_buf->data + prev_len,
800 len - prev_len, nread);
801 read_buf->len = prev_len + *nread;
803 if (status != SOUP_SOCKET_OK)
807 /* Scan for the boundary */
808 end = read_buf->data + read_buf->len;
809 for (p = read_buf->data; p <= end - boundary_len; p++) {
810 if (!memcmp (p, boundary, boundary_len)) {
812 *got_boundary = TRUE;
817 /* Return everything up to 'p' (which is either just after the
818 * boundary, or @boundary_len - 1 bytes before the end of the
821 match_len = p - read_buf->data;
822 return read_from_buf (sock, buffer, MIN (len, match_len), nread);
826 socket_write_watch (GIOChannel *chan, GIOCondition condition, gpointer user_data)
828 SoupSocket *sock = user_data;
830 sock->priv->write_tag = 0;
831 g_signal_emit (sock, signals[WRITABLE], 0);
839 * @buffer: data to write
840 * @len: size of @buffer, in bytes
841 * @nwrite: on return, number of bytes written
843 * Attempts to write @len bytes from @buffer to @sock. If some data is
844 * successfully written, the resturn status will be
845 * %SOUP_SOCKET_SUCCESS, and *@nwrote will contain the number of bytes
848 * If @sock is non-blocking, and no data could be written right away,
849 * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
850 * the caller can connect to the %writable signal to know when more
851 * data can be written. (NB: %writable is only emitted after a
852 * %SOUP_SOCKET_WOULD_BLOCK.)
854 * Return value: a #SoupSocketIOStatus, as described above (or
855 * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR).
858 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
859 gsize len, gsize *nwrote)
862 gpointer pipe_handler;
864 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
866 if (!sock->priv->iochannel)
867 return SOUP_SOCKET_EOF;
868 if (sock->priv->write_tag)
869 return SOUP_SOCKET_WOULD_BLOCK;
871 pipe_handler = signal (SIGPIPE, SIG_IGN);
872 status = g_io_channel_write_chars (sock->priv->iochannel,
873 buffer, len, nwrote, NULL);
874 signal (SIGPIPE, pipe_handler);
875 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN)
876 return SOUP_SOCKET_ERROR;
879 return SOUP_SOCKET_OK;
881 sock->priv->write_tag =
882 g_io_add_watch (sock->priv->iochannel, G_IO_OUT,
883 socket_write_watch, sock);
884 return SOUP_SOCKET_WOULD_BLOCK;