summaryrefslogtreecommitdiff
path: root/libsoup/soup-socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsoup/soup-socket.c')
-rw-r--r--libsoup/soup-socket.c113
1 files changed, 70 insertions, 43 deletions
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;
}