From: Dan Winship Date: Thu, 10 Nov 2005 16:48:42 +0000 (+0000) Subject: bump version to 2.2.90. This will not be officially released, but once X-Git-Tag: LIBSOUP_2_2_90_NOT_A_REAL_RELEASE~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9781c6572877b6a2b83661073cf7932e4d54566b;p=platform%2Fupstream%2Flibsoup.git 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. --- diff --git a/ChangeLog b/ChangeLog index 6c14b9c..1a921f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2005-11-10 Dan Winship + + * 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 * docs/reference/libsoup-docs.sgml: tell it to generate an index diff --git a/configure.in b/configure.in index 61d759e..3db8069 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 5302768..0169e13 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 0c191b9..5bfb6aa 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 b06d350..7e59f16 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 500caad..7f19d5d 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 0962813..0398abe 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 22f6205..f64d7d3 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 40f7fad..c530a15 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 e9d3266..6381939 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 cdafd96..b19f783 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 1bd9869..a958af9 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 ba7ccae..0f95dc6 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: