• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-socket.c: Socket networking code.
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <string.h>
13 
14 #include <glib/gi18n-lib.h>
15 #include <gio/gnetworking.h>
16 
17 #include "soup-socket.h"
18 #include "soup-socket-private.h"
19 #include "soup.h"
20 #include "soup-filter-input-stream.h"
21 #include "soup-io-stream.h"
22 
23 /**
24  * SECTION:soup-socket
25  * @short_description: A network socket
26  *
27  * #SoupSocket is libsoup's TCP socket type. While it is primarily
28  * intended for internal use, #SoupSocket<!-- -->s are exposed in the
29  * API in various places, and some of their methods (eg,
30  * soup_socket_get_remote_address()) may be useful to applications.
31  **/
32 
33 enum {
34 	READABLE,
35 	WRITABLE,
36 	DISCONNECTED,
37 	NEW_CONNECTION,
38 	EVENT,
39 	LAST_SIGNAL
40 };
41 
42 static guint signals[LAST_SIGNAL] = { 0 };
43 
44 enum {
45 	PROP_0,
46 
47 	PROP_FD,
48 	PROP_GSOCKET,
49 	PROP_IOSTREAM,
50 	PROP_LOCAL_ADDRESS,
51 	PROP_REMOTE_ADDRESS,
52 	PROP_NON_BLOCKING,
53 	PROP_IPV6_ONLY,
54 	PROP_IS_SERVER,
55 	PROP_SSL_CREDENTIALS,
56 	PROP_SSL_STRICT,
57 	PROP_SSL_FALLBACK,
58 	PROP_ASYNC_CONTEXT,
59 	PROP_USE_THREAD_CONTEXT,
60 	PROP_TIMEOUT,
61 	PROP_TRUSTED_CERTIFICATE,
62 	PROP_TLS_CERTIFICATE,
63 	PROP_TLS_ERRORS,
64 	PROP_SOCKET_PROPERTIES,
65 
66 	LAST_PROP
67 };
68 
69 typedef struct {
70 	SoupAddress *local_addr, *remote_addr;
71 	GIOStream *conn, *iostream;
72 	GSocket *gsock;
73 	GInputStream *istream;
74 	GOutputStream *ostream;
75 	GTlsCertificateFlags tls_errors;
76 	GTlsInteraction *tls_interaction;
77 	GProxyResolver *proxy_resolver;
78 
79 	guint non_blocking:1;
80 	guint ipv6_only:1;
81 	guint is_server:1;
82 	guint ssl:1;
83 	guint ssl_strict:1;
84 	guint ssl_fallback:1;
85 	guint clean_dispose:1;
86 	guint use_thread_context:1;
87 	gpointer ssl_creds;
88 
89 	GMainContext   *async_context;
90 	GSource        *watch_src;
91 	GSource        *read_src, *write_src;
92 
93 	GMutex iolock, addrlock;
94 	guint timeout;
95 
96 	GCancellable *connect_cancel;
97 	int fd;
98 } SoupSocketPrivate;
99 
100 static void soup_socket_initable_interface_init (GInitableIface *initable_interface);
101 
102 G_DEFINE_TYPE_WITH_CODE (SoupSocket, soup_socket, G_TYPE_OBJECT,
103                          G_ADD_PRIVATE (SoupSocket)
104 			 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
105 						soup_socket_initable_interface_init))
106 
107 static void soup_socket_peer_certificate_changed (GObject *conn,
108 						  GParamSpec *pspec,
109 						  gpointer user_data);
110 static void finish_socket_setup (SoupSocket *sock);
111 static void finish_listener_setup (SoupSocket *sock);
112 
113 static void
soup_socket_init(SoupSocket * sock)114 soup_socket_init (SoupSocket *sock)
115 {
116 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
117 
118 	priv->non_blocking = TRUE;
119 	priv->fd = -1;
120 	g_mutex_init (&priv->addrlock);
121 	g_mutex_init (&priv->iolock);
122 }
123 
124 static gboolean
soup_socket_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)125 soup_socket_initable_init (GInitable     *initable,
126 			   GCancellable  *cancellable,
127 			   GError       **error)
128 {
129 	SoupSocket *sock = SOUP_SOCKET (initable);
130 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
131 
132 	if (priv->conn) {
133 		g_warn_if_fail (priv->gsock == NULL);
134 		g_warn_if_fail (priv->fd == -1);
135 
136 		finish_socket_setup (sock);
137 	}
138 
139 	if (priv->fd != -1) {
140 		guint type, len = sizeof (type);
141 
142 		g_warn_if_fail (priv->gsock == NULL);
143 
144 		/* GSocket will g_error() this, so we have to check ourselves. */
145 		if (getsockopt (priv->fd, SOL_SOCKET, SO_TYPE,
146 				(gpointer)&type, (gpointer)&len) == -1) {
147 			g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
148 					     _("Can’t import non-socket as SoupSocket"));
149 			return FALSE;
150 		}
151 
152 		priv->gsock = g_socket_new_from_fd (priv->fd, error);
153 		if (!priv->gsock)
154 			return FALSE;
155 	}
156 
157 	if (priv->gsock != NULL) {
158 		int listening;
159 
160 		g_warn_if_fail (priv->local_addr == NULL);
161 		g_warn_if_fail (priv->remote_addr == NULL);
162 
163 		if (!g_socket_get_option (priv->gsock,
164 					  SOL_SOCKET, SO_ACCEPTCONN,
165 					  &listening, error)) {
166 			g_prefix_error (error, _("Could not import existing socket: "));
167 			return FALSE;
168 		}
169 
170 		finish_socket_setup (sock);
171 		if (listening)
172 			finish_listener_setup (sock);
173 		else if (!g_socket_is_connected (priv->gsock)) {
174 			g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
175 					     _("Can’t import unconnected socket"));
176 			return FALSE;
177 		}
178 	}
179 
180 	return TRUE;
181 }
182 
183 static void
disconnect_internal(SoupSocket * sock,gboolean close)184 disconnect_internal (SoupSocket *sock, gboolean close)
185 {
186 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
187 
188 	g_clear_object (&priv->gsock);
189 	if (priv->conn && close) {
190 		g_io_stream_close (priv->conn, NULL, NULL);
191 		g_signal_handlers_disconnect_by_data (priv->conn, sock);
192 		g_clear_object (&priv->conn);
193 	}
194 
195 	if (priv->read_src) {
196 		g_source_destroy (priv->read_src);
197 		priv->read_src = NULL;
198 	}
199 	if (priv->write_src) {
200 		g_source_destroy (priv->write_src);
201 		priv->write_src = NULL;
202 	}
203 }
204 
205 static void
soup_socket_finalize(GObject * object)206 soup_socket_finalize (GObject *object)
207 {
208 	SoupSocket *sock = SOUP_SOCKET (object);
209 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
210 
211 	if (priv->connect_cancel) {
212 		if (priv->clean_dispose)
213 			g_warning ("Disposing socket %p during connect", object);
214 		g_object_unref (priv->connect_cancel);
215 	}
216 	if (priv->conn) {
217 		if (priv->clean_dispose)
218 			g_warning ("Disposing socket %p while still connected", object);
219 		disconnect_internal (SOUP_SOCKET (object), TRUE);
220 	}
221 
222 	g_clear_object (&priv->conn);
223 	g_clear_object (&priv->iostream);
224 	g_clear_object (&priv->istream);
225 	g_clear_object (&priv->ostream);
226 
227 	g_clear_object (&priv->local_addr);
228 	g_clear_object (&priv->remote_addr);
229 
230 	g_clear_object (&priv->tls_interaction);
231 	g_clear_object (&priv->proxy_resolver);
232 	g_clear_object (&priv->ssl_creds);
233 
234 	if (priv->watch_src) {
235 		if (priv->clean_dispose && !priv->is_server)
236 			g_warning ("Disposing socket %p during async op", object);
237 		g_source_destroy (priv->watch_src);
238 	}
239 	g_clear_pointer (&priv->async_context, g_main_context_unref);
240 
241 	g_mutex_clear (&priv->addrlock);
242 	g_mutex_clear (&priv->iolock);
243 
244 	G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
245 }
246 
247 static void
finish_socket_setup(SoupSocket * sock)248 finish_socket_setup (SoupSocket *sock)
249 {
250 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
251 
252 	if (priv->gsock) {
253 		if (!priv->conn)
254 			priv->conn = (GIOStream *)g_socket_connection_factory_create_connection (priv->gsock);
255 
256 		g_socket_set_timeout (priv->gsock, priv->timeout);
257 		g_socket_set_option (priv->gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
258 	}
259 
260 	if (!priv->conn)
261 		return;
262 
263 	if (!priv->iostream)
264 		priv->iostream = soup_io_stream_new (priv->conn, FALSE);
265 	if (!priv->istream)
266 		priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
267 	if (!priv->ostream)
268 		priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
269 }
270 
271 static void
soup_socket_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)272 soup_socket_set_property (GObject *object, guint prop_id,
273 			  const GValue *value, GParamSpec *pspec)
274 {
275 	SoupSocket *sock = SOUP_SOCKET (object);
276 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
277 	SoupSocketProperties *props;
278 
279 	switch (prop_id) {
280 	case PROP_FD:
281 		priv->fd = g_value_get_int (value);
282 		break;
283 	case PROP_GSOCKET:
284 		priv->gsock = g_value_dup_object (value);
285 		break;
286 	case PROP_IOSTREAM:
287 		priv->conn = g_value_dup_object (value);
288 		break;
289 	case PROP_LOCAL_ADDRESS:
290 		priv->local_addr = g_value_dup_object (value);
291 		break;
292 	case PROP_REMOTE_ADDRESS:
293 		priv->remote_addr = g_value_dup_object (value);
294 		break;
295 	case PROP_NON_BLOCKING:
296 		priv->non_blocking = g_value_get_boolean (value);
297 		break;
298 	case PROP_IPV6_ONLY:
299 		priv->ipv6_only = g_value_get_boolean (value);
300 		break;
301 	case PROP_SSL_CREDENTIALS:
302 		priv->ssl_creds = g_value_get_pointer (value);
303 		if (priv->ssl_creds)
304 			g_object_ref (priv->ssl_creds);
305 		break;
306 	case PROP_SSL_STRICT:
307 		priv->ssl_strict = g_value_get_boolean (value);
308 		break;
309 	case PROP_SSL_FALLBACK:
310 		priv->ssl_fallback = g_value_get_boolean (value);
311 		break;
312 	case PROP_ASYNC_CONTEXT:
313 		if (!priv->use_thread_context) {
314 			priv->async_context = g_value_get_pointer (value);
315 			if (priv->async_context)
316 				g_main_context_ref (priv->async_context);
317 		}
318 		break;
319 	case PROP_USE_THREAD_CONTEXT:
320 		priv->use_thread_context = g_value_get_boolean (value);
321 		if (priv->use_thread_context) {
322 			g_clear_pointer (&priv->async_context, g_main_context_unref);
323 			priv->async_context = g_main_context_ref_thread_default ();
324 		}
325 		break;
326 	case PROP_TIMEOUT:
327 		priv->timeout = g_value_get_uint (value);
328 		if (priv->conn)
329 			g_socket_set_timeout (priv->gsock, priv->timeout);
330 		break;
331 	case PROP_SOCKET_PROPERTIES:
332 		props = g_value_get_boxed (value);
333 		if (props) {
334 			g_clear_pointer (&priv->async_context, g_main_context_unref);
335 			if (props->use_thread_context) {
336 				priv->use_thread_context = TRUE;
337 				priv->async_context = g_main_context_ref_thread_default ();
338 			} else {
339 				priv->use_thread_context = FALSE;
340 				if (props->async_context)
341 					priv->async_context = g_main_context_ref (props->async_context);
342 			}
343 
344 			g_clear_object (&priv->proxy_resolver);
345 			if (props->proxy_resolver)
346 				priv->proxy_resolver = g_object_ref (props->proxy_resolver);
347 
348 			g_clear_object (&priv->local_addr);
349 			if (props->local_addr)
350 				priv->local_addr = g_object_ref (props->local_addr);
351 
352 			g_clear_object (&priv->ssl_creds);
353 			if (props->tlsdb)
354 				priv->ssl_creds = g_object_ref (props->tlsdb);
355 			g_clear_object (&priv->tls_interaction);
356 			if (props->tls_interaction)
357 				priv->tls_interaction = g_object_ref (props->tls_interaction);
358 			priv->ssl_strict = props->ssl_strict;
359 
360 			priv->timeout = props->io_timeout;
361 			if (priv->conn)
362 				g_socket_set_timeout (priv->gsock, priv->timeout);
363 
364 			priv->clean_dispose = TRUE;
365 		}
366 		break;
367 	default:
368 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
369 		break;
370 	}
371 }
372 
373 static void
soup_socket_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)374 soup_socket_get_property (GObject *object, guint prop_id,
375 			  GValue *value, GParamSpec *pspec)
376 {
377 	SoupSocket *sock = SOUP_SOCKET (object);
378 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
379 
380 	switch (prop_id) {
381 	case PROP_FD:
382 		g_value_set_int (value, priv->fd);
383 		break;
384 	case PROP_LOCAL_ADDRESS:
385 		g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
386 		break;
387 	case PROP_REMOTE_ADDRESS:
388 		g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
389 		break;
390 	case PROP_NON_BLOCKING:
391 		g_value_set_boolean (value, priv->non_blocking);
392 		break;
393 	case PROP_IPV6_ONLY:
394 		g_value_set_boolean (value, priv->ipv6_only);
395 		break;
396 	case PROP_IS_SERVER:
397 		g_value_set_boolean (value, priv->is_server);
398 		break;
399 	case PROP_SSL_CREDENTIALS:
400 		g_value_set_pointer (value, priv->ssl_creds);
401 		break;
402 	case PROP_SSL_STRICT:
403 		g_value_set_boolean (value, priv->ssl_strict);
404 		break;
405 	case PROP_SSL_FALLBACK:
406 		g_value_set_boolean (value, priv->ssl_fallback);
407 		break;
408 	case PROP_TRUSTED_CERTIFICATE:
409 		g_value_set_boolean (value, priv->tls_errors == 0);
410 		break;
411 	case PROP_ASYNC_CONTEXT:
412 		g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
413 		break;
414 	case PROP_USE_THREAD_CONTEXT:
415 		g_value_set_boolean (value, priv->use_thread_context);
416 		break;
417 	case PROP_TIMEOUT:
418 		g_value_set_uint (value, priv->timeout);
419 		break;
420 	case PROP_TLS_CERTIFICATE:
421 		if (G_IS_TLS_CONNECTION (priv->conn))
422 			g_value_set_object (value, g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (priv->conn)));
423 		else
424 			g_value_set_object (value, NULL);
425 		break;
426 	case PROP_TLS_ERRORS:
427 		g_value_set_flags (value, priv->tls_errors);
428 		break;
429 	default:
430 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
431 		break;
432 	}
433 }
434 
435 static void
soup_socket_class_init(SoupSocketClass * socket_class)436 soup_socket_class_init (SoupSocketClass *socket_class)
437 {
438 	GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
439 
440 	/* virtual method override */
441 	object_class->finalize = soup_socket_finalize;
442 	object_class->set_property = soup_socket_set_property;
443 	object_class->get_property = soup_socket_get_property;
444 
445 	/* signals */
446 
447 	/**
448 	 * SoupSocket::readable:
449 	 * @sock: the socket
450 	 *
451 	 * Emitted when an async socket is readable. See
452 	 * soup_socket_read(), soup_socket_read_until() and
453 	 * #SoupSocket:non-blocking.
454 	 **/
455 	signals[READABLE] =
456 		g_signal_new ("readable",
457 			      G_OBJECT_CLASS_TYPE (object_class),
458 			      G_SIGNAL_RUN_LAST,
459 			      G_STRUCT_OFFSET (SoupSocketClass, readable),
460 			      NULL, NULL,
461 			      NULL,
462 			      G_TYPE_NONE, 0);
463 
464 	/**
465 	 * SoupSocket::writable:
466 	 * @sock: the socket
467 	 *
468 	 * Emitted when an async socket is writable. See
469 	 * soup_socket_write() and #SoupSocket:non-blocking.
470 	 **/
471 	signals[WRITABLE] =
472 		g_signal_new ("writable",
473 			      G_OBJECT_CLASS_TYPE (object_class),
474 			      G_SIGNAL_RUN_LAST,
475 			      G_STRUCT_OFFSET (SoupSocketClass, writable),
476 			      NULL, NULL,
477 			      NULL,
478 			      G_TYPE_NONE, 0);
479 
480 	/**
481 	 * SoupSocket::disconnected:
482 	 * @sock: the socket
483 	 *
484 	 * Emitted when the socket is disconnected, for whatever
485 	 * reason.
486 	 **/
487 	signals[DISCONNECTED] =
488 		g_signal_new ("disconnected",
489 			      G_OBJECT_CLASS_TYPE (object_class),
490 			      G_SIGNAL_RUN_LAST,
491 			      G_STRUCT_OFFSET (SoupSocketClass, disconnected),
492 			      NULL, NULL,
493 			      NULL,
494 			      G_TYPE_NONE, 0);
495 
496 	/**
497 	 * SoupSocket::new-connection:
498 	 * @sock: the socket
499 	 * @new: the new socket
500 	 *
501 	 * Emitted when a listening socket (set up with
502 	 * soup_socket_listen()) receives a new connection.
503 	 *
504 	 * You must ref the @new if you want to keep it; otherwise it
505 	 * will be destroyed after the signal is emitted.
506 	 **/
507 	signals[NEW_CONNECTION] =
508 		g_signal_new ("new_connection",
509 			      G_OBJECT_CLASS_TYPE (object_class),
510 			      G_SIGNAL_RUN_FIRST,
511 			      G_STRUCT_OFFSET (SoupSocketClass, new_connection),
512 			      NULL, NULL,
513 			      NULL,
514 			      G_TYPE_NONE, 1,
515 			      SOUP_TYPE_SOCKET);
516 	/**
517 	 * SoupSocket::event:
518 	 * @sock: the socket
519 	 * @event: the event that occurred
520 	 * @connection: the current connection state
521 	 *
522 	 * Emitted when a network-related event occurs. See
523 	 * #GSocketClient::event for more details.
524 	 *
525 	 * Since: 2.38
526 	 **/
527 	signals[EVENT] =
528 		g_signal_new ("event",
529 			      G_OBJECT_CLASS_TYPE (object_class),
530 			      G_SIGNAL_RUN_LAST,
531 			      0,
532 			      NULL, NULL,
533 			      NULL,
534 			      G_TYPE_NONE, 2,
535 			      G_TYPE_SOCKET_CLIENT_EVENT,
536 			      G_TYPE_IO_STREAM);
537 
538 
539 	/* properties */
540 	g_object_class_install_property (
541 		 object_class, PROP_FD,
542 		 g_param_spec_int (SOUP_SOCKET_FD,
543 				   "FD",
544 				   "The socket's file descriptor",
545 				   -1, G_MAXINT, -1,
546 				   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
547 				   G_PARAM_STATIC_STRINGS));
548 	g_object_class_install_property (
549 		 object_class, PROP_GSOCKET,
550 		 g_param_spec_object (SOUP_SOCKET_GSOCKET,
551 				      "GSocket",
552 				      "The socket's underlying GSocket",
553 				      G_TYPE_SOCKET,
554 				      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
555 				      G_PARAM_STATIC_STRINGS));
556 	g_object_class_install_property (
557 		 object_class, PROP_IOSTREAM,
558 		 g_param_spec_object (SOUP_SOCKET_IOSTREAM,
559 				      "GIOStream",
560 				      "The socket's underlying GIOStream",
561 				      G_TYPE_IO_STREAM,
562 				      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
563 				      G_PARAM_STATIC_STRINGS));
564 
565 	/**
566 	 * SOUP_SOCKET_LOCAL_ADDRESS:
567 	 *
568 	 * Alias for the #SoupSocket:local-address property. (Address
569 	 * of local end of socket.)
570 	 **/
571 	g_object_class_install_property (
572 		object_class, PROP_LOCAL_ADDRESS,
573 		g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
574 				     "Local address",
575 				     "Address of local end of socket",
576 				     SOUP_TYPE_ADDRESS,
577 				     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
578 				     G_PARAM_STATIC_STRINGS));
579 	/**
580 	 * SOUP_SOCKET_REMOTE_ADDRESS:
581 	 *
582 	 * Alias for the #SoupSocket:remote-address property. (Address
583 	 * of remote end of socket.)
584 	 **/
585 	g_object_class_install_property (
586 		object_class, PROP_REMOTE_ADDRESS,
587 		g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
588 				     "Remote address",
589 				     "Address of remote end of socket",
590 				     SOUP_TYPE_ADDRESS,
591 				     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
592 				     G_PARAM_STATIC_STRINGS));
593 	/**
594 	 * SoupSocket:non-blocking:
595 	 *
596 	 * Whether or not the socket uses non-blocking I/O.
597 	 *
598 	 * #SoupSocket's I/O methods are designed around the idea of
599 	 * using a single codepath for both synchronous and
600 	 * asynchronous I/O. If you want to read off a #SoupSocket,
601 	 * the "correct" way to do it is to call soup_socket_read() or
602 	 * soup_socket_read_until() repeatedly until you have read
603 	 * everything you want. If it returns %SOUP_SOCKET_WOULD_BLOCK
604 	 * at any point, stop reading and wait for it to emit the
605 	 * #SoupSocket::readable signal. Then go back to the
606 	 * reading-as-much-as-you-can loop. Likewise, for writing to a
607 	 * #SoupSocket, you should call soup_socket_write() either
608 	 * until you have written everything, or it returns
609 	 * %SOUP_SOCKET_WOULD_BLOCK (in which case you wait for
610 	 * #SoupSocket::writable and then go back into the loop).
611 	 *
612 	 * Code written this way will work correctly with both
613 	 * blocking and non-blocking sockets; blocking sockets will
614 	 * simply never return %SOUP_SOCKET_WOULD_BLOCK, and so the
615 	 * code that handles that case just won't get used for them.
616 	 **/
617 	/**
618 	 * SOUP_SOCKET_FLAG_NONBLOCKING:
619 	 *
620 	 * Alias for the #SoupSocket:non-blocking property. (Whether
621 	 * or not the socket uses non-blocking I/O.)
622 	 **/
623 	g_object_class_install_property (
624 		object_class, PROP_NON_BLOCKING,
625 		g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
626 				      "Non-blocking",
627 				      "Whether or not the socket uses non-blocking I/O",
628 				      TRUE,
629 				      G_PARAM_READWRITE |
630 				      G_PARAM_STATIC_STRINGS));
631 	g_object_class_install_property (
632 		object_class, PROP_IPV6_ONLY,
633 		g_param_spec_boolean (SOUP_SOCKET_IPV6_ONLY,
634 				      "IPv6 only",
635 				      "IPv6 only",
636 				      FALSE,
637 				      G_PARAM_READWRITE |
638 				      G_PARAM_STATIC_STRINGS));
639 	/**
640 	 * SOUP_SOCKET_IS_SERVER:
641 	 *
642 	 * Alias for the #SoupSocket:is-server property, qv.
643 	 **/
644 	/**
645 	 * SoupSocket:is-server:
646 	 *
647 	 * Whether or not the socket is a server socket.
648 	 *
649 	 * Note that for "ordinary" #SoupSockets this will be set for
650 	 * both listening sockets and the sockets emitted by
651 	 * #SoupSocket::new-connection, but for sockets created by
652 	 * setting #SoupSocket:fd, it will only be set for listening
653 	 * sockets.
654 	 **/
655 	g_object_class_install_property (
656 		object_class, PROP_IS_SERVER,
657 		g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
658 				      "Server",
659 				      "Whether or not the socket is a server socket",
660 				      FALSE,
661 				      G_PARAM_READABLE |
662 				      G_PARAM_STATIC_STRINGS));
663 	/**
664 	 * SOUP_SOCKET_SSL_CREDENTIALS:
665 	 *
666 	 * Alias for the #SoupSocket:ssl-creds property.
667 	 * (SSL credential information.)
668 	 **/
669 	/* For historical reasons, there's only a single property
670 	 * here, which is a GTlsDatabase for client sockets, and
671 	 * a GTlsCertificate for server sockets. Whee!
672 	 */
673 	g_object_class_install_property (
674 		object_class, PROP_SSL_CREDENTIALS,
675 		g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
676 				      "SSL credentials",
677 				      "SSL credential information, passed from the session to the SSL implementation",
678 				      G_PARAM_READWRITE |
679 				      G_PARAM_STATIC_STRINGS));
680 	/**
681 	 * SOUP_SOCKET_SSL_STRICT:
682 	 *
683 	 * Alias for the #SoupSocket:ssl-strict property.
684 	 **/
685 	g_object_class_install_property (
686 		object_class, PROP_SSL_STRICT,
687 		g_param_spec_boolean (SOUP_SOCKET_SSL_STRICT,
688 				      "Strictly validate SSL certificates",
689 				      "Whether certificate errors should be considered a connection error",
690 				      TRUE,
691 				      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
692 				      G_PARAM_STATIC_STRINGS));
693 	/**
694 	 * SOUP_SOCKET_SSL_FALLBACK:
695 	 *
696 	 * Alias for the #SoupSocket:ssl-fallback property.
697 	 **/
698 	g_object_class_install_property (
699 		object_class, PROP_SSL_FALLBACK,
700 		g_param_spec_boolean (SOUP_SOCKET_SSL_FALLBACK,
701 				      "SSLv3 fallback",
702 				      "Use SSLv3 instead of TLS (client-side only)",
703 				      FALSE,
704 				      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
705 				      G_PARAM_STATIC_STRINGS));
706 	/**
707 	 * SOUP_SOCKET_TRUSTED_CERTIFICATE:
708 	 *
709 	 * Alias for the #SoupSocket:trusted-certificate
710 	 * property.
711 	 **/
712 	g_object_class_install_property (
713 		object_class, PROP_TRUSTED_CERTIFICATE,
714 		g_param_spec_boolean (SOUP_SOCKET_TRUSTED_CERTIFICATE,
715 				     "Trusted Certificate",
716 				     "Whether the server certificate is trusted, if this is an SSL socket",
717 				     FALSE,
718 				     G_PARAM_READABLE |
719 				     G_PARAM_STATIC_STRINGS));
720 	/**
721 	 * SOUP_SOCKET_ASYNC_CONTEXT:
722 	 *
723 	 * Alias for the #SoupSocket:async-context property. (The
724 	 * socket's #GMainContext.)
725 	 **/
726 	g_object_class_install_property (
727 		object_class, PROP_ASYNC_CONTEXT,
728 		g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
729 				      "Async GMainContext",
730 				      "The GMainContext to dispatch this socket's async I/O in",
731 				      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
732 				      G_PARAM_STATIC_STRINGS));
733 
734 	/**
735 	 * SOUP_SOCKET_USE_THREAD_CONTEXT:
736 	 *
737 	 * Alias for the #SoupSocket:use-thread-context property. (Use
738 	 * g_main_context_get_thread_default())
739 	 *
740 	 * Since: 2.38
741 	 */
742 	/**
743 	 * SoupSocket:use-thread-context:
744 	 *
745 	 * Use g_main_context_get_thread_default().
746 	 *
747 	 * Since: 2.38
748 	 */
749 	g_object_class_install_property (
750 		object_class, PROP_USE_THREAD_CONTEXT,
751 		g_param_spec_boolean (SOUP_SOCKET_USE_THREAD_CONTEXT,
752 				      "Use thread context",
753 				      "Use g_main_context_get_thread_default",
754 				      FALSE,
755 				      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
756 				      G_PARAM_STATIC_STRINGS));
757 
758 	/**
759 	 * SOUP_SOCKET_TIMEOUT:
760 	 *
761 	 * Alias for the #SoupSocket:timeout property. (The timeout
762 	 * in seconds for blocking socket I/O operations.)
763 	 **/
764 	g_object_class_install_property (
765 		object_class, PROP_TIMEOUT,
766 		g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
767 				   "Timeout value",
768 				   "Value in seconds to timeout a blocking I/O",
769 				   0, G_MAXUINT, 0,
770 				   G_PARAM_READWRITE |
771 				   G_PARAM_STATIC_STRINGS));
772 
773 	/**
774 	 * SOUP_SOCKET_TLS_CERTIFICATE:
775 	 *
776 	 * Alias for the #SoupSocket:tls-certificate
777 	 * property. Note that this property's value is only useful
778 	 * if the socket is for a TLS connection, and only reliable
779 	 * after some data has been transferred to or from it.
780 	 *
781 	 * Since: 2.34
782 	 **/
783 	g_object_class_install_property (
784 		object_class, PROP_TLS_CERTIFICATE,
785 		g_param_spec_object (SOUP_SOCKET_TLS_CERTIFICATE,
786 				     "TLS certificate",
787 				     "The peer's TLS certificate",
788 				     G_TYPE_TLS_CERTIFICATE,
789 				     G_PARAM_READABLE |
790 				     G_PARAM_STATIC_STRINGS));
791 	/**
792 	 * SOUP_SOCKET_TLS_ERRORS:
793 	 *
794 	 * Alias for the #SoupSocket:tls-errors
795 	 * property. Note that this property's value is only useful
796 	 * if the socket is for a TLS connection, and only reliable
797 	 * after some data has been transferred to or from it.
798 	 *
799 	 * Since: 2.34
800 	 **/
801 	g_object_class_install_property (
802 		object_class, PROP_TLS_ERRORS,
803 		g_param_spec_flags (SOUP_SOCKET_TLS_ERRORS,
804 				    "TLS errors",
805 				    "Errors with the peer's TLS certificate",
806 				    G_TYPE_TLS_CERTIFICATE_FLAGS, 0,
807 				    G_PARAM_READABLE |
808 				    G_PARAM_STATIC_STRINGS));
809 
810 	g_object_class_install_property (
811 		 object_class, PROP_SOCKET_PROPERTIES,
812 		 g_param_spec_boxed (SOUP_SOCKET_SOCKET_PROPERTIES,
813 				     "Socket properties",
814 				     "Socket properties",
815 				     SOUP_TYPE_SOCKET_PROPERTIES,
816 				     G_PARAM_WRITABLE |
817 				     G_PARAM_STATIC_STRINGS));
818 }
819 
820 static void
soup_socket_initable_interface_init(GInitableIface * initable_interface)821 soup_socket_initable_interface_init (GInitableIface *initable_interface)
822 {
823 	initable_interface->init = soup_socket_initable_init;
824 }
825 
826 
827 /**
828  * soup_socket_new:
829  * @optname1: name of first property to set (or %NULL)
830  * @...: value of @optname1, followed by additional property/value pairs
831  *
832  * Creates a new (disconnected) socket
833  *
834  * Return value: the new socket
835  **/
836 SoupSocket *
soup_socket_new(const char * optname1,...)837 soup_socket_new (const char *optname1, ...)
838 {
839 	SoupSocket *sock;
840 	va_list ap;
841 
842 	va_start (ap, optname1);
843 	sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
844 						  optname1, ap);
845 	va_end (ap);
846 
847 	return sock;
848 }
849 
850 static void
soup_socket_event(SoupSocket * sock,GSocketClientEvent event,GIOStream * connection)851 soup_socket_event (SoupSocket         *sock,
852 		   GSocketClientEvent  event,
853 		   GIOStream          *connection)
854 {
855 	g_signal_emit (sock, signals[EVENT], 0,
856 		       event, connection);
857 }
858 
859 static void
re_emit_socket_client_event(GSocketClient * client,GSocketClientEvent event,GSocketConnectable * connectable,GIOStream * connection,gpointer user_data)860 re_emit_socket_client_event (GSocketClient       *client,
861 			     GSocketClientEvent   event,
862 			     GSocketConnectable  *connectable,
863 			     GIOStream           *connection,
864 			     gpointer             user_data)
865 {
866 	SoupSocket *sock = user_data;
867 
868 	soup_socket_event (sock, event, connection);
869 }
870 
871 static gboolean
socket_connect_finish(SoupSocket * sock,GSocketConnection * conn)872 socket_connect_finish (SoupSocket *sock, GSocketConnection *conn)
873 {
874 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
875 
876 	g_clear_object (&priv->connect_cancel);
877 
878 	if (conn) {
879 		priv->conn = (GIOStream *)conn;
880 		priv->gsock = g_object_ref (g_socket_connection_get_socket (conn));
881 		finish_socket_setup (sock);
882 		return TRUE;
883 	} else
884 		return FALSE;
885 }
886 
887 static guint
socket_legacy_error(SoupSocket * sock,GError * error)888 socket_legacy_error (SoupSocket *sock, GError *error)
889 {
890 	guint status;
891 
892 	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
893 		status = SOUP_STATUS_CANCELLED;
894 	else if (error->domain == G_RESOLVER_ERROR)
895 		status = SOUP_STATUS_CANT_RESOLVE;
896 	else
897 		status = SOUP_STATUS_CANT_CONNECT;
898 
899 	g_error_free (error);
900 	return status;
901 }
902 
903 static GSocketClient *
new_socket_client(SoupSocket * sock)904 new_socket_client (SoupSocket *sock)
905 {
906 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
907 	GSocketClient *client = g_socket_client_new ();
908 
909 	g_signal_connect (client, "event",
910 			  G_CALLBACK (re_emit_socket_client_event), sock);
911 	if (priv->proxy_resolver) {
912 		g_socket_client_set_proxy_resolver (client, priv->proxy_resolver);
913 		g_socket_client_add_application_proxy (client, "http");
914 	} else
915 		g_socket_client_set_enable_proxy (client, FALSE);
916 	if (priv->timeout)
917 		g_socket_client_set_timeout (client, priv->timeout);
918 
919 	if (priv->local_addr) {
920 		GSocketAddress *addr;
921 
922 		addr = soup_address_get_gsockaddr (priv->local_addr);
923 		g_socket_client_set_local_address (client, addr);
924 		g_object_unref (addr);
925 	}
926 
927 	return client;
928 }
929 
930 static void
async_connected(GObject * client,GAsyncResult * result,gpointer data)931 async_connected (GObject *client, GAsyncResult *result, gpointer data)
932 {
933 	GTask *task = data;
934 	SoupSocket *sock = g_task_get_source_object (task);
935 	GSocketConnection *conn;
936 	GError *error = NULL;
937 
938 	conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client),
939 					       result, &error);
940 	if (socket_connect_finish (sock, conn))
941 		g_task_return_boolean (task, TRUE);
942 	else
943 		g_task_return_error (task, error);
944 	g_object_unref (task);
945 }
946 
947 gboolean
soup_socket_connect_finish_internal(SoupSocket * sock,GAsyncResult * result,GError ** error)948 soup_socket_connect_finish_internal (SoupSocket    *sock,
949 				     GAsyncResult  *result,
950 				     GError       **error)
951 {
952 	return g_task_propagate_boolean (G_TASK (result), error);
953 }
954 
955 void
soup_socket_connect_async_internal(SoupSocket * sock,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)956 soup_socket_connect_async_internal (SoupSocket          *sock,
957 				    GCancellable        *cancellable,
958 				    GAsyncReadyCallback  callback,
959 				    gpointer             user_data)
960 {
961 	SoupSocketPrivate *priv;
962 	GSocketClient *client;
963 	GTask *task;
964 
965 	g_return_if_fail (SOUP_IS_SOCKET (sock));
966 	priv = soup_socket_get_instance_private (sock);
967 	g_return_if_fail (!priv->is_server);
968 	g_return_if_fail (priv->gsock == NULL);
969 	g_return_if_fail (priv->remote_addr != NULL);
970 
971 	priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
972 	task = g_task_new (sock, priv->connect_cancel, callback, user_data);
973 
974 	client = new_socket_client (sock);
975 	g_socket_client_connect_async (client,
976 				       G_SOCKET_CONNECTABLE (priv->remote_addr),
977 				       priv->connect_cancel,
978 				       async_connected, task);
979 	g_object_unref (client);
980 }
981 
982 /**
983  * SoupSocketCallback:
984  * @sock: the #SoupSocket
985  * @status: an HTTP status code indicating success or failure
986  * @user_data: the data passed to soup_socket_connect_async()
987  *
988  * The callback function passed to soup_socket_connect_async().
989  **/
990 
991 typedef struct {
992 	SoupSocket *sock;
993 	SoupSocketCallback callback;
994 	gpointer user_data;
995 } SoupSocketAsyncConnectData;
996 
997 static void
legacy_connect_async_cb(GObject * object,GAsyncResult * result,gpointer user_data)998 legacy_connect_async_cb (GObject       *object,
999 			 GAsyncResult  *result,
1000 			 gpointer       user_data)
1001 {
1002 	SoupSocket *sock = SOUP_SOCKET (object);
1003 	SoupSocketAsyncConnectData *sacd = user_data;
1004 	GError *error = NULL;
1005 	guint status;
1006 
1007 	if (soup_socket_connect_finish_internal (sock, result, &error))
1008 		status = SOUP_STATUS_OK;
1009 	else
1010 		status = socket_legacy_error (sock, error);
1011 
1012 	sacd->callback (sock, status, sacd->user_data);
1013 	g_object_unref (sacd->sock);
1014 	g_slice_free (SoupSocketAsyncConnectData, sacd);
1015 }
1016 
1017 /**
1018  * soup_socket_connect_async:
1019  * @sock: a client #SoupSocket (which must not already be connected)
1020  * @cancellable: a #GCancellable, or %NULL
1021  * @callback: (scope async): callback to call after connecting
1022  * @user_data: data to pass to @callback
1023  *
1024  * Begins asynchronously connecting to @sock's remote address. The
1025  * socket will call @callback when it succeeds or fails (but not
1026  * before returning from this function).
1027  *
1028  * If @cancellable is non-%NULL, it can be used to cancel the
1029  * connection. @callback will still be invoked in this case, with a
1030  * status of %SOUP_STATUS_CANCELLED.
1031  **/
1032 void
soup_socket_connect_async(SoupSocket * sock,GCancellable * cancellable,SoupSocketCallback callback,gpointer user_data)1033 soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
1034 			   SoupSocketCallback callback, gpointer user_data)
1035 {
1036 	SoupSocketPrivate *priv;
1037 	SoupSocketAsyncConnectData *sacd;
1038 
1039 	g_return_if_fail (SOUP_IS_SOCKET (sock));
1040 	priv = soup_socket_get_instance_private (sock);
1041 	g_return_if_fail (!priv->is_server);
1042 	g_return_if_fail (priv->gsock == NULL);
1043 	g_return_if_fail (priv->remote_addr != NULL);
1044 
1045 	sacd = g_slice_new0 (SoupSocketAsyncConnectData);
1046 	sacd->sock = g_object_ref (sock);
1047 	sacd->callback = callback;
1048 	sacd->user_data = user_data;
1049 
1050 	if (priv->async_context && !priv->use_thread_context)
1051 		g_main_context_push_thread_default (priv->async_context);
1052 
1053 	soup_socket_connect_async_internal (sock, cancellable,
1054 					    legacy_connect_async_cb,
1055 					    sacd);
1056 
1057 	if (priv->async_context && !priv->use_thread_context)
1058 		g_main_context_pop_thread_default (priv->async_context);
1059 }
1060 
1061 gboolean
soup_socket_connect_sync_internal(SoupSocket * sock,GCancellable * cancellable,GError ** error)1062 soup_socket_connect_sync_internal (SoupSocket    *sock,
1063 				   GCancellable  *cancellable,
1064 				   GError       **error)
1065 {
1066 	SoupSocketPrivate *priv;
1067 	GSocketClient *client;
1068 	GSocketConnection *conn;
1069 
1070 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
1071 	priv = soup_socket_get_instance_private (sock);
1072 	g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
1073 	g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED);
1074 	g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
1075 
1076 	priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
1077 
1078 	client = new_socket_client (sock);
1079 	conn = g_socket_client_connect (client,
1080 					G_SOCKET_CONNECTABLE (priv->remote_addr),
1081 					priv->connect_cancel, error);
1082 	g_object_unref (client);
1083 
1084 	return socket_connect_finish (sock, conn);
1085 }
1086 
1087 /**
1088  * soup_socket_connect_sync:
1089  * @sock: a client #SoupSocket (which must not already be connected)
1090  * @cancellable: a #GCancellable, or %NULL
1091  *
1092  * Attempt to synchronously connect @sock to its remote address.
1093  *
1094  * If @cancellable is non-%NULL, it can be used to cancel the
1095  * connection, in which case soup_socket_connect_sync() will return
1096  * %SOUP_STATUS_CANCELLED.
1097  *
1098  * Return value: a success or failure code.
1099  **/
1100 guint
soup_socket_connect_sync(SoupSocket * sock,GCancellable * cancellable)1101 soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
1102 {
1103 	SoupSocketPrivate *priv;
1104 	GError *error = NULL;
1105 
1106 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
1107 	priv = soup_socket_get_instance_private (sock);
1108 	g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
1109 	g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED);
1110 	g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
1111 
1112 	if (soup_socket_connect_sync_internal (sock, cancellable, &error))
1113 		return SOUP_STATUS_OK;
1114 	else
1115 		return socket_legacy_error (sock, error);
1116 }
1117 
1118 /**
1119  * soup_socket_get_fd:
1120  * @sock: a #SoupSocket
1121  *
1122  * Gets @sock's underlying file descriptor.
1123  *
1124  * Note that fiddling with the file descriptor may break the
1125  * #SoupSocket.
1126  *
1127  * Return value: @sock's file descriptor.
1128  */
1129 int
soup_socket_get_fd(SoupSocket * sock)1130 soup_socket_get_fd (SoupSocket *sock)
1131 {
1132 	SoupSocketPrivate *priv;
1133 
1134 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1);
1135 
1136 	priv = soup_socket_get_instance_private (sock);
1137 
1138 	return g_socket_get_fd (priv->gsock);
1139 }
1140 
1141 GSocket *
soup_socket_get_gsocket(SoupSocket * sock)1142 soup_socket_get_gsocket (SoupSocket *sock)
1143 {
1144 	SoupSocketPrivate *priv;
1145 
1146 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1147 
1148 	priv = soup_socket_get_instance_private (sock);
1149 
1150 	return priv->gsock;
1151 }
1152 
1153 GSocket *
soup_socket_steal_gsocket(SoupSocket * sock)1154 soup_socket_steal_gsocket (SoupSocket *sock)
1155 {
1156 	SoupSocketPrivate *priv;
1157 	GSocket *gsock;
1158 
1159 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1160 	priv = soup_socket_get_instance_private (sock);
1161 
1162 	gsock = priv->gsock;
1163 	priv->gsock = NULL;
1164 	g_clear_object (&priv->conn);
1165 	g_clear_object (&priv->iostream);
1166 
1167 	return gsock;
1168 }
1169 
1170 GIOStream *
soup_socket_get_connection(SoupSocket * sock)1171 soup_socket_get_connection (SoupSocket *sock)
1172 {
1173 	SoupSocketPrivate *priv;
1174 
1175 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1176 
1177 	priv = soup_socket_get_instance_private (sock);
1178 
1179 	return priv->conn;
1180 }
1181 
1182 GIOStream *
soup_socket_get_iostream(SoupSocket * sock)1183 soup_socket_get_iostream (SoupSocket *sock)
1184 {
1185 	SoupSocketPrivate *priv;
1186 
1187 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1188 
1189 	priv = soup_socket_get_instance_private (sock);
1190 
1191 	return priv->iostream;
1192 }
1193 
1194 static GSource *
soup_socket_create_watch(SoupSocketPrivate * priv,GIOCondition cond,GPollableSourceFunc callback,gpointer user_data,GCancellable * cancellable)1195 soup_socket_create_watch (SoupSocketPrivate *priv, GIOCondition cond,
1196 			  GPollableSourceFunc callback, gpointer user_data,
1197 			  GCancellable *cancellable)
1198 {
1199 	GSource *watch;
1200 
1201 	if (cond == G_IO_IN)
1202 		watch = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->istream), cancellable);
1203 	else
1204 		watch = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (priv->ostream), cancellable);
1205 	g_source_set_callback (watch, (GSourceFunc)callback, user_data, NULL);
1206 
1207 	g_source_attach (watch, priv->async_context);
1208 	g_source_unref (watch);
1209 
1210 	return watch;
1211 }
1212 
1213 static gboolean
listen_watch(GObject * pollable,gpointer data)1214 listen_watch (GObject *pollable, gpointer data)
1215 {
1216 	SoupSocket *sock = data, *new;
1217 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock), *new_priv;
1218 	GSocket *new_gsock;
1219 
1220 	new_gsock = g_socket_accept (priv->gsock, NULL, NULL);
1221 	if (!new_gsock)
1222 		return FALSE;
1223 
1224 	new = g_object_new (SOUP_TYPE_SOCKET, NULL);
1225 	new_priv = soup_socket_get_instance_private (new);
1226 	new_priv->gsock = new_gsock;
1227 	if (priv->async_context)
1228 		new_priv->async_context = g_main_context_ref (priv->async_context);
1229 	new_priv->use_thread_context = priv->use_thread_context;
1230 	new_priv->non_blocking = priv->non_blocking;
1231 	new_priv->clean_dispose = priv->clean_dispose;
1232 	new_priv->is_server = TRUE;
1233 	new_priv->ssl = priv->ssl;
1234 	if (priv->ssl_creds)
1235 		new_priv->ssl_creds = g_object_ref (priv->ssl_creds);
1236 	finish_socket_setup (new);
1237 
1238 	if (new_priv->ssl_creds) {
1239 		if (!soup_socket_start_proxy_ssl (new, NULL, NULL)) {
1240 			g_object_unref (new);
1241 			return TRUE;
1242 		}
1243 	}
1244 
1245 	g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
1246 	g_object_unref (new);
1247 
1248 	return TRUE;
1249 }
1250 
1251 static void
finish_listener_setup(SoupSocket * sock)1252 finish_listener_setup (SoupSocket *sock)
1253 {
1254 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1255 
1256 	priv->is_server = TRUE;
1257 	priv->watch_src = soup_socket_create_watch (priv, G_IO_IN,
1258 						    listen_watch, sock,
1259 						    NULL);
1260 }
1261 
1262 /**
1263  * soup_socket_listen:
1264  * @sock: a server #SoupSocket (which must not already be connected or
1265  * listening)
1266  *
1267  * Makes @sock start listening on its local address. When connections
1268  * come in, @sock will emit #SoupSocket::new_connection.
1269  *
1270  * Return value: whether or not @sock is now listening.
1271  **/
1272 gboolean
soup_socket_listen(SoupSocket * sock)1273 soup_socket_listen (SoupSocket *sock)
1274 {
1275 	return soup_socket_listen_full (sock, NULL);
1276 }
1277 
1278 /**
1279  * soup_socket_listen_full:
1280  * @sock: a server #SoupSocket (which must not already be connected or listening)
1281  * @error: error pointer
1282  *
1283  * Makes @sock start listening on its local address. When connections
1284  * come in, @sock will emit #SoupSocket::new_connection.
1285  *
1286  * Return value: whether or not @sock is now listening.
1287  **/
1288 gboolean
soup_socket_listen_full(SoupSocket * sock,GError ** error)1289 soup_socket_listen_full (SoupSocket *sock,
1290                          GError **error)
1291 
1292 {
1293 	SoupSocketPrivate *priv;
1294 	GSocketAddress *addr;
1295 
1296 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1297 	priv = soup_socket_get_instance_private (sock);
1298 	g_return_val_if_fail (priv->gsock == NULL, FALSE);
1299 	g_return_val_if_fail (priv->local_addr != NULL, FALSE);
1300 
1301 	/* @local_addr may have its port set to 0. So we intentionally
1302 	 * don't store it in priv->local_addr, so that if the
1303 	 * caller calls soup_socket_get_local_address() later, we'll
1304 	 * have to make a new addr by calling getsockname(), which
1305 	 * will have the right port number.
1306 	 */
1307 	addr = soup_address_get_gsockaddr (priv->local_addr);
1308 	g_return_val_if_fail (addr != NULL, FALSE);
1309 
1310 	priv->gsock = g_socket_new (g_socket_address_get_family (addr),
1311 				    G_SOCKET_TYPE_STREAM,
1312 				    G_SOCKET_PROTOCOL_DEFAULT,
1313 				    error);
1314 	if (!priv->gsock)
1315 		goto cant_listen;
1316 	finish_socket_setup (sock);
1317 
1318 #if defined (IPPROTO_IPV6) && defined (IPV6_V6ONLY)
1319 	if (priv->ipv6_only) {
1320 		int fd, v6_only;
1321 
1322 		fd = g_socket_get_fd (priv->gsock);
1323 		v6_only = TRUE;
1324 		setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY,
1325 			    &v6_only, sizeof (v6_only));
1326 	}
1327 #endif
1328 
1329 	/* Bind */
1330 	if (!g_socket_bind (priv->gsock, addr, TRUE, error))
1331 		goto cant_listen;
1332 	/* Force local_addr to be re-resolved now */
1333 	g_object_unref (priv->local_addr);
1334 	priv->local_addr = NULL;
1335 
1336 	/* Listen */
1337 	if (!g_socket_listen (priv->gsock, error))
1338 		goto cant_listen;
1339 	finish_listener_setup (sock);
1340 
1341 	g_object_unref (addr);
1342 	return TRUE;
1343 
1344  cant_listen:
1345 	if (priv->conn)
1346 		disconnect_internal (sock, TRUE);
1347 	g_object_unref (addr);
1348 
1349 	return FALSE;
1350 }
1351 
1352 static void
soup_socket_peer_certificate_changed(GObject * conn,GParamSpec * pspec,gpointer sock)1353 soup_socket_peer_certificate_changed (GObject *conn, GParamSpec *pspec,
1354 				      gpointer sock)
1355 {
1356 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1357 
1358 	priv->tls_errors = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (priv->conn));
1359 
1360 	g_object_notify (sock, "tls-certificate");
1361 	g_object_notify (sock, "tls-errors");
1362 }
1363 
1364 static gboolean
soup_socket_accept_certificate(GTlsConnection * conn,GTlsCertificate * cert,GTlsCertificateFlags errors,gpointer sock)1365 soup_socket_accept_certificate (GTlsConnection *conn, GTlsCertificate *cert,
1366 				GTlsCertificateFlags errors, gpointer sock)
1367 {
1368 	return TRUE;
1369 }
1370 
1371 static gboolean
soup_socket_setup_ssl(SoupSocket * sock,const char * ssl_host,GCancellable * cancellable,GError ** error)1372 soup_socket_setup_ssl (SoupSocket    *sock,
1373 		       const char    *ssl_host,
1374 		       GCancellable  *cancellable,
1375 		       GError       **error)
1376 {
1377 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1378 	GTlsBackend *backend = g_tls_backend_get_default ();
1379 
1380 	if (G_IS_TLS_CONNECTION (priv->conn))
1381 		return TRUE;
1382 
1383 	if (g_cancellable_set_error_if_cancelled (cancellable, error))
1384 		return FALSE;
1385 
1386 	priv->ssl = TRUE;
1387 
1388 	if (!priv->is_server) {
1389 		GTlsClientConnection *conn;
1390 		GSocketConnectable *identity;
1391 
1392 		identity = g_network_address_new (ssl_host, 0);
1393 		conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
1394 				       cancellable, error,
1395 				       "base-io-stream", priv->conn,
1396 				       "server-identity", identity,
1397 				       "database", priv->ssl_creds,
1398 				       "require-close-notify", FALSE,
1399 				       "use-ssl3", priv->ssl_fallback,
1400 				       NULL);
1401 		g_object_unref (identity);
1402 
1403 		if (!conn)
1404 			return FALSE;
1405 
1406 		/* GLib < 2.41 mistakenly doesn't implement this property in the
1407 		 * dummy TLS backend, so we don't include it in the g_initable_new()
1408 		 * call above.
1409 		 */
1410 		g_object_set (G_OBJECT (conn),
1411 			      "interaction", priv->tls_interaction,
1412 			      NULL);
1413 
1414 		g_object_unref (priv->conn);
1415 		priv->conn = G_IO_STREAM (conn);
1416 
1417 		if (!priv->ssl_strict) {
1418 			g_signal_connect (conn, "accept-certificate",
1419 					  G_CALLBACK (soup_socket_accept_certificate),
1420 					  sock);
1421 		}
1422 	} else {
1423 		GTlsServerConnection *conn;
1424 
1425 		conn = g_initable_new (g_tls_backend_get_server_connection_type (backend),
1426 				       cancellable, error,
1427 				       "base-io-stream", priv->conn,
1428 				       "certificate", priv->ssl_creds,
1429 				       "use-system-certdb", FALSE,
1430 				       "require-close-notify", FALSE,
1431 				       NULL);
1432 		if (!conn)
1433 			return FALSE;
1434 
1435 		g_object_unref (priv->conn);
1436 		priv->conn = G_IO_STREAM (conn);
1437 	}
1438 
1439 	g_signal_connect (priv->conn, "notify::peer-certificate",
1440 			  G_CALLBACK (soup_socket_peer_certificate_changed), sock);
1441 
1442 	g_clear_object (&priv->istream);
1443 	g_clear_object (&priv->ostream);
1444 	g_clear_object (&priv->iostream);
1445 	priv->iostream = soup_io_stream_new (priv->conn, FALSE);
1446 	priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
1447 	priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
1448 
1449 	return TRUE;
1450 }
1451 
1452 /**
1453  * soup_socket_start_ssl:
1454  * @sock: the socket
1455  * @cancellable: a #GCancellable
1456  *
1457  * Starts using SSL on @socket.
1458  *
1459  * Return value: success or failure
1460  **/
1461 gboolean
soup_socket_start_ssl(SoupSocket * sock,GCancellable * cancellable)1462 soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
1463 {
1464 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1465 
1466 	return soup_socket_setup_ssl (sock, soup_address_get_name (priv->remote_addr),
1467 				      cancellable, NULL);
1468 }
1469 
1470 /**
1471  * soup_socket_start_proxy_ssl:
1472  * @sock: the socket
1473  * @ssl_host: hostname of the SSL server
1474  * @cancellable: a #GCancellable
1475  *
1476  * Starts using SSL on @socket, expecting to find a host named
1477  * @ssl_host.
1478  *
1479  * Return value: success or failure
1480  **/
1481 gboolean
soup_socket_start_proxy_ssl(SoupSocket * sock,const char * ssl_host,GCancellable * cancellable)1482 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
1483 			     GCancellable *cancellable)
1484 {
1485 	return soup_socket_setup_ssl (sock, ssl_host, cancellable, NULL);
1486 }
1487 
1488 gboolean
soup_socket_handshake_sync(SoupSocket * sock,const char * ssl_host,GCancellable * cancellable,GError ** error)1489 soup_socket_handshake_sync (SoupSocket    *sock,
1490 			    const char    *ssl_host,
1491 			    GCancellable  *cancellable,
1492 			    GError       **error)
1493 {
1494 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1495 
1496 	if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, error))
1497 		return FALSE;
1498 
1499 	soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKING, priv->conn);
1500 
1501 	if (!g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn),
1502 					 cancellable, error))
1503 		return FALSE;
1504 
1505 	soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKED, priv->conn);
1506 	return TRUE;
1507 }
1508 
1509 static void
handshake_async_ready(GObject * source,GAsyncResult * result,gpointer user_data)1510 handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data)
1511 {
1512 	GTask *task = user_data;
1513 	GError *error = NULL;
1514 
1515 	if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (source),
1516 					       result, &error)) {
1517 		SoupSocket *sock = g_task_get_source_object (task);
1518 		SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1519 
1520 		soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKED, priv->conn);
1521 		g_task_return_boolean (task, TRUE);
1522 	} else
1523 		g_task_return_error (task, error);
1524 	g_object_unref (task);
1525 }
1526 
1527 void
soup_socket_handshake_async(SoupSocket * sock,const char * ssl_host,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1528 soup_socket_handshake_async (SoupSocket          *sock,
1529 			     const char          *ssl_host,
1530 			     GCancellable        *cancellable,
1531 			     GAsyncReadyCallback  callback,
1532 			     gpointer             user_data)
1533 {
1534 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1535 	GTask *task;
1536 	GError *error = NULL;
1537 
1538 	task = g_task_new (sock, cancellable, callback, user_data);
1539 
1540 	if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, &error)) {
1541 		g_task_return_error (task, error);
1542 		g_object_unref (task);
1543 		return;
1544 	}
1545 
1546 	soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKING, priv->conn);
1547 
1548 	g_tls_connection_handshake_async (G_TLS_CONNECTION (priv->conn),
1549 					  G_PRIORITY_DEFAULT,
1550 					  cancellable, handshake_async_ready,
1551 					  task);
1552 }
1553 
1554 gboolean
soup_socket_handshake_finish(SoupSocket * sock,GAsyncResult * result,GError ** error)1555 soup_socket_handshake_finish (SoupSocket    *sock,
1556 			      GAsyncResult  *result,
1557 			      GError       **error)
1558 {
1559 	return g_task_propagate_boolean (G_TASK (result), error);
1560 }
1561 
1562 /**
1563  * soup_socket_is_ssl:
1564  * @sock: a #SoupSocket
1565  *
1566  * Tests if @sock is doing (or has attempted to do) SSL.
1567  *
1568  * Return value: %TRUE if @sock has SSL credentials set
1569  **/
1570 gboolean
soup_socket_is_ssl(SoupSocket * sock)1571 soup_socket_is_ssl (SoupSocket *sock)
1572 {
1573 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1574 
1575 	return priv->ssl;
1576 }
1577 
1578 /**
1579  * soup_socket_disconnect:
1580  * @sock: a #SoupSocket
1581  *
1582  * Disconnects @sock. Any further read or write attempts on it will
1583  * fail.
1584  **/
1585 void
soup_socket_disconnect(SoupSocket * sock)1586 soup_socket_disconnect (SoupSocket *sock)
1587 {
1588 	SoupSocketPrivate *priv;
1589 	gboolean already_disconnected = FALSE;
1590 
1591 	g_return_if_fail (SOUP_IS_SOCKET (sock));
1592 	priv = soup_socket_get_instance_private (sock);
1593 
1594 	if (priv->connect_cancel) {
1595 		disconnect_internal (sock, FALSE);
1596 		g_cancellable_cancel (priv->connect_cancel);
1597 		return;
1598 	} else if (g_mutex_trylock (&priv->iolock)) {
1599 		if (priv->conn)
1600 			disconnect_internal (sock, TRUE);
1601 		else
1602 			already_disconnected = TRUE;
1603 		g_mutex_unlock (&priv->iolock);
1604 	} else {
1605 		/* Another thread is currently doing IO, so
1606 		 * we can't close the socket. So just shutdown
1607 		 * the file descriptor to force the I/O to fail.
1608 		 * (It will actually be closed when the socket
1609 		 * is destroyed.)
1610 		 */
1611 		g_socket_shutdown (priv->gsock, TRUE, TRUE, NULL);
1612 	}
1613 
1614 	if (already_disconnected)
1615 		return;
1616 
1617 	/* Keep ref around signals in case the object is unreferenced
1618 	 * in a handler
1619 	 */
1620 	g_object_ref (sock);
1621 
1622 	if (priv->non_blocking) {
1623 		/* Give all readers a chance to notice the connection close */
1624 		g_signal_emit (sock, signals[READABLE], 0);
1625 	}
1626 
1627 	/* FIXME: can't disconnect until all data is read */
1628 
1629 	/* Then let everyone know we're disconnected */
1630 	g_signal_emit (sock, signals[DISCONNECTED], 0);
1631 
1632 	g_object_unref (sock);
1633 }
1634 
1635 /**
1636  * soup_socket_is_connected:
1637  * @sock: a #SoupSocket
1638  *
1639  * Tests if @sock is connected to another host
1640  *
1641  * Return value: %TRUE or %FALSE.
1642  **/
1643 gboolean
soup_socket_is_connected(SoupSocket * sock)1644 soup_socket_is_connected (SoupSocket *sock)
1645 {
1646 	SoupSocketPrivate *priv;
1647 
1648 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1649 	priv = soup_socket_get_instance_private (sock);
1650 
1651 	return priv->conn && !g_io_stream_is_closed (priv->conn);
1652 }
1653 
1654 /**
1655  * soup_socket_get_local_address:
1656  * @sock: a #SoupSocket
1657  *
1658  * Returns the #SoupAddress corresponding to the local end of @sock.
1659  *
1660  * Calling this method on an unconnected socket is considered to be
1661  * an error, and produces undefined results.
1662  *
1663  * Return value: (transfer none): the #SoupAddress
1664  **/
1665 SoupAddress *
soup_socket_get_local_address(SoupSocket * sock)1666 soup_socket_get_local_address (SoupSocket *sock)
1667 {
1668 	SoupSocketPrivate *priv;
1669 
1670 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1671 	priv = soup_socket_get_instance_private (sock);
1672 
1673 	g_mutex_lock (&priv->addrlock);
1674 	if (!priv->local_addr) {
1675 		GSocketAddress *addr;
1676 		struct sockaddr_storage sa;
1677 		gssize sa_len;
1678 		GError *error = NULL;
1679 
1680 		if (priv->gsock == NULL) {
1681 			g_warning ("%s: socket not connected", G_STRLOC);
1682 			goto unlock;
1683 		}
1684 
1685 		addr = g_socket_get_local_address (priv->gsock, &error);
1686 		if (addr == NULL) {
1687 			g_warning ("%s: %s", G_STRLOC, error->message);
1688 			g_error_free (error);
1689 			goto unlock;
1690 		}
1691 		sa_len = g_socket_address_get_native_size (addr);
1692 		g_socket_address_to_native (addr, &sa, sa_len, NULL);
1693 		priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
1694 		g_object_unref (addr);
1695 	}
1696 unlock:
1697 	g_mutex_unlock (&priv->addrlock);
1698 
1699 	return priv->local_addr;
1700 }
1701 
1702 /**
1703  * soup_socket_get_remote_address:
1704  * @sock: a #SoupSocket
1705  *
1706  * Returns the #SoupAddress corresponding to the remote end of @sock.
1707  *
1708  * Calling this method on an unconnected socket is considered to be
1709  * an error, and produces undefined results.
1710  *
1711  * Return value: (transfer none): the #SoupAddress
1712  **/
1713 SoupAddress *
soup_socket_get_remote_address(SoupSocket * sock)1714 soup_socket_get_remote_address (SoupSocket *sock)
1715 {
1716 	SoupSocketPrivate *priv;
1717 
1718 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1719 	priv = soup_socket_get_instance_private (sock);
1720 
1721 	g_mutex_lock (&priv->addrlock);
1722 	if (!priv->remote_addr) {
1723 		GSocketAddress *addr;
1724 		struct sockaddr_storage sa;
1725 		gssize sa_len;
1726 		GError *error = NULL;
1727 
1728 		if (priv->gsock == NULL) {
1729 			g_warning ("%s: socket not connected", G_STRLOC);
1730 			goto unlock;
1731 		}
1732 
1733 		addr = g_socket_get_remote_address (priv->gsock, &error);
1734 		if (addr == NULL) {
1735 			g_warning ("%s: %s", G_STRLOC, error->message);
1736 			g_error_free (error);
1737 			goto unlock;
1738 		}
1739 		sa_len = g_socket_address_get_native_size (addr);
1740 		g_socket_address_to_native (addr, &sa, sa_len, NULL);
1741 		priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
1742 		g_object_unref (addr);
1743 	}
1744 unlock:
1745 	g_mutex_unlock (&priv->addrlock);
1746 
1747 	return priv->remote_addr;
1748 }
1749 
1750 SoupURI *
soup_socket_get_http_proxy_uri(SoupSocket * sock)1751 soup_socket_get_http_proxy_uri (SoupSocket *sock)
1752 {
1753 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1754 	GSocketAddress *addr;
1755 	GProxyAddress *paddr;
1756 	SoupURI *uri;
1757 
1758 	if (!priv->gsock)
1759 		return NULL;
1760 	addr = g_socket_get_remote_address (priv->gsock, NULL);
1761 	if (!addr || !G_IS_PROXY_ADDRESS (addr)) {
1762 		if (addr)
1763 			g_object_unref (addr);
1764 		return NULL;
1765 	}
1766 
1767 	paddr = G_PROXY_ADDRESS (addr);
1768 	if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0)
1769 		return NULL;
1770 
1771 	uri = soup_uri_new (g_proxy_address_get_uri (paddr));
1772 	g_object_unref (addr);
1773 	return uri;
1774 }
1775 
1776 static gboolean
socket_read_watch(GObject * pollable,gpointer user_data)1777 socket_read_watch (GObject *pollable, gpointer user_data)
1778 {
1779 	SoupSocket *sock = user_data;
1780 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1781 
1782 	priv->read_src = NULL;
1783 	g_signal_emit (sock, signals[READABLE], 0);
1784 	return FALSE;
1785 }
1786 
1787 static SoupSocketIOStatus
translate_read_status(SoupSocket * sock,GCancellable * cancellable,gssize my_nread,gsize * nread,GError * my_err,GError ** error)1788 translate_read_status (SoupSocket *sock, GCancellable *cancellable,
1789 		       gssize my_nread, gsize *nread,
1790 		       GError *my_err, GError **error)
1791 {
1792 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1793 
1794 	if (my_nread > 0) {
1795 		g_assert_no_error (my_err);
1796 		*nread = my_nread;
1797 		return SOUP_SOCKET_OK;
1798 	} else if (my_nread == 0) {
1799 		g_assert_no_error (my_err);
1800 		*nread = my_nread;
1801 		return SOUP_SOCKET_EOF;
1802 	} else if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
1803 		g_clear_error (&my_err);
1804 		if (!priv->read_src) {
1805 			priv->read_src =
1806 				soup_socket_create_watch (priv, G_IO_IN,
1807 							  socket_read_watch, sock,
1808 							  cancellable);
1809 		}
1810 		return SOUP_SOCKET_WOULD_BLOCK;
1811 	}
1812 
1813 	g_propagate_error (error, my_err);
1814 	return SOUP_SOCKET_ERROR;
1815 }
1816 
1817 /**
1818  * SoupSocketIOStatus:
1819  * @SOUP_SOCKET_OK: Success
1820  * @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time
1821  * @SOUP_SOCKET_EOF: End of file
1822  * @SOUP_SOCKET_ERROR: Other error
1823  *
1824  * Return value from the #SoupSocket IO methods.
1825  **/
1826 
1827 /**
1828  * soup_socket_read:
1829  * @sock: the socket
1830  * @buffer: (array length=len) (element-type guint8): buffer to read
1831  *   into
1832  * @len: size of @buffer in bytes
1833  * @nread: (out): on return, the number of bytes read into @buffer
1834  * @cancellable: a #GCancellable, or %NULL
1835  * @error: error pointer
1836  *
1837  * Attempts to read up to @len bytes from @sock into @buffer. If some
1838  * data is successfully read, soup_socket_read() will return
1839  * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
1840  * actually read (which may be less than @len).
1841  *
1842  * If @sock is non-blocking, and no data is available, the return
1843  * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
1844  * can connect to the #SoupSocket::readable signal to know when there
1845  * is more data to read. (NB: You MUST read all available data off the
1846  * socket first. #SoupSocket::readable is only emitted after
1847  * soup_socket_read() returns %SOUP_SOCKET_WOULD_BLOCK, and it is only
1848  * emitted once. See the documentation for #SoupSocket:non-blocking.)
1849  *
1850  * Return value: a #SoupSocketIOStatus, as described above (or
1851  * %SOUP_SOCKET_EOF if the socket is no longer connected, or
1852  * %SOUP_SOCKET_ERROR on any other error, in which case @error will
1853  * also be set).
1854  **/
1855 SoupSocketIOStatus
soup_socket_read(SoupSocket * sock,gpointer buffer,gsize len,gsize * nread,GCancellable * cancellable,GError ** error)1856 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
1857 		  gsize *nread, GCancellable *cancellable, GError **error)
1858 {
1859 	SoupSocketPrivate *priv;
1860 	SoupSocketIOStatus status;
1861 	gssize my_nread;
1862 	GError *my_err = NULL;
1863 
1864 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1865 	g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1866 
1867 	priv = soup_socket_get_instance_private (sock);
1868 
1869 	g_mutex_lock (&priv->iolock);
1870 
1871 	if (!priv->istream) {
1872 		status = SOUP_SOCKET_EOF;
1873 		goto out;
1874 	}
1875 
1876 	if (!priv->non_blocking) {
1877 		my_nread = g_input_stream_read (priv->istream, buffer, len,
1878 						cancellable, &my_err);
1879 	} else {
1880 		my_nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (priv->istream),
1881 								     buffer, len,
1882 								     cancellable, &my_err);
1883 	}
1884 	status = translate_read_status (sock, cancellable,
1885 					my_nread, nread, my_err, error);
1886 
1887 out:
1888 	g_mutex_unlock (&priv->iolock);
1889 
1890 	return status;
1891 }
1892 
1893 /**
1894  * soup_socket_read_until:
1895  * @sock: the socket
1896  * @buffer: (array length=len) (element-type guint8): buffer to read
1897  *   into
1898  * @len: size of @buffer in bytes
1899  * @boundary: boundary to read until
1900  * @boundary_len: length of @boundary in bytes
1901  * @nread: (out): on return, the number of bytes read into @buffer
1902  * @got_boundary: on return, whether or not the data in @buffer
1903  * ends with the boundary string
1904  * @cancellable: a #GCancellable, or %NULL
1905  * @error: error pointer
1906  *
1907  * Like soup_socket_read(), but reads no further than the first
1908  * occurrence of @boundary. (If the boundary is found, it will be
1909  * included in the returned data, and *@got_boundary will be set to
1910  * %TRUE.) Any data after the boundary will returned in future reads.
1911  *
1912  * soup_socket_read_until() will almost always return fewer than @len
1913  * bytes: if the boundary is found, then it will only return the bytes
1914  * up until the end of the boundary, and if the boundary is not found,
1915  * then it will leave the last <literal>(boundary_len - 1)</literal>
1916  * bytes in its internal buffer, in case they form the start of the
1917  * boundary string. Thus, @len normally needs to be at least 1 byte
1918  * longer than @boundary_len if you want to make any progress at all.
1919  *
1920  * Return value: as for soup_socket_read()
1921  **/
1922 SoupSocketIOStatus
soup_socket_read_until(SoupSocket * sock,gpointer buffer,gsize len,gconstpointer boundary,gsize boundary_len,gsize * nread,gboolean * got_boundary,GCancellable * cancellable,GError ** error)1923 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1924 			gconstpointer boundary, gsize boundary_len,
1925 			gsize *nread, gboolean *got_boundary,
1926 			GCancellable *cancellable, GError **error)
1927 {
1928 	SoupSocketPrivate *priv;
1929 	SoupSocketIOStatus status;
1930 	gssize my_nread;
1931 	GError *my_err = NULL;
1932 
1933 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1934 	g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1935 	g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1936 
1937 	priv = soup_socket_get_instance_private (sock);
1938 
1939 	g_mutex_lock (&priv->iolock);
1940 
1941 	*got_boundary = FALSE;
1942 
1943 	if (!priv->istream)
1944 		status = SOUP_SOCKET_EOF;
1945 	else {
1946 		my_nread = soup_filter_input_stream_read_until (
1947 			SOUP_FILTER_INPUT_STREAM (priv->istream),
1948 			buffer, len, boundary, boundary_len,
1949 			!priv->non_blocking,
1950 			TRUE, got_boundary, cancellable, &my_err);
1951 		status = translate_read_status (sock, cancellable,
1952 						my_nread, nread, my_err, error);
1953 	}
1954 
1955 	g_mutex_unlock (&priv->iolock);
1956 	return status;
1957 }
1958 
1959 static gboolean
socket_write_watch(GObject * pollable,gpointer user_data)1960 socket_write_watch (GObject *pollable, gpointer user_data)
1961 {
1962 	SoupSocket *sock = user_data;
1963 	SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
1964 
1965 	priv->write_src = NULL;
1966 	g_signal_emit (sock, signals[WRITABLE], 0);
1967 	return FALSE;
1968 }
1969 
1970 /**
1971  * soup_socket_write:
1972  * @sock: the socket
1973  * @buffer: (array length=len) (element-type guint8): data to write
1974  * @len: size of @buffer, in bytes
1975  * @nwrote: (out): on return, number of bytes written
1976  * @cancellable: a #GCancellable, or %NULL
1977  * @error: error pointer
1978  *
1979  * Attempts to write @len bytes from @buffer to @sock. If some data is
1980  * successfully written, the return status will be %SOUP_SOCKET_OK,
1981  * and *@nwrote will contain the number of bytes actually written
1982  * (which may be less than @len).
1983  *
1984  * If @sock is non-blocking, and no data could be written right away,
1985  * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1986  * the caller can connect to the #SoupSocket::writable signal to know
1987  * when more data can be written. (NB: #SoupSocket::writable is only
1988  * emitted after soup_socket_write() returns %SOUP_SOCKET_WOULD_BLOCK,
1989  * and it is only emitted once. See the documentation for
1990  * #SoupSocket:non-blocking.)
1991  *
1992  * Return value: a #SoupSocketIOStatus, as described above (or
1993  * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the
1994  * return value is %SOUP_SOCKET_ERROR.)
1995  **/
1996 SoupSocketIOStatus
soup_socket_write(SoupSocket * sock,gconstpointer buffer,gsize len,gsize * nwrote,GCancellable * cancellable,GError ** error)1997 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1998 		   gsize len, gsize *nwrote,
1999 		   GCancellable *cancellable, GError **error)
2000 {
2001 	SoupSocketPrivate *priv;
2002 	GError *my_err = NULL;
2003 	gssize my_nwrote;
2004 
2005 	g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
2006 	g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR);
2007 
2008 	priv = soup_socket_get_instance_private (sock);
2009 
2010 	g_mutex_lock (&priv->iolock);
2011 
2012 	if (!priv->conn) {
2013 		g_mutex_unlock (&priv->iolock);
2014 		return SOUP_SOCKET_EOF;
2015 	}
2016 	if (priv->write_src) {
2017 		g_mutex_unlock (&priv->iolock);
2018 		return SOUP_SOCKET_WOULD_BLOCK;
2019 	}
2020 
2021 	if (!priv->non_blocking) {
2022 		my_nwrote = g_output_stream_write (priv->ostream,
2023 						   buffer, len,
2024 						   cancellable, &my_err);
2025 	} else {
2026 		my_nwrote = g_pollable_output_stream_write_nonblocking (
2027 			G_POLLABLE_OUTPUT_STREAM (priv->ostream),
2028 			buffer, len, cancellable, &my_err);
2029 	}
2030 
2031 	if (my_nwrote > 0) {
2032 		g_mutex_unlock (&priv->iolock);
2033 		g_clear_error (&my_err);
2034 		*nwrote = my_nwrote;
2035 		return SOUP_SOCKET_OK;
2036 	}
2037 
2038 	if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
2039 		g_mutex_unlock (&priv->iolock);
2040 		g_clear_error (&my_err);
2041 
2042 		priv->write_src =
2043 			soup_socket_create_watch (priv,
2044 						  G_IO_OUT,
2045 						  socket_write_watch, sock, cancellable);
2046 		return SOUP_SOCKET_WOULD_BLOCK;
2047 	}
2048 
2049 	g_mutex_unlock (&priv->iolock);
2050 	g_propagate_error (error, my_err);
2051 	return SOUP_SOCKET_ERROR;
2052 }
2053