summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2005-11-10 16:48:42 +0000
committerDan Winship <danw@src.gnome.org>2005-11-10 16:48:42 +0000
commit9781c6572877b6a2b83661073cf7932e4d54566b (patch)
treed43354b1a7692460514c516c3449c034cb642110
parentfda55879a793982bf069d399fce60c85380ad7b0 (diff)
downloadlibsoup-9781c6572877b6a2b83661073cf7932e4d54566b.tar.gz
bump version to 2.2.90. This will not be officially released, but once
* configure.in: bump version to 2.2.90. This will not be officially released, but once these patches have gotten some testing they may be pulled up to the gnome-2-12 branch. * libsoup/soup-connection.c: * libsoup/soup-server.c: * libsoup/soup-session.c: * libsoup/soup-socket.c: add an "async-context" property, which gets passed from server to socket, and session to connection to socket, allowing async usage outside the main thread. Based on patches from Armin Bauer and Jürg Billeter. * libsoup/soup-misc.c (soup_add_io_watch, soup_add_idle, soup_add_timeout): utility routines to add watches, idles, and timeouts to non-default GMainContexts. * libsoup/soup-message-io.c (io_write): set the read state appropriately after writing a "100 Continue" response (io_read): More 100-Continue stuff. I don't think this is quite right so it will probably change again later.
-rw-r--r--ChangeLog23
-rw-r--r--configure.in6
-rw-r--r--libsoup/soup-connection.c37
-rw-r--r--libsoup/soup-connection.h1
-rw-r--r--libsoup/soup-message-io.c6
-rw-r--r--libsoup/soup-misc.c78
-rw-r--r--libsoup/soup-misc.h14
-rw-r--r--libsoup/soup-server.c33
-rw-r--r--libsoup/soup-server.h1
-rw-r--r--libsoup/soup-session.c21
-rw-r--r--libsoup/soup-session.h1
-rw-r--r--libsoup/soup-socket.c113
-rw-r--r--libsoup/soup-socket.h1
13 files changed, 276 insertions, 59 deletions
diff --git a/ChangeLog b/ChangeLog
index 6c14b9cb..1a921f2f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2005-11-10 Dan Winship <danw@novell.com>
+
+ * configure.in: bump version to 2.2.90. This will not be
+ officially released, but once these patches have gotten some
+ testing they may be pulled up to the gnome-2-12 branch.
+
+ * libsoup/soup-connection.c:
+ * libsoup/soup-server.c:
+ * libsoup/soup-session.c:
+ * libsoup/soup-socket.c: add an "async-context" property,
+ which gets passed from server to socket, and session to connection
+ to socket, allowing async usage outside the main thread. Based on
+ patches from Armin Bauer and Jürg Billeter.
+
+ * libsoup/soup-misc.c (soup_add_io_watch, soup_add_idle,
+ soup_add_timeout): utility routines to add watches, idles, and
+ timeouts to non-default GMainContexts.
+
+ * libsoup/soup-message-io.c (io_write): set the read state
+ appropriately after writing a "100 Continue" response
+ (io_read): More 100-Continue stuff. I don't think this is quite
+ right so it will probably change again later.
+
2005-11-01 Dan Winship <danw@novell.com>
* docs/reference/libsoup-docs.sgml: tell it to generate an index
diff --git a/configure.in b/configure.in
index 61d759ec..3db8069c 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@ dnl *** Initialize automake and set version ***
dnl *******************************************
AC_PREREQ(2.53)
-AC_INIT(libsoup, 2.2.6.1)
+AC_INIT(libsoup, 2.2.90)
AC_CONFIG_SRCDIR(libsoup.pc.in)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
@@ -15,10 +15,10 @@ SOUP_API_VERSION=2.2
AC_SUBST(SOUP_API_VERSION)
# Increment on interface addition. Reset on removal.
-SOUP_AGE=1
+SOUP_AGE=2
# Increment on interface add, remove, or change.
-SOUP_CURRENT=9
+SOUP_CURRENT=10
# Increment on source change. Reset when CURRENT changes.
SOUP_REVISION=0
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 53027681..0169e137 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -41,6 +41,7 @@ typedef struct {
gpointer ssl_creds;
SoupMessageFilter *filter;
+ GMainContext *async_context;
SoupMessage *cur_req;
time_t last_used;
@@ -67,6 +68,7 @@ enum {
PROP_PROXY_URI,
PROP_SSL_CREDS,
PROP_MESSAGE_FILTER,
+ PROP_ASYNC_CONTEXT,
LAST_PROP
};
@@ -96,6 +98,8 @@ finalize (GObject *object)
if (priv->filter)
g_object_unref (priv->filter);
+ if (priv->async_context)
+ g_main_context_unref (priv->async_context);
G_OBJECT_CLASS (soup_connection_parent_class)->finalize (object);
}
@@ -244,6 +248,12 @@ soup_connection_class_init (SoupConnectionClass *connection_class)
"Message filter",
"Message filter object for this connection",
G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class, PROP_ASYNC_CONTEXT,
+ g_param_spec_pointer (SOUP_CONNECTION_ASYNC_CONTEXT,
+ "Async GMainContext",
+ "GMainContext to dispatch this connection's async I/O in",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
@@ -304,7 +314,16 @@ set_property (GObject *object, guint prop_id,
priv->ssl_creds = g_value_get_pointer (value);
break;
case PROP_MESSAGE_FILTER:
- priv->filter = g_object_ref (g_value_get_pointer (value));
+ if (priv->filter)
+ g_object_unref (priv->filter);
+ priv->filter = g_value_get_pointer (value);
+ if (priv->filter)
+ g_object_ref (priv->filter);
+ break;
+ case PROP_ASYNC_CONTEXT:
+ priv->async_context = g_value_get_pointer (value);
+ if (priv->async_context)
+ g_main_context_ref (priv->async_context);
break;
default:
break;
@@ -331,7 +350,10 @@ get_property (GObject *object, guint prop_id,
g_value_set_pointer (value, priv->ssl_creds);
break;
case PROP_MESSAGE_FILTER:
- g_value_set_pointer (value, g_object_ref (priv->filter));
+ g_value_set_pointer (value, priv->filter ? g_object_ref (priv->filter) : NULL);
+ break;
+ case PROP_ASYNC_CONTEXT:
+ g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
break;
default:
break;
@@ -513,10 +535,13 @@ soup_connection_connect_async (SoupConnection *conn,
}
priv->socket =
- soup_socket_client_new_async (priv->conn_uri->host,
- priv->conn_uri->port,
- priv->ssl_creds,
- socket_connect_result, conn);
+ soup_socket_new (SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
+ SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
+ NULL);
+ soup_socket_connect (priv->socket, soup_address_new (priv->conn_uri->host,
+ priv->conn_uri->port));
+ soup_signal_connect_once (priv->socket, "connect_result",
+ G_CALLBACK (socket_connect_result), conn);
g_signal_connect (priv->socket, "disconnected",
G_CALLBACK (socket_disconnected), conn);
}
diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h
index 0c191b96..5bfb6aa8 100644
--- a/libsoup/soup-connection.h
+++ b/libsoup/soup-connection.h
@@ -60,6 +60,7 @@ typedef void (*SoupConnectionCallback) (SoupConnection *conn,
#define SOUP_CONNECTION_PROXY_URI "proxy-uri"
#define SOUP_CONNECTION_SSL_CREDENTIALS "ssl-creds"
#define SOUP_CONNECTION_MESSAGE_FILTER "message-filter"
+#define SOUP_CONNECTION_ASYNC_CONTEXT "async-context"
SoupConnection *soup_connection_new (const char *propname1,
...) G_GNUC_NULL_TERMINATED;
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index b06d3505..7e59f163 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -373,6 +373,7 @@ io_write (SoupSocket *sock, SoupMessage *msg)
/* Stop and wait for the body now */
io->write_state =
SOUP_MESSAGE_IO_STATE_BLOCKING;
+ io->read_state = io_body_state (io->read_encoding);
} else {
/* We just wrote a 1xx response
* header, so stay in STATE_HEADERS.
@@ -570,13 +571,16 @@ io_read (SoupSocket *sock, SoupMessage *msg)
} else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
(priv->msg_flags & SOUP_MESSAGE_EXPECT_CONTINUE)) {
/* The client requested a Continue response. */
+ soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
+
io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
} else
io->read_state = io_body_state (io->read_encoding);
SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
- if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
+ if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code) &&
+ !(priv->msg_flags & SOUP_MESSAGE_EXPECT_CONTINUE)) {
soup_message_got_informational (msg);
soup_message_cleanup_response (msg);
} else
diff --git a/libsoup/soup-misc.c b/libsoup/soup-misc.c
index 500caadd..7f19d5dd 100644
--- a/libsoup/soup-misc.c
+++ b/libsoup/soup-misc.c
@@ -392,3 +392,81 @@ soup_signal_connect_once (gpointer instance, const char *detailed_signal,
closure, FALSE);
return ssod->signal_id;
}
+
+/**
+ * soup_add_io_watch:
+ * @async_context: the #GMainContext to dispatch the I/O watch in, or
+ * %NULL for the default context
+ * @chan: the #GIOChannel to watch
+ * @condition: the condition to watch for
+ * @function: the callback to invoke when @condition occurs
+ * @data: user data to pass to @function
+ *
+ * Adds an I/O watch as with g_io_add_watch(), but using the given
+ * @async_context.
+ *
+ * Return value: a #GSource, which can be removed from @async_context
+ * with g_source_destroy().
+ **/
+GSource *
+soup_add_io_watch (GMainContext *async_context,
+ GIOChannel *chan, GIOCondition condition,
+ GIOFunc function, gpointer data)
+{
+ GSource *watch = g_io_create_watch (chan, condition);
+ g_source_set_callback (watch, (GSourceFunc) function, data, NULL);
+ g_source_attach (watch, async_context);
+ g_source_unref (watch);
+ return watch;
+}
+
+/**
+ * soup_add_idle:
+ * @async_context: the #GMainContext to dispatch the idle event in, or
+ * %NULL for the default context
+ * @function: the callback to invoke at idle time
+ * @data: user data to pass to @function
+ *
+ * Adds an idle event as with g_idle_add(), but using the given
+ * @async_context.
+ *
+ * Return value: a #GSource, which can be removed from @async_context
+ * with g_source_destroy().
+ **/
+GSource *
+soup_add_idle (GMainContext *async_context,
+ GSourceFunc function, gpointer data)
+{
+ GSource *source = g_idle_source_new ();
+ g_source_set_callback (source, function, data, NULL);
+ g_source_attach (source, async_context);
+ g_source_unref (watch);
+ return source;
+}
+
+/**
+ * soup_add_timeout:
+ * @async_context: the #GMainContext to dispatch the timeout in, or
+ * %NULL for the default context
+ * @interval: the timeout interval, in milliseconds
+ * @function: the callback to invoke at timeout time
+ * @data: user data to pass to @function
+ *
+ * Adds a timeout as with g_timeout_add(), but using the given
+ * @async_context.
+ *
+ * Return value: a #GSource, which can be removed from @async_context
+ * with g_source_destroy().
+ **/
+GSource *
+soup_add_timeout (GMainContext *async_context,
+ guint interval,
+ GSourceFunc function, gpointer data)
+{
+ GSource *source = g_timeout_source_new (interval);
+ g_source_set_callback (source, function, data, NULL);
+ g_source_attach (source, async_context);
+ g_source_unref (watch);
+ return source;
+}
+
diff --git a/libsoup/soup-misc.h b/libsoup/soup-misc.h
index 0962813c..0398abe7 100644
--- a/libsoup/soup-misc.h
+++ b/libsoup/soup-misc.h
@@ -36,6 +36,20 @@ int soup_base64_decode_step (const guchar *in,
int *state,
guint *save);
+/* Non-default-GMainContext operations */
+GSource *soup_add_io_watch (GMainContext *async_context,
+ GIOChannel *chan,
+ GIOCondition condition,
+ GIOFunc function,
+ gpointer data);
+GSource *soup_add_idle (GMainContext *async_context,
+ GSourceFunc function,
+ gpointer data);
+GSource *soup_add_timeout (GMainContext *async_context,
+ guint interval,
+ GSourceFunc function,
+ gpointer data);
+
/* Misc utils */
guint soup_signal_connect_once (gpointer instance,
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index 22f62058..f64d7d34 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -42,6 +42,8 @@ typedef struct {
GHashTable *handlers; /* KEY: path, VALUE: SoupServerHandler */
SoupServerHandler *default_handler;
+
+ GMainContext *async_context;
} SoupServerPrivate;
#define SOUP_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SERVER, SoupServerPrivate))
@@ -52,6 +54,7 @@ enum {
PROP_INTERFACE,
PROP_SSL_CERT_FILE,
PROP_SSL_KEY_FILE,
+ PROP_ASYNC_CONTEXT,
LAST_PROP
};
@@ -124,6 +127,8 @@ finalize (GObject *object)
if (priv->loop)
g_main_loop_unref (priv->loop);
+ if (priv->async_context)
+ g_main_context_unref (priv->async_context);
G_OBJECT_CLASS (soup_server_parent_class)->finalize (object);
}
@@ -169,6 +174,12 @@ soup_server_class_init (SoupServerClass *server_class)
"File containing server SSL key",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (
+ object_class, PROP_ASYNC_CONTEXT,
+ g_param_spec_pointer (SOUP_SERVER_ASYNC_CONTEXT,
+ "Async GMainContext",
+ "The GMainContext to dispatch async I/O in",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
@@ -197,6 +208,11 @@ set_property (GObject *object, guint prop_id,
priv->ssl_key_file =
g_strdup (g_value_get_string (value));
break;
+ case PROP_ASYNC_CONTEXT:
+ priv->async_context = g_value_get_pointer (value);
+ if (priv->async_context)
+ g_main_context_ref (priv->async_context);
+ break;
default:
break;
}
@@ -221,6 +237,9 @@ get_property (GObject *object, guint prop_id,
case PROP_SSL_KEY_FILE:
g_value_set_string (value, g_strdup (priv->ssl_key_file));
break;
+ case PROP_ASYNC_CONTEXT:
+ g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
+ break;
default:
break;
}
@@ -259,10 +278,10 @@ soup_server_new (const char *optname1, ...)
}
priv->listen_sock =
- soup_socket_server_new (priv->interface,
- priv->ssl_creds,
- NULL, NULL);
- if (!priv->listen_sock) {
+ soup_socket_new (SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
+ SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
+ NULL);
+ if (!soup_socket_listen (priv->listen_sock, priv->interface)) {
g_object_unref (server);
return NULL;
}
@@ -486,7 +505,7 @@ soup_server_run (SoupServer *server)
priv = SOUP_SERVER_GET_PRIVATE (server);
if (!priv->loop) {
- priv->loop = g_main_loop_new (NULL, TRUE);
+ priv->loop = g_main_loop_new (priv->async_context, TRUE);
soup_server_run_async (server);
}
@@ -502,7 +521,9 @@ soup_server_quit (SoupServer *server)
g_return_if_fail (SOUP_IS_SERVER (server));
priv = SOUP_SERVER_GET_PRIVATE (server);
- g_main_loop_quit (priv->loop);
+ if (priv->loop)
+ g_main_loop_quit (priv->loop);
+
g_object_unref (server);
}
diff --git a/libsoup/soup-server.h b/libsoup/soup-server.h
index 40f7fad6..c530a15d 100644
--- a/libsoup/soup-server.h
+++ b/libsoup/soup-server.h
@@ -64,6 +64,7 @@ struct SoupServerHandler {
#define SOUP_SERVER_INTERFACE "interface"
#define SOUP_SERVER_SSL_CERT_FILE "ssl-cert-file"
#define SOUP_SERVER_SSL_KEY_FILE "ssl-key-file"
+#define SOUP_SERVER_ASYNC_CONTEXT "async-context"
SoupServer *soup_server_new (const char *optname1,
...) G_GNUC_NULL_TERMINATED;
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index e9d32662..6381939c 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -54,6 +54,8 @@ typedef struct {
* Must not emit signals or destroy objects while holding it.
*/
GMutex *host_lock;
+
+ GMainContext *async_context;
} SoupSessionPrivate;
#define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate))
@@ -94,6 +96,7 @@ enum {
PROP_MAX_CONNS_PER_HOST,
PROP_USE_NTLM,
PROP_SSL_CA_FILE,
+ PROP_ASYNC_CONTEXT,
LAST_PROP
};
@@ -165,6 +168,9 @@ finalize (GObject *object)
g_hash_table_destroy (priv->hosts);
g_hash_table_destroy (priv->conns);
+ if (priv->async_context)
+ g_main_context_unref (priv->async_context);
+
G_OBJECT_CLASS (soup_session_parent_class)->finalize (object);
}
@@ -307,6 +313,12 @@ soup_session_class_init (SoupSessionClass *session_class)
"File containing SSL CA certificates",
NULL,
G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class, PROP_ASYNC_CONTEXT,
+ g_param_spec_pointer (SOUP_SESSION_ASYNC_CONTEXT,
+ "Async GMainContext",
+ "The GMainContext to dispatch async I/O in",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
static void
@@ -398,6 +410,11 @@ set_property (GObject *object, guint prop_id,
}
break;
+ case PROP_ASYNC_CONTEXT:
+ priv->async_context = g_value_get_pointer (value);
+ if (priv->async_context)
+ g_main_context_ref (priv->async_context);
+ break;
default:
break;
}
@@ -428,6 +445,9 @@ get_property (GObject *object, guint prop_id,
case PROP_SSL_CA_FILE:
g_value_set_string (value, priv->ssl_ca_file);
break;
+ case PROP_ASYNC_CONTEXT:
+ g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
+ break;
default:
break;
}
@@ -1142,6 +1162,7 @@ soup_session_get_connection (SoupSession *session, SoupMessage *msg,
SOUP_CONNECTION_PROXY_URI, priv->proxy_uri,
SOUP_CONNECTION_SSL_CREDENTIALS, priv->ssl_creds,
SOUP_CONNECTION_MESSAGE_FILTER, session,
+ SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context,
NULL);
g_signal_connect (conn, "connect_result",
G_CALLBACK (connect_result),
diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h
index cdafd968..b19f7833 100644
--- a/libsoup/soup-session.h
+++ b/libsoup/soup-session.h
@@ -53,6 +53,7 @@ GType soup_session_get_type (void);
#define SOUP_SESSION_MAX_CONNS_PER_HOST "max-conns-per-host"
#define SOUP_SESSION_USE_NTLM "use-ntlm"
#define SOUP_SESSION_SSL_CA_FILE "ssl-ca-file"
+#define SOUP_SESSION_ASYNC_CONTEXT "async-context"
void soup_session_add_filter (SoupSession *session,
SoupMessageFilter *filter);
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 1bd98699..a958af9a 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -45,6 +45,7 @@ enum {
PROP_CLOEXEC,
PROP_IS_SERVER,
PROP_SSL_CREDENTIALS,
+ PROP_ASYNC_CONTEXT,
LAST_PROP
};
@@ -61,8 +62,9 @@ typedef struct {
guint is_server:1;
gpointer ssl_creds;
- guint watch;
- guint read_tag, write_tag, error_tag;
+ GMainContext *async_context;
+ GSource *watch_src;
+ GSource *read_src, *write_src;
GByteArray *read_buf;
GMutex *iolock, *addrlock;
@@ -112,17 +114,13 @@ disconnect_internal (SoupSocketPrivate *priv)
priv->iochannel = NULL;
priv->sockfd = -1;
- if (priv->read_tag) {
- g_source_remove (priv->read_tag);
- priv->read_tag = 0;
+ if (priv->read_src) {
+ g_source_destroy (priv->read_src);
+ priv->read_src = NULL;
}
- if (priv->write_tag) {
- g_source_remove (priv->write_tag);
- priv->write_tag = 0;
- }
- if (priv->error_tag) {
- g_source_remove (priv->error_tag);
- priv->error_tag = 0;
+ if (priv->write_src) {
+ g_source_destroy (priv->write_src);
+ priv->write_src = NULL;
}
}
@@ -139,8 +137,10 @@ finalize (GObject *object)
if (priv->remote_addr)
g_object_unref (priv->remote_addr);
- if (priv->watch)
- g_source_remove (priv->watch);
+ if (priv->watch_src)
+ g_source_destroy (priv->watch_src);
+ if (priv->async_context)
+ g_main_context_unref (priv->async_context);
if (priv->read_buf)
g_byte_array_free (priv->read_buf, TRUE);
@@ -292,6 +292,12 @@ soup_socket_class_init (SoupSocketClass *socket_class)
"SSL credentials",
"SSL credential information, passed from the session to the SSL implementation",
G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class, PROP_ASYNC_CONTEXT,
+ g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
+ "Async GMainContext",
+ "The GMainContext to dispatch this socket's async I/O in",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
#ifdef G_OS_WIN32
/* Make sure WSAStartup() gets called. */
@@ -374,6 +380,11 @@ set_property (GObject *object, guint prop_id,
case PROP_SSL_CREDENTIALS:
priv->ssl_creds = g_value_get_pointer (value);
break;
+ case PROP_ASYNC_CONTEXT:
+ priv->async_context = g_value_get_pointer (value);
+ if (priv->async_context)
+ g_main_context_ref (priv->async_context);
+ break;
default:
break;
}
@@ -404,6 +415,9 @@ get_property (GObject *object, guint prop_id,
case PROP_SSL_CREDENTIALS:
g_value_set_pointer (value, priv->ssl_creds);
break;
+ case PROP_ASYNC_CONTEXT:
+ g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
+ break;
default:
break;
}
@@ -459,7 +473,7 @@ idle_connect_result (gpointer user_data)
SoupSocket *sock = user_data;
SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
- priv->watch = 0;
+ priv->watch_src = NULL;
g_signal_emit (sock, signals[CONNECT_RESULT], 0,
priv->sockfd != -1 ? SOUP_STATUS_OK : SOUP_STATUS_CANT_CONNECT);
@@ -475,8 +489,8 @@ connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
int len = sizeof (error);
/* Remove the watch now in case we don't return immediately */
- g_source_remove (priv->watch);
- priv->watch = 0;
+ g_source_destroy (priv->watch_src);
+ priv->watch_src = NULL;
if (condition & ~(G_IO_IN | G_IO_OUT))
goto cant_connect;
@@ -570,12 +584,13 @@ soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
if (SOUP_IS_SOCKET_ERROR (status)) {
if (SOUP_IS_CONNECT_STATUS_INPROGRESS ()) {
/* Wait for connect to succeed or fail */
- priv->watch =
- g_io_add_watch (get_iochannel (priv),
- G_IO_IN | G_IO_OUT |
- G_IO_PRI | G_IO_ERR |
- G_IO_HUP | G_IO_NVAL,
- connect_watch, sock);
+ priv->watch_src =
+ soup_add_io_watch (priv->async_context,
+ get_iochannel (priv),
+ G_IO_IN | G_IO_OUT |
+ G_IO_PRI | G_IO_ERR |
+ G_IO_HUP | G_IO_NVAL,
+ connect_watch, sock);
return SOUP_STATUS_CONTINUE;
} else {
SOUP_CLOSE_SOCKET (priv->sockfd);
@@ -586,7 +601,8 @@ soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
done:
if (priv->non_blocking) {
- priv->watch = g_idle_add (idle_connect_result, sock);
+ priv->watch_src = soup_add_idle (priv->async_context,
+ idle_connect_result, sock);
return SOUP_STATUS_CONTINUE;
} else if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
return SOUP_STATUS_CANT_CONNECT;
@@ -603,8 +619,8 @@ listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
int sa_len, sockfd;
if (condition & (G_IO_HUP | G_IO_ERR)) {
- g_source_remove (priv->watch);
- priv->watch = 0;
+ g_source_destroy (priv->watch_src);
+ priv->watch_src = NULL;
return FALSE;
}
@@ -616,6 +632,8 @@ listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
new = g_object_new (SOUP_TYPE_SOCKET, NULL);
new_priv = SOUP_SOCKET_GET_PRIVATE (new);
new_priv->sockfd = sockfd;
+ if (priv->async_context)
+ new_priv->async_context = g_main_context_ref (priv->async_context);
new_priv->non_blocking = priv->non_blocking;
new_priv->nodelay = priv->nodelay;
new_priv->is_server = TRUE;
@@ -658,10 +676,11 @@ soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
priv = SOUP_SOCKET_GET_PRIVATE (sock);
- g_return_val_if_fail (priv->is_server, FALSE);
g_return_val_if_fail (priv->sockfd == -1, FALSE);
g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), FALSE);
+ priv->is_server = TRUE;
+
/* @local_addr may have its port set to 0. So we intentionally
* don't store it in priv->local_addr, so that if the
* caller calls soup_socket_get_local_address() later, we'll
@@ -684,9 +703,10 @@ soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
if (listen (priv->sockfd, 10) != 0)
goto cant_listen;
- priv->watch = g_io_add_watch (get_iochannel (priv),
- G_IO_IN | G_IO_ERR | G_IO_HUP,
- listen_watch, sock);
+ priv->watch_src = soup_add_io_watch (priv->async_context,
+ get_iochannel (priv),
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ listen_watch, sock);
return TRUE;
cant_listen:
@@ -755,6 +775,9 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host)
* Creates a connection to @hostname and @port. @callback will be
* called when the connection completes (or fails).
*
+ * Uses the default #GMainContext. If you need to use an alternate
+ * context, use soup_socket_new() and soup_socket_connect() directly.
+ *
* Return value: the new socket (not yet ready for use).
**/
SoupSocket *
@@ -835,6 +858,9 @@ soup_socket_client_new_sync (const char *hostname, guint port,
* address. @callback will be called each time a client connects,
* with a new #SoupSocket.
*
+ * Uses the default #GMainContext. If you need to use an alternate
+ * context, use soup_socket_new() and soup_socket_listen() directly.
+ *
* Returns: a new #SoupSocket, or NULL if there was a failure.
**/
SoupSocket *
@@ -851,7 +877,6 @@ soup_socket_server_new (SoupAddress *local_addr, gpointer ssl_creds,
SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
NULL);
priv = SOUP_SOCKET_GET_PRIVATE (sock);
- priv->is_server = TRUE;
if (!soup_socket_listen (sock, local_addr)) {
g_object_unref (sock);
return NULL;
@@ -1007,7 +1032,7 @@ socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
SoupSocket *sock = user_data;
SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
- priv->read_tag = 0;
+ priv->read_src = NULL;
if (cond & (G_IO_ERR | G_IO_HUP))
soup_socket_disconnect (sock);
@@ -1049,11 +1074,12 @@ read_from_network (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
if (*nread > 0)
return SOUP_SOCKET_OK;
- if (!priv->read_tag) {
- priv->read_tag =
- g_io_add_watch (priv->iochannel,
- cond | G_IO_HUP | G_IO_ERR,
- socket_read_watch, sock);
+ if (!priv->read_src) {
+ priv->read_src =
+ soup_add_io_watch (priv->async_context,
+ priv->iochannel,
+ cond | G_IO_HUP | G_IO_ERR,
+ socket_read_watch, sock);
}
return SOUP_SOCKET_WOULD_BLOCK;
@@ -1210,7 +1236,7 @@ socket_write_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
SoupSocket *sock = user_data;
SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
- priv->write_tag = 0;
+ priv->write_src = NULL;
if (cond & (G_IO_ERR | G_IO_HUP))
soup_socket_disconnect (sock);
@@ -1262,7 +1288,7 @@ soup_socket_write (SoupSocket *sock, gconstpointer buffer,
g_mutex_unlock (priv->iolock);
return SOUP_SOCKET_EOF;
}
- if (priv->write_tag) {
+ if (priv->write_src) {
g_mutex_unlock (priv->iolock);
return SOUP_SOCKET_WOULD_BLOCK;
}
@@ -1298,10 +1324,11 @@ soup_socket_write (SoupSocket *sock, gconstpointer buffer,
return SOUP_SOCKET_OK;
}
- priv->write_tag =
- g_io_add_watch (priv->iochannel,
- cond | G_IO_HUP | G_IO_ERR,
- socket_write_watch, sock);
+ priv->write_src =
+ soup_add_io_watch (priv->async_context,
+ priv->iochannel,
+ cond | G_IO_HUP | G_IO_ERR,
+ socket_write_watch, sock);
g_mutex_unlock (priv->iolock);
return SOUP_SOCKET_WOULD_BLOCK;
}
diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h
index ba7ccae9..0f95dc6e 100644
--- a/libsoup/soup-socket.h
+++ b/libsoup/soup-socket.h
@@ -38,6 +38,7 @@ typedef struct {
#define SOUP_SOCKET_FLAG_CLOEXEC "cloexec"
#define SOUP_SOCKET_IS_SERVER "is-server"
#define SOUP_SOCKET_SSL_CREDENTIALS "ssl-creds"
+#define SOUP_SOCKET_ASYNC_CONTEXT "async-context"
/**
* SoupSocketCallback: