|
Packit Service |
ca3877 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
Packit Service |
ca3877 |
/*
|
|
Packit Service |
ca3877 |
* soup-socket.c: Socket networking code.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Copyright (C) 2000-2003, Ximian, Inc.
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
ca3877 |
#include <config.h>
|
|
Packit Service |
ca3877 |
#endif
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
#include <string.h>
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
#include <glib/gi18n-lib.h>
|
|
Packit Service |
ca3877 |
#include <gio/gnetworking.h>
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
#include "soup-socket.h"
|
|
Packit Service |
ca3877 |
#include "soup-socket-private.h"
|
|
Packit Service |
ca3877 |
#include "soup.h"
|
|
Packit Service |
ca3877 |
#include "soup-filter-input-stream.h"
|
|
Packit Service |
ca3877 |
#include "soup-io-stream.h"
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SECTION:soup-socket
|
|
Packit Service |
ca3877 |
* @short_description: A network socket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* #SoupSocket is libsoup's TCP socket type. While it is primarily
|
|
Packit Service |
ca3877 |
* intended for internal use, #SoupSockets are exposed in the
|
|
Packit Service |
ca3877 |
* API in various places, and some of their methods (eg,
|
|
Packit Service |
ca3877 |
* soup_socket_get_remote_address()) may be useful to applications.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
enum {
|
|
Packit Service |
ca3877 |
READABLE,
|
|
Packit Service |
ca3877 |
WRITABLE,
|
|
Packit Service |
ca3877 |
DISCONNECTED,
|
|
Packit Service |
ca3877 |
NEW_CONNECTION,
|
|
Packit Service |
ca3877 |
EVENT,
|
|
Packit Service |
ca3877 |
LAST_SIGNAL
|
|
Packit Service |
ca3877 |
};
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static guint signals[LAST_SIGNAL] = { 0 };
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
enum {
|
|
Packit Service |
ca3877 |
PROP_0,
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
PROP_FD,
|
|
Packit Service |
ca3877 |
PROP_GSOCKET,
|
|
Packit Service |
ca3877 |
PROP_IOSTREAM,
|
|
Packit Service |
ca3877 |
PROP_LOCAL_ADDRESS,
|
|
Packit Service |
ca3877 |
PROP_REMOTE_ADDRESS,
|
|
Packit Service |
ca3877 |
PROP_NON_BLOCKING,
|
|
Packit Service |
ca3877 |
PROP_IPV6_ONLY,
|
|
Packit Service |
ca3877 |
PROP_IS_SERVER,
|
|
Packit Service |
ca3877 |
PROP_SSL_CREDENTIALS,
|
|
Packit Service |
ca3877 |
PROP_SSL_STRICT,
|
|
Packit Service |
ca3877 |
PROP_SSL_FALLBACK,
|
|
Packit Service |
ca3877 |
PROP_ASYNC_CONTEXT,
|
|
Packit Service |
ca3877 |
PROP_USE_THREAD_CONTEXT,
|
|
Packit Service |
ca3877 |
PROP_TIMEOUT,
|
|
Packit Service |
ca3877 |
PROP_TRUSTED_CERTIFICATE,
|
|
Packit Service |
ca3877 |
PROP_TLS_CERTIFICATE,
|
|
Packit Service |
ca3877 |
PROP_TLS_ERRORS,
|
|
Packit Service |
ca3877 |
PROP_SOCKET_PROPERTIES,
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
LAST_PROP
|
|
Packit Service |
ca3877 |
};
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
typedef struct {
|
|
Packit Service |
ca3877 |
SoupAddress *local_addr, *remote_addr;
|
|
Packit Service |
ca3877 |
GIOStream *conn, *iostream;
|
|
Packit Service |
ca3877 |
GSocket *gsock;
|
|
Packit Service |
ca3877 |
GInputStream *istream;
|
|
Packit Service |
ca3877 |
GOutputStream *ostream;
|
|
Packit Service |
ca3877 |
GTlsCertificateFlags tls_errors;
|
|
Packit Service |
ca3877 |
GTlsInteraction *tls_interaction;
|
|
Packit Service |
ca3877 |
GProxyResolver *proxy_resolver;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
guint non_blocking:1;
|
|
Packit Service |
ca3877 |
guint ipv6_only:1;
|
|
Packit Service |
ca3877 |
guint is_server:1;
|
|
Packit Service |
ca3877 |
guint ssl:1;
|
|
Packit Service |
ca3877 |
guint ssl_strict:1;
|
|
Packit Service |
ca3877 |
guint ssl_fallback:1;
|
|
Packit Service |
ca3877 |
guint clean_dispose:1;
|
|
Packit Service |
ca3877 |
guint use_thread_context:1;
|
|
Packit Service |
ca3877 |
gpointer ssl_creds;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
GMainContext *async_context;
|
|
Packit Service |
ca3877 |
GSource *watch_src;
|
|
Packit Service |
ca3877 |
GSource *read_src, *write_src;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
GMutex iolock, addrlock;
|
|
Packit Service |
ca3877 |
guint timeout;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
GCancellable *connect_cancel;
|
|
Packit Service |
ca3877 |
int fd;
|
|
Packit Service |
ca3877 |
} SoupSocketPrivate;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void soup_socket_initable_interface_init (GInitableIface *initable_interface);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
G_DEFINE_TYPE_WITH_CODE (SoupSocket, soup_socket, G_TYPE_OBJECT,
|
|
Packit Service |
ca3877 |
G_ADD_PRIVATE (SoupSocket)
|
|
Packit Service |
ca3877 |
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
|
Packit Service |
ca3877 |
soup_socket_initable_interface_init))
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void soup_socket_peer_certificate_changed (GObject *conn,
|
|
Packit Service |
ca3877 |
GParamSpec *pspec,
|
|
Packit Service |
ca3877 |
gpointer user_data);
|
|
Packit Service |
ca3877 |
static void finish_socket_setup (SoupSocket *sock);
|
|
Packit Service |
ca3877 |
static void finish_listener_setup (SoupSocket *sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_init (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->non_blocking = TRUE;
|
|
Packit Service |
ca3877 |
priv->fd = -1;
|
|
Packit Service |
ca3877 |
g_mutex_init (&priv->addrlock);
|
|
Packit Service |
ca3877 |
g_mutex_init (&priv->iolock);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static gboolean
|
|
Packit Service |
ca3877 |
soup_socket_initable_init (GInitable *initable,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = SOUP_SOCKET (initable);
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->conn) {
|
|
Packit Service |
ca3877 |
g_warn_if_fail (priv->gsock == NULL);
|
|
Packit Service |
ca3877 |
g_warn_if_fail (priv->fd == -1);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
finish_socket_setup (sock);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->fd != -1) {
|
|
Packit Service |
ca3877 |
guint type, len = sizeof (type);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_warn_if_fail (priv->gsock == NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* GSocket will g_error() this, so we have to check ourselves. */
|
|
Packit Service |
ca3877 |
if (getsockopt (priv->fd, SOL_SOCKET, SO_TYPE,
|
|
Packit Service |
ca3877 |
(gpointer)&type, (gpointer)&len) == -1) {
|
|
Packit Service |
ca3877 |
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
Packit Service |
ca3877 |
_("Can’t import non-socket as SoupSocket"));
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->gsock = g_socket_new_from_fd (priv->fd, error);
|
|
Packit Service |
ca3877 |
if (!priv->gsock)
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->gsock != NULL) {
|
|
Packit Service |
ca3877 |
int listening;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_warn_if_fail (priv->local_addr == NULL);
|
|
Packit Service |
ca3877 |
g_warn_if_fail (priv->remote_addr == NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!g_socket_get_option (priv->gsock,
|
|
Packit Service |
ca3877 |
SOL_SOCKET, SO_ACCEPTCONN,
|
|
Packit Service |
ca3877 |
&listening, error)) {
|
|
Packit Service |
ca3877 |
g_prefix_error (error, _("Could not import existing socket: "));
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
finish_socket_setup (sock);
|
|
Packit Service |
ca3877 |
if (listening)
|
|
Packit Service |
ca3877 |
finish_listener_setup (sock);
|
|
Packit Service |
ca3877 |
else if (!g_socket_is_connected (priv->gsock)) {
|
|
Packit Service |
ca3877 |
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
Packit Service |
ca3877 |
_("Can’t import unconnected socket"));
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
disconnect_internal (SoupSocket *sock, gboolean close)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->gsock);
|
|
Packit Service |
ca3877 |
if (priv->conn && close) {
|
|
Packit Service |
ca3877 |
g_io_stream_close (priv->conn, NULL, NULL);
|
|
Packit Service |
ca3877 |
g_signal_handlers_disconnect_by_data (priv->conn, sock);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->conn);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->read_src) {
|
|
Packit Service |
ca3877 |
g_source_destroy (priv->read_src);
|
|
Packit Service |
ca3877 |
priv->read_src = NULL;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
if (priv->write_src) {
|
|
Packit Service |
ca3877 |
g_source_destroy (priv->write_src);
|
|
Packit Service |
ca3877 |
priv->write_src = NULL;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_finalize (GObject *object)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = SOUP_SOCKET (object);
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->connect_cancel) {
|
|
Packit Service |
ca3877 |
if (priv->clean_dispose)
|
|
Packit Service |
ca3877 |
g_warning ("Disposing socket %p during connect", object);
|
|
Packit Service |
ca3877 |
g_object_unref (priv->connect_cancel);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
if (priv->conn) {
|
|
Packit Service |
ca3877 |
if (priv->clean_dispose)
|
|
Packit Service |
ca3877 |
g_warning ("Disposing socket %p while still connected", object);
|
|
Packit Service |
ca3877 |
disconnect_internal (SOUP_SOCKET (object), TRUE);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->conn);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->iostream);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->istream);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->ostream);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->local_addr);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->remote_addr);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->tls_interaction);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->proxy_resolver);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->ssl_creds);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->watch_src) {
|
|
Packit Service |
ca3877 |
if (priv->clean_dispose && !priv->is_server)
|
|
Packit Service |
ca3877 |
g_warning ("Disposing socket %p during async op", object);
|
|
Packit Service |
ca3877 |
g_source_destroy (priv->watch_src);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
g_clear_pointer (&priv->async_context, g_main_context_unref);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_clear (&priv->addrlock);
|
|
Packit Service |
ca3877 |
g_mutex_clear (&priv->iolock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
finish_socket_setup (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->gsock) {
|
|
Packit Service |
ca3877 |
if (!priv->conn)
|
|
Packit Service |
ca3877 |
priv->conn = (GIOStream *)g_socket_connection_factory_create_connection (priv->gsock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_socket_set_timeout (priv->gsock, priv->timeout);
|
|
Packit Service |
ca3877 |
g_socket_set_option (priv->gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->conn)
|
|
Packit Service |
ca3877 |
return;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->iostream)
|
|
Packit Service |
ca3877 |
priv->iostream = soup_io_stream_new (priv->conn, FALSE);
|
|
Packit Service |
ca3877 |
if (!priv->istream)
|
|
Packit Service |
ca3877 |
priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
|
|
Packit Service |
ca3877 |
if (!priv->ostream)
|
|
Packit Service |
ca3877 |
priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_set_property (GObject *object, guint prop_id,
|
|
Packit Service |
ca3877 |
const GValue *value, GParamSpec *pspec)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = SOUP_SOCKET (object);
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
SoupSocketProperties *props;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
switch (prop_id) {
|
|
Packit Service |
ca3877 |
case PROP_FD:
|
|
Packit Service |
ca3877 |
priv->fd = g_value_get_int (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_GSOCKET:
|
|
Packit Service |
ca3877 |
priv->gsock = g_value_dup_object (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_IOSTREAM:
|
|
Packit Service |
ca3877 |
priv->conn = g_value_dup_object (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_LOCAL_ADDRESS:
|
|
Packit Service |
ca3877 |
priv->local_addr = g_value_dup_object (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_REMOTE_ADDRESS:
|
|
Packit Service |
ca3877 |
priv->remote_addr = g_value_dup_object (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_NON_BLOCKING:
|
|
Packit Service |
ca3877 |
priv->non_blocking = g_value_get_boolean (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_IPV6_ONLY:
|
|
Packit Service |
ca3877 |
priv->ipv6_only = g_value_get_boolean (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_SSL_CREDENTIALS:
|
|
Packit Service |
ca3877 |
priv->ssl_creds = g_value_get_pointer (value);
|
|
Packit Service |
ca3877 |
if (priv->ssl_creds)
|
|
Packit Service |
ca3877 |
g_object_ref (priv->ssl_creds);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_SSL_STRICT:
|
|
Packit Service |
ca3877 |
priv->ssl_strict = g_value_get_boolean (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_SSL_FALLBACK:
|
|
Packit Service |
ca3877 |
priv->ssl_fallback = g_value_get_boolean (value);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_ASYNC_CONTEXT:
|
|
Packit Service |
ca3877 |
if (!priv->use_thread_context) {
|
|
Packit Service |
ca3877 |
priv->async_context = g_value_get_pointer (value);
|
|
Packit Service |
ca3877 |
if (priv->async_context)
|
|
Packit Service |
ca3877 |
g_main_context_ref (priv->async_context);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_USE_THREAD_CONTEXT:
|
|
Packit Service |
ca3877 |
priv->use_thread_context = g_value_get_boolean (value);
|
|
Packit Service |
ca3877 |
if (priv->use_thread_context) {
|
|
Packit Service |
ca3877 |
g_clear_pointer (&priv->async_context, g_main_context_unref);
|
|
Packit Service |
ca3877 |
priv->async_context = g_main_context_ref_thread_default ();
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_TIMEOUT:
|
|
Packit Service |
ca3877 |
priv->timeout = g_value_get_uint (value);
|
|
Packit Service |
ca3877 |
if (priv->conn)
|
|
Packit Service |
ca3877 |
g_socket_set_timeout (priv->gsock, priv->timeout);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_SOCKET_PROPERTIES:
|
|
Packit Service |
ca3877 |
props = g_value_get_boxed (value);
|
|
Packit Service |
ca3877 |
if (props) {
|
|
Packit Service |
ca3877 |
g_clear_pointer (&priv->async_context, g_main_context_unref);
|
|
Packit Service |
ca3877 |
if (props->use_thread_context) {
|
|
Packit Service |
ca3877 |
priv->use_thread_context = TRUE;
|
|
Packit Service |
ca3877 |
priv->async_context = g_main_context_ref_thread_default ();
|
|
Packit Service |
ca3877 |
} else {
|
|
Packit Service |
ca3877 |
priv->use_thread_context = FALSE;
|
|
Packit Service |
ca3877 |
if (props->async_context)
|
|
Packit Service |
ca3877 |
priv->async_context = g_main_context_ref (props->async_context);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->proxy_resolver);
|
|
Packit Service |
ca3877 |
if (props->proxy_resolver)
|
|
Packit Service |
ca3877 |
priv->proxy_resolver = g_object_ref (props->proxy_resolver);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->local_addr);
|
|
Packit Service |
ca3877 |
if (props->local_addr)
|
|
Packit Service |
ca3877 |
priv->local_addr = g_object_ref (props->local_addr);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->ssl_creds);
|
|
Packit Service |
ca3877 |
if (props->tlsdb)
|
|
Packit Service |
ca3877 |
priv->ssl_creds = g_object_ref (props->tlsdb);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->tls_interaction);
|
|
Packit Service |
ca3877 |
if (props->tls_interaction)
|
|
Packit Service |
ca3877 |
priv->tls_interaction = g_object_ref (props->tls_interaction);
|
|
Packit Service |
ca3877 |
priv->ssl_strict = props->ssl_strict;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->timeout = props->io_timeout;
|
|
Packit Service |
ca3877 |
if (priv->conn)
|
|
Packit Service |
ca3877 |
g_socket_set_timeout (priv->gsock, priv->timeout);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->clean_dispose = TRUE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
default:
|
|
Packit Service |
ca3877 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_get_property (GObject *object, guint prop_id,
|
|
Packit Service |
ca3877 |
GValue *value, GParamSpec *pspec)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = SOUP_SOCKET (object);
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
switch (prop_id) {
|
|
Packit Service |
ca3877 |
case PROP_FD:
|
|
Packit Service |
ca3877 |
g_value_set_int (value, priv->fd);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_LOCAL_ADDRESS:
|
|
Packit Service |
ca3877 |
g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_REMOTE_ADDRESS:
|
|
Packit Service |
ca3877 |
g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_NON_BLOCKING:
|
|
Packit Service |
ca3877 |
g_value_set_boolean (value, priv->non_blocking);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_IPV6_ONLY:
|
|
Packit Service |
ca3877 |
g_value_set_boolean (value, priv->ipv6_only);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_IS_SERVER:
|
|
Packit Service |
ca3877 |
g_value_set_boolean (value, priv->is_server);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_SSL_CREDENTIALS:
|
|
Packit Service |
ca3877 |
g_value_set_pointer (value, priv->ssl_creds);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_SSL_STRICT:
|
|
Packit Service |
ca3877 |
g_value_set_boolean (value, priv->ssl_strict);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_SSL_FALLBACK:
|
|
Packit Service |
ca3877 |
g_value_set_boolean (value, priv->ssl_fallback);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_TRUSTED_CERTIFICATE:
|
|
Packit Service |
ca3877 |
g_value_set_boolean (value, priv->tls_errors == 0);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_ASYNC_CONTEXT:
|
|
Packit Service |
ca3877 |
g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_USE_THREAD_CONTEXT:
|
|
Packit Service |
ca3877 |
g_value_set_boolean (value, priv->use_thread_context);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_TIMEOUT:
|
|
Packit Service |
ca3877 |
g_value_set_uint (value, priv->timeout);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_TLS_CERTIFICATE:
|
|
Packit Service |
ca3877 |
if (G_IS_TLS_CONNECTION (priv->conn))
|
|
Packit Service |
ca3877 |
g_value_set_object (value, g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (priv->conn)));
|
|
Packit Service |
ca3877 |
else
|
|
Packit Service |
ca3877 |
g_value_set_object (value, NULL);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
case PROP_TLS_ERRORS:
|
|
Packit Service |
ca3877 |
g_value_set_flags (value, priv->tls_errors);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
default:
|
|
Packit Service |
ca3877 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit Service |
ca3877 |
break;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_class_init (SoupSocketClass *socket_class)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* virtual method override */
|
|
Packit Service |
ca3877 |
object_class->finalize = soup_socket_finalize;
|
|
Packit Service |
ca3877 |
object_class->set_property = soup_socket_set_property;
|
|
Packit Service |
ca3877 |
object_class->get_property = soup_socket_get_property;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* signals */
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket::readable:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Emitted when an async socket is readable. See
|
|
Packit Service |
ca3877 |
* soup_socket_read(), soup_socket_read_until() and
|
|
Packit Service |
ca3877 |
* #SoupSocket:non-blocking.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
signals[READABLE] =
|
|
Packit Service |
ca3877 |
g_signal_new ("readable",
|
|
Packit Service |
ca3877 |
G_OBJECT_CLASS_TYPE (object_class),
|
|
Packit Service |
ca3877 |
G_SIGNAL_RUN_LAST,
|
|
Packit Service |
ca3877 |
G_STRUCT_OFFSET (SoupSocketClass, readable),
|
|
Packit Service |
ca3877 |
NULL, NULL,
|
|
Packit Service |
ca3877 |
NULL,
|
|
Packit Service |
ca3877 |
G_TYPE_NONE, 0);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket::writable:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Emitted when an async socket is writable. See
|
|
Packit Service |
ca3877 |
* soup_socket_write() and #SoupSocket:non-blocking.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
signals[WRITABLE] =
|
|
Packit Service |
ca3877 |
g_signal_new ("writable",
|
|
Packit Service |
ca3877 |
G_OBJECT_CLASS_TYPE (object_class),
|
|
Packit Service |
ca3877 |
G_SIGNAL_RUN_LAST,
|
|
Packit Service |
ca3877 |
G_STRUCT_OFFSET (SoupSocketClass, writable),
|
|
Packit Service |
ca3877 |
NULL, NULL,
|
|
Packit Service |
ca3877 |
NULL,
|
|
Packit Service |
ca3877 |
G_TYPE_NONE, 0);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket::disconnected:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Emitted when the socket is disconnected, for whatever
|
|
Packit Service |
ca3877 |
* reason.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
signals[DISCONNECTED] =
|
|
Packit Service |
ca3877 |
g_signal_new ("disconnected",
|
|
Packit Service |
ca3877 |
G_OBJECT_CLASS_TYPE (object_class),
|
|
Packit Service |
ca3877 |
G_SIGNAL_RUN_LAST,
|
|
Packit Service |
ca3877 |
G_STRUCT_OFFSET (SoupSocketClass, disconnected),
|
|
Packit Service |
ca3877 |
NULL, NULL,
|
|
Packit Service |
ca3877 |
NULL,
|
|
Packit Service |
ca3877 |
G_TYPE_NONE, 0);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket::new-connection:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
* @new: the new socket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Emitted when a listening socket (set up with
|
|
Packit Service |
ca3877 |
* soup_socket_listen()) receives a new connection.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* You must ref the @new if you want to keep it; otherwise it
|
|
Packit Service |
ca3877 |
* will be destroyed after the signal is emitted.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
signals[NEW_CONNECTION] =
|
|
Packit Service |
ca3877 |
g_signal_new ("new_connection",
|
|
Packit Service |
ca3877 |
G_OBJECT_CLASS_TYPE (object_class),
|
|
Packit Service |
ca3877 |
G_SIGNAL_RUN_FIRST,
|
|
Packit Service |
ca3877 |
G_STRUCT_OFFSET (SoupSocketClass, new_connection),
|
|
Packit Service |
ca3877 |
NULL, NULL,
|
|
Packit Service |
ca3877 |
NULL,
|
|
Packit Service |
ca3877 |
G_TYPE_NONE, 1,
|
|
Packit Service |
ca3877 |
SOUP_TYPE_SOCKET);
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket::event:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
* @event: the event that occurred
|
|
Packit Service |
ca3877 |
* @connection: the current connection state
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Emitted when a network-related event occurs. See
|
|
Packit Service |
ca3877 |
* #GSocketClient::event for more details.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Since: 2.38
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
signals[EVENT] =
|
|
Packit Service |
ca3877 |
g_signal_new ("event",
|
|
Packit Service |
ca3877 |
G_OBJECT_CLASS_TYPE (object_class),
|
|
Packit Service |
ca3877 |
G_SIGNAL_RUN_LAST,
|
|
Packit Service |
ca3877 |
0,
|
|
Packit Service |
ca3877 |
NULL, NULL,
|
|
Packit Service |
ca3877 |
NULL,
|
|
Packit Service |
ca3877 |
G_TYPE_NONE, 2,
|
|
Packit Service |
ca3877 |
G_TYPE_SOCKET_CLIENT_EVENT,
|
|
Packit Service |
ca3877 |
G_TYPE_IO_STREAM);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* properties */
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_FD,
|
|
Packit Service |
ca3877 |
g_param_spec_int (SOUP_SOCKET_FD,
|
|
Packit Service |
ca3877 |
"FD",
|
|
Packit Service |
ca3877 |
"The socket's file descriptor",
|
|
Packit Service |
ca3877 |
-1, G_MAXINT, -1,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_GSOCKET,
|
|
Packit Service |
ca3877 |
g_param_spec_object (SOUP_SOCKET_GSOCKET,
|
|
Packit Service |
ca3877 |
"GSocket",
|
|
Packit Service |
ca3877 |
"The socket's underlying GSocket",
|
|
Packit Service |
ca3877 |
G_TYPE_SOCKET,
|
|
Packit Service |
ca3877 |
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_IOSTREAM,
|
|
Packit Service |
ca3877 |
g_param_spec_object (SOUP_SOCKET_IOSTREAM,
|
|
Packit Service |
ca3877 |
"GIOStream",
|
|
Packit Service |
ca3877 |
"The socket's underlying GIOStream",
|
|
Packit Service |
ca3877 |
G_TYPE_IO_STREAM,
|
|
Packit Service |
ca3877 |
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_LOCAL_ADDRESS:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:local-address property. (Address
|
|
Packit Service |
ca3877 |
* of local end of socket.)
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_LOCAL_ADDRESS,
|
|
Packit Service |
ca3877 |
g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
|
|
Packit Service |
ca3877 |
"Local address",
|
|
Packit Service |
ca3877 |
"Address of local end of socket",
|
|
Packit Service |
ca3877 |
SOUP_TYPE_ADDRESS,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_REMOTE_ADDRESS:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:remote-address property. (Address
|
|
Packit Service |
ca3877 |
* of remote end of socket.)
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_REMOTE_ADDRESS,
|
|
Packit Service |
ca3877 |
g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
|
|
Packit Service |
ca3877 |
"Remote address",
|
|
Packit Service |
ca3877 |
"Address of remote end of socket",
|
|
Packit Service |
ca3877 |
SOUP_TYPE_ADDRESS,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket:non-blocking:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Whether or not the socket uses non-blocking I/O.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* #SoupSocket's I/O methods are designed around the idea of
|
|
Packit Service |
ca3877 |
* using a single codepath for both synchronous and
|
|
Packit Service |
ca3877 |
* asynchronous I/O. If you want to read off a #SoupSocket,
|
|
Packit Service |
ca3877 |
* the "correct" way to do it is to call soup_socket_read() or
|
|
Packit Service |
ca3877 |
* soup_socket_read_until() repeatedly until you have read
|
|
Packit Service |
ca3877 |
* everything you want. If it returns %SOUP_SOCKET_WOULD_BLOCK
|
|
Packit Service |
ca3877 |
* at any point, stop reading and wait for it to emit the
|
|
Packit Service |
ca3877 |
* #SoupSocket::readable signal. Then go back to the
|
|
Packit Service |
ca3877 |
* reading-as-much-as-you-can loop. Likewise, for writing to a
|
|
Packit Service |
ca3877 |
* #SoupSocket, you should call soup_socket_write() either
|
|
Packit Service |
ca3877 |
* until you have written everything, or it returns
|
|
Packit Service |
ca3877 |
* %SOUP_SOCKET_WOULD_BLOCK (in which case you wait for
|
|
Packit Service |
ca3877 |
* #SoupSocket::writable and then go back into the loop).
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Code written this way will work correctly with both
|
|
Packit Service |
ca3877 |
* blocking and non-blocking sockets; blocking sockets will
|
|
Packit Service |
ca3877 |
* simply never return %SOUP_SOCKET_WOULD_BLOCK, and so the
|
|
Packit Service |
ca3877 |
* code that handles that case just won't get used for them.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_FLAG_NONBLOCKING:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:non-blocking property. (Whether
|
|
Packit Service |
ca3877 |
* or not the socket uses non-blocking I/O.)
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_NON_BLOCKING,
|
|
Packit Service |
ca3877 |
g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
|
|
Packit Service |
ca3877 |
"Non-blocking",
|
|
Packit Service |
ca3877 |
"Whether or not the socket uses non-blocking I/O",
|
|
Packit Service |
ca3877 |
TRUE,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE));
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_IPV6_ONLY,
|
|
Packit Service |
ca3877 |
g_param_spec_boolean (SOUP_SOCKET_IPV6_ONLY,
|
|
Packit Service |
ca3877 |
"IPv6 only",
|
|
Packit Service |
ca3877 |
"IPv6 only",
|
|
Packit Service |
ca3877 |
FALSE,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_IS_SERVER:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:is-server property, qv.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket:is-server:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Whether or not the socket is a server socket.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Note that for "ordinary" #SoupSockets this will be set for
|
|
Packit Service |
ca3877 |
* both listening sockets and the sockets emitted by
|
|
Packit Service |
ca3877 |
* #SoupSocket::new-connection, but for sockets created by
|
|
Packit Service |
ca3877 |
* setting #SoupSocket:fd, it will only be set for listening
|
|
Packit Service |
ca3877 |
* sockets.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_IS_SERVER,
|
|
Packit Service |
ca3877 |
g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
|
|
Packit Service |
ca3877 |
"Server",
|
|
Packit Service |
ca3877 |
"Whether or not the socket is a server socket",
|
|
Packit Service |
ca3877 |
FALSE,
|
|
Packit Service |
ca3877 |
G_PARAM_READABLE));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_SSL_CREDENTIALS:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:ssl-creds property.
|
|
Packit Service |
ca3877 |
* (SSL credential information.)
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
/* For historical reasons, there's only a single property
|
|
Packit Service |
ca3877 |
* here, which is a GTlsDatabase for client sockets, and
|
|
Packit Service |
ca3877 |
* a GTlsCertificate for server sockets. Whee!
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_SSL_CREDENTIALS,
|
|
Packit Service |
ca3877 |
g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
|
|
Packit Service |
ca3877 |
"SSL credentials",
|
|
Packit Service |
ca3877 |
"SSL credential information, passed from the session to the SSL implementation",
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_SSL_STRICT:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:ssl-strict property.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_SSL_STRICT,
|
|
Packit Service |
ca3877 |
g_param_spec_boolean (SOUP_SOCKET_SSL_STRICT,
|
|
Packit Service |
ca3877 |
"Strictly validate SSL certificates",
|
|
Packit Service |
ca3877 |
"Whether certificate errors should be considered a connection error",
|
|
Packit Service |
ca3877 |
TRUE,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_SSL_FALLBACK:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:ssl-fallback property.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_SSL_FALLBACK,
|
|
Packit Service |
ca3877 |
g_param_spec_boolean (SOUP_SOCKET_SSL_FALLBACK,
|
|
Packit Service |
ca3877 |
"SSLv3 fallback",
|
|
Packit Service |
ca3877 |
"Use SSLv3 instead of TLS (client-side only)",
|
|
Packit Service |
ca3877 |
FALSE,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_TRUSTED_CERTIFICATE:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:trusted-certificate
|
|
Packit Service |
ca3877 |
* property.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_TRUSTED_CERTIFICATE,
|
|
Packit Service |
ca3877 |
g_param_spec_boolean (SOUP_SOCKET_TRUSTED_CERTIFICATE,
|
|
Packit Service |
ca3877 |
"Trusted Certificate",
|
|
Packit Service |
ca3877 |
"Whether the server certificate is trusted, if this is an SSL socket",
|
|
Packit Service |
ca3877 |
FALSE,
|
|
Packit Service |
ca3877 |
G_PARAM_READABLE));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_ASYNC_CONTEXT:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:async-context property. (The
|
|
Packit Service |
ca3877 |
* socket's #GMainContext.)
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_ASYNC_CONTEXT,
|
|
Packit Service |
ca3877 |
g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
|
|
Packit Service |
ca3877 |
"Async GMainContext",
|
|
Packit Service |
ca3877 |
"The GMainContext to dispatch this socket's async I/O in",
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_USE_THREAD_CONTEXT:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:use-thread-context property. (Use
|
|
Packit Service |
ca3877 |
* g_main_context_get_thread_default())
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Since: 2.38
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocket:use-thread-context:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Use g_main_context_get_thread_default().
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Since: 2.38
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_USE_THREAD_CONTEXT,
|
|
Packit Service |
ca3877 |
g_param_spec_boolean (SOUP_SOCKET_USE_THREAD_CONTEXT,
|
|
Packit Service |
ca3877 |
"Use thread context",
|
|
Packit Service |
ca3877 |
"Use g_main_context_get_thread_default",
|
|
Packit Service |
ca3877 |
FALSE,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_TIMEOUT:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:timeout property. (The timeout
|
|
Packit Service |
ca3877 |
* in seconds for blocking socket I/O operations.)
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_TIMEOUT,
|
|
Packit Service |
ca3877 |
g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
|
|
Packit Service |
ca3877 |
"Timeout value",
|
|
Packit Service |
ca3877 |
"Value in seconds to timeout a blocking I/O",
|
|
Packit Service |
ca3877 |
0, G_MAXUINT, 0,
|
|
Packit Service |
ca3877 |
G_PARAM_READWRITE));
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_TLS_CERTIFICATE:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:tls-certificate
|
|
Packit Service |
ca3877 |
* property. Note that this property's value is only useful
|
|
Packit Service |
ca3877 |
* if the socket is for a TLS connection, and only reliable
|
|
Packit Service |
ca3877 |
* after some data has been transferred to or from it.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Since: 2.34
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_TLS_CERTIFICATE,
|
|
Packit Service |
ca3877 |
g_param_spec_object (SOUP_SOCKET_TLS_CERTIFICATE,
|
|
Packit Service |
ca3877 |
"TLS certificate",
|
|
Packit Service |
ca3877 |
"The peer's TLS certificate",
|
|
Packit Service |
ca3877 |
G_TYPE_TLS_CERTIFICATE,
|
|
Packit Service |
ca3877 |
G_PARAM_READABLE));
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SOUP_SOCKET_TLS_ERRORS:
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Alias for the #SoupSocket:tls-errors
|
|
Packit Service |
ca3877 |
* property. Note that this property's value is only useful
|
|
Packit Service |
ca3877 |
* if the socket is for a TLS connection, and only reliable
|
|
Packit Service |
ca3877 |
* after some data has been transferred to or from it.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Since: 2.34
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_TLS_ERRORS,
|
|
Packit Service |
ca3877 |
g_param_spec_flags (SOUP_SOCKET_TLS_ERRORS,
|
|
Packit Service |
ca3877 |
"TLS errors",
|
|
Packit Service |
ca3877 |
"Errors with the peer's TLS certificate",
|
|
Packit Service |
ca3877 |
G_TYPE_TLS_CERTIFICATE_FLAGS, 0,
|
|
Packit Service |
ca3877 |
G_PARAM_READABLE));
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_object_class_install_property (
|
|
Packit Service |
ca3877 |
object_class, PROP_SOCKET_PROPERTIES,
|
|
Packit Service |
ca3877 |
g_param_spec_boxed (SOUP_SOCKET_SOCKET_PROPERTIES,
|
|
Packit Service |
ca3877 |
"Socket properties",
|
|
Packit Service |
ca3877 |
"Socket properties",
|
|
Packit Service |
ca3877 |
SOUP_TYPE_SOCKET_PROPERTIES,
|
|
Packit Service |
ca3877 |
G_PARAM_WRITABLE));
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_initable_interface_init (GInitableIface *initable_interface)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
initable_interface->init = soup_socket_initable_init;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_new:
|
|
Packit Service |
ca3877 |
* @optname1: name of first property to set (or %NULL)
|
|
Packit Service |
ca3877 |
* @...: value of @optname1, followed by additional property/value pairs
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Creates a new (disconnected) socket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: the new socket
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
SoupSocket *
|
|
Packit Service |
ca3877 |
soup_socket_new (const char *optname1, ...)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock;
|
|
Packit Service |
ca3877 |
va_list ap;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
va_start (ap, optname1);
|
|
Packit Service |
ca3877 |
sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
|
|
Packit Service |
ca3877 |
optname1, ap);
|
|
Packit Service |
ca3877 |
va_end (ap);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return sock;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_event (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
GSocketClientEvent event,
|
|
Packit Service |
ca3877 |
GIOStream *connection)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
g_signal_emit (sock, signals[EVENT], 0,
|
|
Packit Service |
ca3877 |
event, connection);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
re_emit_socket_client_event (GSocketClient *client,
|
|
Packit Service |
ca3877 |
GSocketClientEvent event,
|
|
Packit Service |
ca3877 |
GSocketConnectable *connectable,
|
|
Packit Service |
ca3877 |
GIOStream *connection,
|
|
Packit Service |
ca3877 |
gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = user_data;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
soup_socket_event (sock, event, connection);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static gboolean
|
|
Packit Service |
ca3877 |
socket_connect_finish (SoupSocket *sock, GSocketConnection *conn)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->connect_cancel);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (conn) {
|
|
Packit Service |
ca3877 |
priv->conn = (GIOStream *)conn;
|
|
Packit Service |
ca3877 |
priv->gsock = g_object_ref (g_socket_connection_get_socket (conn));
|
|
Packit Service |
ca3877 |
finish_socket_setup (sock);
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
} else
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static guint
|
|
Packit Service |
ca3877 |
socket_legacy_error (SoupSocket *sock, GError *error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
guint status;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
Packit Service |
ca3877 |
status = SOUP_STATUS_CANCELLED;
|
|
Packit Service |
ca3877 |
else if (error->domain == G_RESOLVER_ERROR)
|
|
Packit Service |
ca3877 |
status = SOUP_STATUS_CANT_RESOLVE;
|
|
Packit Service |
ca3877 |
else
|
|
Packit Service |
ca3877 |
status = SOUP_STATUS_CANT_CONNECT;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_error_free (error);
|
|
Packit Service |
ca3877 |
return status;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static GSocketClient *
|
|
Packit Service |
ca3877 |
new_socket_client (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
GSocketClient *client = g_socket_client_new ();
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_signal_connect (client, "event",
|
|
Packit Service |
ca3877 |
G_CALLBACK (re_emit_socket_client_event), sock);
|
|
Packit Service |
ca3877 |
if (priv->proxy_resolver) {
|
|
Packit Service |
ca3877 |
g_socket_client_set_proxy_resolver (client, priv->proxy_resolver);
|
|
Packit Service |
ca3877 |
g_socket_client_add_application_proxy (client, "http");
|
|
Packit Service |
ca3877 |
} else
|
|
Packit Service |
ca3877 |
g_socket_client_set_enable_proxy (client, FALSE);
|
|
Packit Service |
ca3877 |
if (priv->timeout)
|
|
Packit Service |
ca3877 |
g_socket_client_set_timeout (client, priv->timeout);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->local_addr) {
|
|
Packit Service |
ca3877 |
GSocketAddress *addr;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
addr = soup_address_get_gsockaddr (priv->local_addr);
|
|
Packit Service |
ca3877 |
g_socket_client_set_local_address (client, addr);
|
|
Packit Service |
ca3877 |
g_object_unref (addr);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return client;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
async_connected (GObject *client, GAsyncResult *result, gpointer data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
GTask *task = data;
|
|
Packit Service |
ca3877 |
SoupSocket *sock = g_task_get_source_object (task);
|
|
Packit Service |
ca3877 |
GSocketConnection *conn;
|
|
Packit Service |
ca3877 |
GError *error = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client),
|
|
Packit Service |
ca3877 |
result, &error);
|
|
Packit Service |
ca3877 |
if (socket_connect_finish (sock, conn))
|
|
Packit Service |
ca3877 |
g_task_return_boolean (task, TRUE);
|
|
Packit Service |
ca3877 |
else
|
|
Packit Service |
ca3877 |
g_task_return_error (task, error);
|
|
Packit Service |
ca3877 |
g_object_unref (task);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_connect_finish_internal (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
GAsyncResult *result,
|
|
Packit Service |
ca3877 |
GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
return g_task_propagate_boolean (G_TASK (result), error);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
void
|
|
Packit Service |
ca3877 |
soup_socket_connect_async_internal (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
GAsyncReadyCallback callback,
|
|
Packit Service |
ca3877 |
gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
GSocketClient *client;
|
|
Packit Service |
ca3877 |
GTask *task;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_if_fail (SOUP_IS_SOCKET (sock));
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
g_return_if_fail (!priv->is_server);
|
|
Packit Service |
ca3877 |
g_return_if_fail (priv->gsock == NULL);
|
|
Packit Service |
ca3877 |
g_return_if_fail (priv->remote_addr != NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
|
|
Packit Service |
ca3877 |
task = g_task_new (sock, priv->connect_cancel, callback, user_data);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
client = new_socket_client (sock);
|
|
Packit Service |
ca3877 |
g_socket_client_connect_async (client,
|
|
Packit Service |
ca3877 |
G_SOCKET_CONNECTABLE (priv->remote_addr),
|
|
Packit Service |
ca3877 |
priv->connect_cancel,
|
|
Packit Service |
ca3877 |
async_connected, task);
|
|
Packit Service |
ca3877 |
g_object_unref (client);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocketCallback:
|
|
Packit Service |
ca3877 |
* @sock: the #SoupSocket
|
|
Packit Service |
ca3877 |
* @status: an HTTP status code indicating success or failure
|
|
Packit Service |
ca3877 |
* @user_data: the data passed to soup_socket_connect_async()
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* The callback function passed to soup_socket_connect_async().
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
typedef struct {
|
|
Packit Service |
ca3877 |
SoupSocket *sock;
|
|
Packit Service |
ca3877 |
SoupSocketCallback callback;
|
|
Packit Service |
ca3877 |
gpointer user_data;
|
|
Packit Service |
ca3877 |
} SoupSocketAsyncConnectData;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
legacy_connect_async_cb (GObject *object,
|
|
Packit Service |
ca3877 |
GAsyncResult *result,
|
|
Packit Service |
ca3877 |
gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = SOUP_SOCKET (object);
|
|
Packit Service |
ca3877 |
SoupSocketAsyncConnectData *sacd = user_data;
|
|
Packit Service |
ca3877 |
GError *error = NULL;
|
|
Packit Service |
ca3877 |
guint status;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (soup_socket_connect_finish_internal (sock, result, &error))
|
|
Packit Service |
ca3877 |
status = SOUP_STATUS_OK;
|
|
Packit Service |
ca3877 |
else
|
|
Packit Service |
ca3877 |
status = socket_legacy_error (sock, error);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
sacd->callback (sock, status, sacd->user_data);
|
|
Packit Service |
ca3877 |
g_object_unref (sacd->sock);
|
|
Packit Service |
ca3877 |
g_slice_free (SoupSocketAsyncConnectData, sacd);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_connect_async:
|
|
Packit Service |
ca3877 |
* @sock: a client #SoupSocket (which must not already be connected)
|
|
Packit Service |
ca3877 |
* @cancellable: a #GCancellable, or %NULL
|
|
Packit Service |
ca3877 |
* @callback: (scope async): callback to call after connecting
|
|
Packit Service |
ca3877 |
* @user_data: data to pass to @callback
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Begins asynchronously connecting to @sock's remote address. The
|
|
Packit Service |
ca3877 |
* socket will call @callback when it succeeds or fails (but not
|
|
Packit Service |
ca3877 |
* before returning from this function).
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* If @cancellable is non-%NULL, it can be used to cancel the
|
|
Packit Service |
ca3877 |
* connection. @callback will still be invoked in this case, with a
|
|
Packit Service |
ca3877 |
* status of %SOUP_STATUS_CANCELLED.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
void
|
|
Packit Service |
ca3877 |
soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
SoupSocketCallback callback, gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
SoupSocketAsyncConnectData *sacd;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_if_fail (SOUP_IS_SOCKET (sock));
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
g_return_if_fail (!priv->is_server);
|
|
Packit Service |
ca3877 |
g_return_if_fail (priv->gsock == NULL);
|
|
Packit Service |
ca3877 |
g_return_if_fail (priv->remote_addr != NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
sacd = g_slice_new0 (SoupSocketAsyncConnectData);
|
|
Packit Service |
ca3877 |
sacd->sock = g_object_ref (sock);
|
|
Packit Service |
ca3877 |
sacd->callback = callback;
|
|
Packit Service |
ca3877 |
sacd->user_data = user_data;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->async_context && !priv->use_thread_context)
|
|
Packit Service |
ca3877 |
g_main_context_push_thread_default (priv->async_context);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
soup_socket_connect_async_internal (sock, cancellable,
|
|
Packit Service |
ca3877 |
legacy_connect_async_cb,
|
|
Packit Service |
ca3877 |
sacd);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->async_context && !priv->use_thread_context)
|
|
Packit Service |
ca3877 |
g_main_context_pop_thread_default (priv->async_context);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_connect_sync_internal (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
GSocketClient *client;
|
|
Packit Service |
ca3877 |
GSocketConnection *conn;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
client = new_socket_client (sock);
|
|
Packit Service |
ca3877 |
conn = g_socket_client_connect (client,
|
|
Packit Service |
ca3877 |
G_SOCKET_CONNECTABLE (priv->remote_addr),
|
|
Packit Service |
ca3877 |
priv->connect_cancel, error);
|
|
Packit Service |
ca3877 |
g_object_unref (client);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return socket_connect_finish (sock, conn);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_connect_sync:
|
|
Packit Service |
ca3877 |
* @sock: a client #SoupSocket (which must not already be connected)
|
|
Packit Service |
ca3877 |
* @cancellable: a #GCancellable, or %NULL
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Attempt to synchronously connect @sock to its remote address.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* If @cancellable is non-%NULL, it can be used to cancel the
|
|
Packit Service |
ca3877 |
* connection, in which case soup_socket_connect_sync() will return
|
|
Packit Service |
ca3877 |
* %SOUP_STATUS_CANCELLED.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: a success or failure code.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
guint
|
|
Packit Service |
ca3877 |
soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
GError *error = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (soup_socket_connect_sync_internal (sock, cancellable, &error))
|
|
Packit Service |
ca3877 |
return SOUP_STATUS_OK;
|
|
Packit Service |
ca3877 |
else
|
|
Packit Service |
ca3877 |
return socket_legacy_error (sock, error);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_get_fd:
|
|
Packit Service |
ca3877 |
* @sock: a #SoupSocket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Gets @sock's underlying file descriptor.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Note that fiddling with the file descriptor may break the
|
|
Packit Service |
ca3877 |
* #SoupSocket.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: @sock's file descriptor.
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
int
|
|
Packit Service |
ca3877 |
soup_socket_get_fd (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return g_socket_get_fd (priv->gsock);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
GSocket *
|
|
Packit Service |
ca3877 |
soup_socket_get_gsocket (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return priv->gsock;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
GSocket *
|
|
Packit Service |
ca3877 |
soup_socket_steal_gsocket (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
GSocket *gsock;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
gsock = priv->gsock;
|
|
Packit Service |
ca3877 |
priv->gsock = NULL;
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->conn);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->iostream);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return gsock;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_is_readable (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (priv->istream));
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
GIOStream *
|
|
Packit Service |
ca3877 |
soup_socket_get_connection (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return priv->conn;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
GIOStream *
|
|
Packit Service |
ca3877 |
soup_socket_get_iostream (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return priv->iostream;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static GSource *
|
|
Packit Service |
ca3877 |
soup_socket_create_watch (SoupSocketPrivate *priv, GIOCondition cond,
|
|
Packit Service |
ca3877 |
GPollableSourceFunc callback, gpointer user_data,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
GSource *watch;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (cond == G_IO_IN)
|
|
Packit Service |
ca3877 |
watch = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->istream), cancellable);
|
|
Packit Service |
ca3877 |
else
|
|
Packit Service |
ca3877 |
watch = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (priv->ostream), cancellable);
|
|
Packit Service |
ca3877 |
g_source_set_callback (watch, (GSourceFunc)callback, user_data, NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_source_attach (watch, priv->async_context);
|
|
Packit Service |
ca3877 |
g_source_unref (watch);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return watch;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static gboolean
|
|
Packit Service |
ca3877 |
listen_watch (GObject *pollable, gpointer data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = data, *new;
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock), *new_priv;
|
|
Packit Service |
ca3877 |
GSocket *new_gsock;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
new_gsock = g_socket_accept (priv->gsock, NULL, NULL);
|
|
Packit Service |
ca3877 |
if (!new_gsock)
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
new = g_object_new (SOUP_TYPE_SOCKET, NULL);
|
|
Packit Service |
ca3877 |
new_priv = soup_socket_get_instance_private (new);
|
|
Packit Service |
ca3877 |
new_priv->gsock = new_gsock;
|
|
Packit Service |
ca3877 |
if (priv->async_context)
|
|
Packit Service |
ca3877 |
new_priv->async_context = g_main_context_ref (priv->async_context);
|
|
Packit Service |
ca3877 |
new_priv->use_thread_context = priv->use_thread_context;
|
|
Packit Service |
ca3877 |
new_priv->non_blocking = priv->non_blocking;
|
|
Packit Service |
ca3877 |
new_priv->clean_dispose = priv->clean_dispose;
|
|
Packit Service |
ca3877 |
new_priv->is_server = TRUE;
|
|
Packit Service |
ca3877 |
new_priv->ssl = priv->ssl;
|
|
Packit Service |
ca3877 |
if (priv->ssl_creds)
|
|
Packit Service |
ca3877 |
new_priv->ssl_creds = g_object_ref (priv->ssl_creds);
|
|
Packit Service |
ca3877 |
finish_socket_setup (new);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (new_priv->ssl_creds) {
|
|
Packit Service |
ca3877 |
if (!soup_socket_start_proxy_ssl (new, NULL, NULL)) {
|
|
Packit Service |
ca3877 |
g_object_unref (new);
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
|
|
Packit Service |
ca3877 |
g_object_unref (new);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
finish_listener_setup (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->is_server = TRUE;
|
|
Packit Service |
ca3877 |
priv->watch_src = soup_socket_create_watch (priv, G_IO_IN,
|
|
Packit Service |
ca3877 |
listen_watch, sock,
|
|
Packit Service |
ca3877 |
NULL);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_listen:
|
|
Packit Service |
ca3877 |
* @sock: a server #SoupSocket (which must not already be connected or
|
|
Packit Service |
ca3877 |
* listening)
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Makes @sock start listening on its local address. When connections
|
|
Packit Service |
ca3877 |
* come in, @sock will emit #SoupSocket::new_connection.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: whether or not @sock is now listening.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_listen (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
return soup_socket_listen_full (sock, NULL);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_listen_full:
|
|
Packit Service |
ca3877 |
* @sock: a server #SoupSocket (which must not already be connected or listening)
|
|
Packit Service |
ca3877 |
* @error: error pointer
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Makes @sock start listening on its local address. When connections
|
|
Packit Service |
ca3877 |
* come in, @sock will emit #SoupSocket::new_connection.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: whether or not @sock is now listening.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_listen_full (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
GError **error)
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
GSocketAddress *addr;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (priv->gsock == NULL, FALSE);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (priv->local_addr != NULL, FALSE);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* @local_addr may have its port set to 0. So we intentionally
|
|
Packit Service |
ca3877 |
* don't store it in priv->local_addr, so that if the
|
|
Packit Service |
ca3877 |
* caller calls soup_socket_get_local_address() later, we'll
|
|
Packit Service |
ca3877 |
* have to make a new addr by calling getsockname(), which
|
|
Packit Service |
ca3877 |
* will have the right port number.
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
addr = soup_address_get_gsockaddr (priv->local_addr);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (addr != NULL, FALSE);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->gsock = g_socket_new (g_socket_address_get_family (addr),
|
|
Packit Service |
ca3877 |
G_SOCKET_TYPE_STREAM,
|
|
Packit Service |
ca3877 |
G_SOCKET_PROTOCOL_DEFAULT,
|
|
Packit Service |
ca3877 |
error);
|
|
Packit Service |
ca3877 |
if (!priv->gsock)
|
|
Packit Service |
ca3877 |
goto cant_listen;
|
|
Packit Service |
ca3877 |
finish_socket_setup (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
#if defined (IPPROTO_IPV6) && defined (IPV6_V6ONLY)
|
|
Packit Service |
ca3877 |
if (priv->ipv6_only) {
|
|
Packit Service |
ca3877 |
int fd, v6_only;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
fd = g_socket_get_fd (priv->gsock);
|
|
Packit Service |
ca3877 |
v6_only = TRUE;
|
|
Packit Service |
ca3877 |
setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY,
|
|
Packit Service |
ca3877 |
&v6_only, sizeof (v6_only));
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
#endif
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* Bind */
|
|
Packit Service |
ca3877 |
if (!g_socket_bind (priv->gsock, addr, TRUE, error))
|
|
Packit Service |
ca3877 |
goto cant_listen;
|
|
Packit Service |
ca3877 |
/* Force local_addr to be re-resolved now */
|
|
Packit Service |
ca3877 |
g_object_unref (priv->local_addr);
|
|
Packit Service |
ca3877 |
priv->local_addr = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* Listen */
|
|
Packit Service |
ca3877 |
if (!g_socket_listen (priv->gsock, error))
|
|
Packit Service |
ca3877 |
goto cant_listen;
|
|
Packit Service |
ca3877 |
finish_listener_setup (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_object_unref (addr);
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
cant_listen:
|
|
Packit Service |
ca3877 |
if (priv->conn)
|
|
Packit Service |
ca3877 |
disconnect_internal (sock, TRUE);
|
|
Packit Service |
ca3877 |
g_object_unref (addr);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
soup_socket_peer_certificate_changed (GObject *conn, GParamSpec *pspec,
|
|
Packit Service |
ca3877 |
gpointer sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->tls_errors = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (priv->conn));
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_object_notify (sock, "tls-certificate");
|
|
Packit Service |
ca3877 |
g_object_notify (sock, "tls-errors");
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static gboolean
|
|
Packit Service |
ca3877 |
soup_socket_accept_certificate (GTlsConnection *conn, GTlsCertificate *cert,
|
|
Packit Service |
ca3877 |
GTlsCertificateFlags errors, gpointer sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static gboolean
|
|
Packit Service |
ca3877 |
soup_socket_setup_ssl (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
const char *ssl_host,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
GTlsBackend *backend = g_tls_backend_get_default ();
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (G_IS_TLS_CONNECTION (priv->conn))
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->ssl = TRUE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->is_server) {
|
|
Packit Service |
ca3877 |
GTlsClientConnection *conn;
|
|
Packit Service |
ca3877 |
GSocketConnectable *identity;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
identity = g_network_address_new (ssl_host, 0);
|
|
Packit Service |
ca3877 |
conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
|
|
Packit Service |
ca3877 |
cancellable, error,
|
|
Packit Service |
ca3877 |
"base-io-stream", priv->conn,
|
|
Packit Service |
ca3877 |
"server-identity", identity,
|
|
Packit Service |
ca3877 |
"database", priv->ssl_creds,
|
|
Packit Service |
ca3877 |
"require-close-notify", FALSE,
|
|
Packit Service |
ca3877 |
"use-ssl3", priv->ssl_fallback,
|
|
Packit Service |
ca3877 |
NULL);
|
|
Packit Service |
ca3877 |
g_object_unref (identity);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!conn)
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* GLib < 2.41 mistakenly doesn't implement this property in the
|
|
Packit Service |
ca3877 |
* dummy TLS backend, so we don't include it in the g_initable_new()
|
|
Packit Service |
ca3877 |
* call above.
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
g_object_set (G_OBJECT (conn),
|
|
Packit Service |
ca3877 |
"interaction", priv->tls_interaction,
|
|
Packit Service |
ca3877 |
NULL);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_object_unref (priv->conn);
|
|
Packit Service |
ca3877 |
priv->conn = G_IO_STREAM (conn);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->ssl_strict) {
|
|
Packit Service |
ca3877 |
g_signal_connect (conn, "accept-certificate",
|
|
Packit Service |
ca3877 |
G_CALLBACK (soup_socket_accept_certificate),
|
|
Packit Service |
ca3877 |
sock);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
} else {
|
|
Packit Service |
ca3877 |
GTlsServerConnection *conn;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
conn = g_initable_new (g_tls_backend_get_server_connection_type (backend),
|
|
Packit Service |
ca3877 |
cancellable, error,
|
|
Packit Service |
ca3877 |
"base-io-stream", priv->conn,
|
|
Packit Service |
ca3877 |
"certificate", priv->ssl_creds,
|
|
Packit Service |
ca3877 |
"use-system-certdb", FALSE,
|
|
Packit Service |
ca3877 |
"require-close-notify", FALSE,
|
|
Packit Service |
ca3877 |
NULL);
|
|
Packit Service |
ca3877 |
if (!conn)
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_object_unref (priv->conn);
|
|
Packit Service |
ca3877 |
priv->conn = G_IO_STREAM (conn);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_signal_connect (priv->conn, "notify::peer-certificate",
|
|
Packit Service |
ca3877 |
G_CALLBACK (soup_socket_peer_certificate_changed), sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->istream);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->ostream);
|
|
Packit Service |
ca3877 |
g_clear_object (&priv->iostream);
|
|
Packit Service |
ca3877 |
priv->iostream = soup_io_stream_new (priv->conn, FALSE);
|
|
Packit Service |
ca3877 |
priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
|
|
Packit Service |
ca3877 |
priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_start_ssl:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
* @cancellable: a #GCancellable
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Starts using SSL on @socket.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: success or failure
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return soup_socket_setup_ssl (sock, soup_address_get_name (priv->remote_addr),
|
|
Packit Service |
ca3877 |
cancellable, NULL);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_start_proxy_ssl:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
* @ssl_host: hostname of the SSL server
|
|
Packit Service |
ca3877 |
* @cancellable: a #GCancellable
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Starts using SSL on @socket, expecting to find a host named
|
|
Packit Service |
ca3877 |
* @ssl_host.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: success or failure
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
return soup_socket_setup_ssl (sock, ssl_host, cancellable, NULL);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_handshake_sync (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
const char *ssl_host,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, error))
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKING, priv->conn);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn),
|
|
Packit Service |
ca3877 |
cancellable, error))
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKED, priv->conn);
|
|
Packit Service |
ca3877 |
return TRUE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static void
|
|
Packit Service |
ca3877 |
handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
GTask *task = user_data;
|
|
Packit Service |
ca3877 |
GError *error = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (source),
|
|
Packit Service |
ca3877 |
result, &error)) {
|
|
Packit Service |
ca3877 |
SoupSocket *sock = g_task_get_source_object (task);
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKED, priv->conn);
|
|
Packit Service |
ca3877 |
g_task_return_boolean (task, TRUE);
|
|
Packit Service |
ca3877 |
} else
|
|
Packit Service |
ca3877 |
g_task_return_error (task, error);
|
|
Packit Service |
ca3877 |
g_object_unref (task);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
void
|
|
Packit Service |
ca3877 |
soup_socket_handshake_async (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
const char *ssl_host,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
GAsyncReadyCallback callback,
|
|
Packit Service |
ca3877 |
gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
GTask *task;
|
|
Packit Service |
ca3877 |
GError *error = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
task = g_task_new (sock, cancellable, callback, user_data);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, &error)) {
|
|
Packit Service |
ca3877 |
g_task_return_error (task, error);
|
|
Packit Service |
ca3877 |
g_object_unref (task);
|
|
Packit Service |
ca3877 |
return;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
soup_socket_event (sock, G_SOCKET_CLIENT_TLS_HANDSHAKING, priv->conn);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_tls_connection_handshake_async (G_TLS_CONNECTION (priv->conn),
|
|
Packit Service |
ca3877 |
G_PRIORITY_DEFAULT,
|
|
Packit Service |
ca3877 |
cancellable, handshake_async_ready,
|
|
Packit Service |
ca3877 |
task);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_handshake_finish (SoupSocket *sock,
|
|
Packit Service |
ca3877 |
GAsyncResult *result,
|
|
Packit Service |
ca3877 |
GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
return g_task_propagate_boolean (G_TASK (result), error);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_is_ssl:
|
|
Packit Service |
ca3877 |
* @sock: a #SoupSocket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Tests if @sock is doing (or has attempted to do) SSL.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: %TRUE if @sock has SSL credentials set
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_is_ssl (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return priv->ssl;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_disconnect:
|
|
Packit Service |
ca3877 |
* @sock: a #SoupSocket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Disconnects @sock. Any further read or write attempts on it will
|
|
Packit Service |
ca3877 |
* fail.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
void
|
|
Packit Service |
ca3877 |
soup_socket_disconnect (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
gboolean already_disconnected = FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_if_fail (SOUP_IS_SOCKET (sock));
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->connect_cancel) {
|
|
Packit Service |
ca3877 |
disconnect_internal (sock, FALSE);
|
|
Packit Service |
ca3877 |
g_cancellable_cancel (priv->connect_cancel);
|
|
Packit Service |
ca3877 |
return;
|
|
Packit Service |
ca3877 |
} else if (g_mutex_trylock (&priv->iolock)) {
|
|
Packit Service |
ca3877 |
if (priv->conn)
|
|
Packit Service |
ca3877 |
disconnect_internal (sock, TRUE);
|
|
Packit Service |
ca3877 |
else
|
|
Packit Service |
ca3877 |
already_disconnected = TRUE;
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
} else {
|
|
Packit Service |
ca3877 |
/* Another thread is currently doing IO, so
|
|
Packit Service |
ca3877 |
* we can't close the socket. So just shutdown
|
|
Packit Service |
ca3877 |
* the file descriptor to force the I/O to fail.
|
|
Packit Service |
ca3877 |
* (It will actually be closed when the socket
|
|
Packit Service |
ca3877 |
* is destroyed.)
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
g_socket_shutdown (priv->gsock, TRUE, TRUE, NULL);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (already_disconnected)
|
|
Packit Service |
ca3877 |
return;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* Keep ref around signals in case the object is unreferenced
|
|
Packit Service |
ca3877 |
* in a handler
|
|
Packit Service |
ca3877 |
*/
|
|
Packit Service |
ca3877 |
g_object_ref (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->non_blocking) {
|
|
Packit Service |
ca3877 |
/* Give all readers a chance to notice the connection close */
|
|
Packit Service |
ca3877 |
g_signal_emit (sock, signals[READABLE], 0);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* FIXME: can't disconnect until all data is read */
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/* Then let everyone know we're disconnected */
|
|
Packit Service |
ca3877 |
g_signal_emit (sock, signals[DISCONNECTED], 0);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_object_unref (sock);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_is_connected:
|
|
Packit Service |
ca3877 |
* @sock: a #SoupSocket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Tests if @sock is connected to another host
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: %TRUE or %FALSE.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
gboolean
|
|
Packit Service |
ca3877 |
soup_socket_is_connected (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return priv->conn && !g_io_stream_is_closed (priv->conn);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_get_local_address:
|
|
Packit Service |
ca3877 |
* @sock: a #SoupSocket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Returns the #SoupAddress corresponding to the local end of @sock.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Calling this method on an unconnected socket is considered to be
|
|
Packit Service |
ca3877 |
* an error, and produces undefined results.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: (transfer none): the #SoupAddress
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
SoupAddress *
|
|
Packit Service |
ca3877 |
soup_socket_get_local_address (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_lock (&priv->addrlock);
|
|
Packit Service |
ca3877 |
if (!priv->local_addr) {
|
|
Packit Service |
ca3877 |
GSocketAddress *addr;
|
|
Packit Service |
ca3877 |
struct sockaddr_storage sa;
|
|
Packit Service |
ca3877 |
gssize sa_len;
|
|
Packit Service |
ca3877 |
GError *error = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->gsock == NULL) {
|
|
Packit Service |
ca3877 |
g_warning ("%s: socket not connected", G_STRLOC);
|
|
Packit Service |
ca3877 |
goto unlock;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
addr = g_socket_get_local_address (priv->gsock, &error);
|
|
Packit Service |
ca3877 |
if (addr == NULL) {
|
|
Packit Service |
ca3877 |
g_warning ("%s: %s", G_STRLOC, error->message);
|
|
Packit Service |
ca3877 |
g_error_free (error);
|
|
Packit Service |
ca3877 |
goto unlock;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
sa_len = g_socket_address_get_native_size (addr);
|
|
Packit Service |
ca3877 |
g_socket_address_to_native (addr, &sa, sa_len, NULL);
|
|
Packit Service |
ca3877 |
priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
|
|
Packit Service |
ca3877 |
g_object_unref (addr);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
unlock:
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->addrlock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return priv->local_addr;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_get_remote_address:
|
|
Packit Service |
ca3877 |
* @sock: a #SoupSocket
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Returns the #SoupAddress corresponding to the remote end of @sock.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Calling this method on an unconnected socket is considered to be
|
|
Packit Service |
ca3877 |
* an error, and produces undefined results.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: (transfer none): the #SoupAddress
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
SoupAddress *
|
|
Packit Service |
ca3877 |
soup_socket_get_remote_address (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_lock (&priv->addrlock);
|
|
Packit Service |
ca3877 |
if (!priv->remote_addr) {
|
|
Packit Service |
ca3877 |
GSocketAddress *addr;
|
|
Packit Service |
ca3877 |
struct sockaddr_storage sa;
|
|
Packit Service |
ca3877 |
gssize sa_len;
|
|
Packit Service |
ca3877 |
GError *error = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (priv->gsock == NULL) {
|
|
Packit Service |
ca3877 |
g_warning ("%s: socket not connected", G_STRLOC);
|
|
Packit Service |
ca3877 |
goto unlock;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
addr = g_socket_get_remote_address (priv->gsock, &error);
|
|
Packit Service |
ca3877 |
if (addr == NULL) {
|
|
Packit Service |
ca3877 |
g_warning ("%s: %s", G_STRLOC, error->message);
|
|
Packit Service |
ca3877 |
g_error_free (error);
|
|
Packit Service |
ca3877 |
goto unlock;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
sa_len = g_socket_address_get_native_size (addr);
|
|
Packit Service |
ca3877 |
g_socket_address_to_native (addr, &sa, sa_len, NULL);
|
|
Packit Service |
ca3877 |
priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
|
|
Packit Service |
ca3877 |
g_object_unref (addr);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
unlock:
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->addrlock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return priv->remote_addr;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
SoupURI *
|
|
Packit Service |
ca3877 |
soup_socket_get_http_proxy_uri (SoupSocket *sock)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
GSocketAddress *addr;
|
|
Packit Service |
ca3877 |
GProxyAddress *paddr;
|
|
Packit Service |
ca3877 |
SoupURI *uri;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->gsock)
|
|
Packit Service |
ca3877 |
return NULL;
|
|
Packit Service |
ca3877 |
addr = g_socket_get_remote_address (priv->gsock, NULL);
|
|
Packit Service |
ca3877 |
if (!addr || !G_IS_PROXY_ADDRESS (addr)) {
|
|
Packit Service |
ca3877 |
if (addr)
|
|
Packit Service |
ca3877 |
g_object_unref (addr);
|
|
Packit Service |
ca3877 |
return NULL;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
paddr = G_PROXY_ADDRESS (addr);
|
|
Packit Service |
ca3877 |
if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0)
|
|
Packit Service |
ca3877 |
return NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
uri = soup_uri_new (g_proxy_address_get_uri (paddr));
|
|
Packit Service |
ca3877 |
g_object_unref (addr);
|
|
Packit Service |
ca3877 |
return uri;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static gboolean
|
|
Packit Service |
ca3877 |
socket_read_watch (GObject *pollable, gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = user_data;
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->read_src = NULL;
|
|
Packit Service |
ca3877 |
g_signal_emit (sock, signals[READABLE], 0);
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static SoupSocketIOStatus
|
|
Packit Service |
ca3877 |
translate_read_status (SoupSocket *sock, GCancellable *cancellable,
|
|
Packit Service |
ca3877 |
gssize my_nread, gsize *nread,
|
|
Packit Service |
ca3877 |
GError *my_err, GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (my_nread > 0) {
|
|
Packit Service |
ca3877 |
g_assert_no_error (my_err);
|
|
Packit Service |
ca3877 |
*nread = my_nread;
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_OK;
|
|
Packit Service |
ca3877 |
} else if (my_nread == 0) {
|
|
Packit Service |
ca3877 |
g_assert_no_error (my_err);
|
|
Packit Service |
ca3877 |
*nread = my_nread;
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_EOF;
|
|
Packit Service |
ca3877 |
} else if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
|
Packit Service |
ca3877 |
g_clear_error (&my_err);
|
|
Packit Service |
ca3877 |
if (!priv->read_src) {
|
|
Packit Service |
ca3877 |
priv->read_src =
|
|
Packit Service |
ca3877 |
soup_socket_create_watch (priv, G_IO_IN,
|
|
Packit Service |
ca3877 |
socket_read_watch, sock,
|
|
Packit Service |
ca3877 |
cancellable);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_WOULD_BLOCK;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_propagate_error (error, my_err);
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_ERROR;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* SoupSocketIOStatus:
|
|
Packit Service |
ca3877 |
* @SOUP_SOCKET_OK: Success
|
|
Packit Service |
ca3877 |
* @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time
|
|
Packit Service |
ca3877 |
* @SOUP_SOCKET_EOF: End of file
|
|
Packit Service |
ca3877 |
* @SOUP_SOCKET_ERROR: Other error
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value from the #SoupSocket IO methods.
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_read:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
* @buffer: (array length=len) (element-type guint8): buffer to read
|
|
Packit Service |
ca3877 |
* into
|
|
Packit Service |
ca3877 |
* @len: size of @buffer in bytes
|
|
Packit Service |
ca3877 |
* @nread: (out): on return, the number of bytes read into @buffer
|
|
Packit Service |
ca3877 |
* @cancellable: a #GCancellable, or %NULL
|
|
Packit Service |
ca3877 |
* @error: error pointer
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Attempts to read up to @len bytes from @sock into @buffer. If some
|
|
Packit Service |
ca3877 |
* data is successfully read, soup_socket_read() will return
|
|
Packit Service |
ca3877 |
* %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
|
|
Packit Service |
ca3877 |
* actually read (which may be less than @len).
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* If @sock is non-blocking, and no data is available, the return
|
|
Packit Service |
ca3877 |
* value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
|
|
Packit Service |
ca3877 |
* can connect to the #SoupSocket::readable signal to know when there
|
|
Packit Service |
ca3877 |
* is more data to read. (NB: You MUST read all available data off the
|
|
Packit Service |
ca3877 |
* socket first. #SoupSocket::readable is only emitted after
|
|
Packit Service |
ca3877 |
* soup_socket_read() returns %SOUP_SOCKET_WOULD_BLOCK, and it is only
|
|
Packit Service |
ca3877 |
* emitted once. See the documentation for #SoupSocket:non-blocking.)
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: a #SoupSocketIOStatus, as described above (or
|
|
Packit Service |
ca3877 |
* %SOUP_SOCKET_EOF if the socket is no longer connected, or
|
|
Packit Service |
ca3877 |
* %SOUP_SOCKET_ERROR on any other error, in which case @error will
|
|
Packit Service |
ca3877 |
* also be set).
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
SoupSocketIOStatus
|
|
Packit Service |
ca3877 |
soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
|
|
Packit Service |
ca3877 |
gsize *nread, GCancellable *cancellable, GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
SoupSocketIOStatus status;
|
|
Packit Service |
ca3877 |
gssize my_nread;
|
|
Packit Service |
ca3877 |
GError *my_err = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_lock (&priv->iolock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->istream) {
|
|
Packit Service |
ca3877 |
status = SOUP_SOCKET_EOF;
|
|
Packit Service |
ca3877 |
goto out;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->non_blocking) {
|
|
Packit Service |
ca3877 |
my_nread = g_input_stream_read (priv->istream, buffer, len,
|
|
Packit Service |
ca3877 |
cancellable, &my_err);
|
|
Packit Service |
ca3877 |
} else {
|
|
Packit Service |
ca3877 |
my_nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (priv->istream),
|
|
Packit Service |
ca3877 |
buffer, len,
|
|
Packit Service |
ca3877 |
cancellable, &my_err);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
status = translate_read_status (sock, cancellable,
|
|
Packit Service |
ca3877 |
my_nread, nread, my_err, error);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
out:
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
return status;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_read_until:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
* @buffer: (array length=len) (element-type guint8): buffer to read
|
|
Packit Service |
ca3877 |
* into
|
|
Packit Service |
ca3877 |
* @len: size of @buffer in bytes
|
|
Packit Service |
ca3877 |
* @boundary: boundary to read until
|
|
Packit Service |
ca3877 |
* @boundary_len: length of @boundary in bytes
|
|
Packit Service |
ca3877 |
* @nread: (out): on return, the number of bytes read into @buffer
|
|
Packit Service |
ca3877 |
* @got_boundary: on return, whether or not the data in @buffer
|
|
Packit Service |
ca3877 |
* ends with the boundary string
|
|
Packit Service |
ca3877 |
* @cancellable: a #GCancellable, or %NULL
|
|
Packit Service |
ca3877 |
* @error: error pointer
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Like soup_socket_read(), but reads no further than the first
|
|
Packit Service |
ca3877 |
* occurrence of @boundary. (If the boundary is found, it will be
|
|
Packit Service |
ca3877 |
* included in the returned data, and *@got_boundary will be set to
|
|
Packit Service |
ca3877 |
* %TRUE.) Any data after the boundary will returned in future reads.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* soup_socket_read_until() will almost always return fewer than @len
|
|
Packit Service |
ca3877 |
* bytes: if the boundary is found, then it will only return the bytes
|
|
Packit Service |
ca3877 |
* up until the end of the boundary, and if the boundary is not found,
|
|
Packit Service |
ca3877 |
* then it will leave the last <literal>(boundary_len - 1)</literal>
|
|
Packit Service |
ca3877 |
* bytes in its internal buffer, in case they form the start of the
|
|
Packit Service |
ca3877 |
* boundary string. Thus, @len normally needs to be at least 1 byte
|
|
Packit Service |
ca3877 |
* longer than @boundary_len if you want to make any progress at all.
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: as for soup_socket_read()
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
SoupSocketIOStatus
|
|
Packit Service |
ca3877 |
soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
|
|
Packit Service |
ca3877 |
gconstpointer boundary, gsize boundary_len,
|
|
Packit Service |
ca3877 |
gsize *nread, gboolean *got_boundary,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable, GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
SoupSocketIOStatus status;
|
|
Packit Service |
ca3877 |
gssize my_nread;
|
|
Packit Service |
ca3877 |
GError *my_err = NULL;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_lock (&priv->iolock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
*got_boundary = FALSE;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->istream)
|
|
Packit Service |
ca3877 |
status = SOUP_SOCKET_EOF;
|
|
Packit Service |
ca3877 |
else {
|
|
Packit Service |
ca3877 |
my_nread = soup_filter_input_stream_read_until (
|
|
Packit Service |
ca3877 |
SOUP_FILTER_INPUT_STREAM (priv->istream),
|
|
Packit Service |
ca3877 |
buffer, len, boundary, boundary_len,
|
|
Packit Service |
ca3877 |
!priv->non_blocking,
|
|
Packit Service |
ca3877 |
TRUE, got_boundary, cancellable, &my_err);
|
|
Packit Service |
ca3877 |
status = translate_read_status (sock, cancellable,
|
|
Packit Service |
ca3877 |
my_nread, nread, my_err, error);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
return status;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
static gboolean
|
|
Packit Service |
ca3877 |
socket_write_watch (GObject *pollable, gpointer user_data)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocket *sock = user_data;
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->write_src = NULL;
|
|
Packit Service |
ca3877 |
g_signal_emit (sock, signals[WRITABLE], 0);
|
|
Packit Service |
ca3877 |
return FALSE;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
/**
|
|
Packit Service |
ca3877 |
* soup_socket_write:
|
|
Packit Service |
ca3877 |
* @sock: the socket
|
|
Packit Service |
ca3877 |
* @buffer: (array length=len) (element-type guint8): data to write
|
|
Packit Service |
ca3877 |
* @len: size of @buffer, in bytes
|
|
Packit Service |
ca3877 |
* @nwrote: (out): on return, number of bytes written
|
|
Packit Service |
ca3877 |
* @cancellable: a #GCancellable, or %NULL
|
|
Packit Service |
ca3877 |
* @error: error pointer
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Attempts to write @len bytes from @buffer to @sock. If some data is
|
|
Packit Service |
ca3877 |
* successfully written, the return status will be %SOUP_SOCKET_OK,
|
|
Packit Service |
ca3877 |
* and *@nwrote will contain the number of bytes actually written
|
|
Packit Service |
ca3877 |
* (which may be less than @len).
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* If @sock is non-blocking, and no data could be written right away,
|
|
Packit Service |
ca3877 |
* the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
|
|
Packit Service |
ca3877 |
* the caller can connect to the #SoupSocket::writable signal to know
|
|
Packit Service |
ca3877 |
* when more data can be written. (NB: #SoupSocket::writable is only
|
|
Packit Service |
ca3877 |
* emitted after soup_socket_write() returns %SOUP_SOCKET_WOULD_BLOCK,
|
|
Packit Service |
ca3877 |
* and it is only emitted once. See the documentation for
|
|
Packit Service |
ca3877 |
* #SoupSocket:non-blocking.)
|
|
Packit Service |
ca3877 |
*
|
|
Packit Service |
ca3877 |
* Return value: a #SoupSocketIOStatus, as described above (or
|
|
Packit Service |
ca3877 |
* %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the
|
|
Packit Service |
ca3877 |
* return value is %SOUP_SOCKET_ERROR.)
|
|
Packit Service |
ca3877 |
**/
|
|
Packit Service |
ca3877 |
SoupSocketIOStatus
|
|
Packit Service |
ca3877 |
soup_socket_write (SoupSocket *sock, gconstpointer buffer,
|
|
Packit Service |
ca3877 |
gsize len, gsize *nwrote,
|
|
Packit Service |
ca3877 |
GCancellable *cancellable, GError **error)
|
|
Packit Service |
ca3877 |
{
|
|
Packit Service |
ca3877 |
SoupSocketPrivate *priv;
|
|
Packit Service |
ca3877 |
GError *my_err = NULL;
|
|
Packit Service |
ca3877 |
gssize my_nwrote;
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
|
|
Packit Service |
ca3877 |
g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv = soup_socket_get_instance_private (sock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_lock (&priv->iolock);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->conn) {
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_EOF;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
if (priv->write_src) {
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_WOULD_BLOCK;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (!priv->non_blocking) {
|
|
Packit Service |
ca3877 |
my_nwrote = g_output_stream_write (priv->ostream,
|
|
Packit Service |
ca3877 |
buffer, len,
|
|
Packit Service |
ca3877 |
cancellable, &my_err);
|
|
Packit Service |
ca3877 |
} else {
|
|
Packit Service |
ca3877 |
my_nwrote = g_pollable_output_stream_write_nonblocking (
|
|
Packit Service |
ca3877 |
G_POLLABLE_OUTPUT_STREAM (priv->ostream),
|
|
Packit Service |
ca3877 |
buffer, len, cancellable, &my_err);
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (my_nwrote > 0) {
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
g_clear_error (&my_err);
|
|
Packit Service |
ca3877 |
*nwrote = my_nwrote;
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_OK;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
g_clear_error (&my_err);
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
priv->write_src =
|
|
Packit Service |
ca3877 |
soup_socket_create_watch (priv,
|
|
Packit Service |
ca3877 |
G_IO_OUT,
|
|
Packit Service |
ca3877 |
socket_write_watch, sock, cancellable);
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_WOULD_BLOCK;
|
|
Packit Service |
ca3877 |
}
|
|
Packit Service |
ca3877 |
|
|
Packit Service |
ca3877 |
g_mutex_unlock (&priv->iolock);
|
|
Packit Service |
ca3877 |
g_propagate_error (error, my_err);
|
|
Packit Service |
ca3877 |
return SOUP_SOCKET_ERROR;
|
|
Packit Service |
ca3877 |
}
|