From: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> --- gtk/spice-channel-priv.h | 4 ++- gtk/spice-channel.c | 81 +++++++++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h index 35704ea..00893c3 100644 --- a/gtk/spice-channel-priv.h +++ b/gtk/spice-channel-priv.h @@ -80,8 +80,10 @@ struct _SpiceChannelPrivate { SSL_CTX *ctx; SSL *ssl; SpiceOpenSSLVerify *sslverify; - GSocket *sock; + GSocket *socket; GSocketConnection *conn; + GInputStream *in; + GOutputStream *out; #if HAVE_SASL sasl_conn_t *sasl_conn; diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c index 7bcb0b8..b1e049d 100644 --- a/gtk/spice-channel.c +++ b/gtk/spice-channel.c @@ -763,7 +763,8 @@ static void spice_channel_flush_wire(SpiceChannel *channel, GIOCondition cond; while (offset < datalen) { - int ret; + gssize ret; + GError *error = NULL; if (c->has_error) return; @@ -779,9 +780,12 @@ static void spice_channel_flush_wire(SpiceChannel *channel, ret = -1; } } else { - GError *error = NULL; - ret = g_socket_send(c->sock, ptr+offset, datalen-offset, - NULL, &error); +#if GLIB_CHECK_VERSION(2, 28, 0) + ret = g_pollable_output_stream_write_nonblocking(G_POLLABLE_OUTPUT_STREAM(c->out), + ptr+offset, datalen-offset, NULL, &error); +#else + ret = g_socket_send(c->socket, ptr+offset, datalen-offset, NULL, &error); +#endif if (ret < 0) { if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { cond = G_IO_OUT; @@ -794,7 +798,8 @@ static void spice_channel_flush_wire(SpiceChannel *channel, } if (ret == -1) { if (cond != 0) { - g_coroutine_socket_wait(&c->coroutine, c->sock, cond); + // TODO: should use g_pollable_input/output_stream_create_source() in 2.28 ? + g_coroutine_socket_wait(&c->coroutine, c->socket, cond); continue; } else { CHANNEL_DEBUG(channel, "Closing the channel: spice_channel_flush %d", errno); @@ -888,7 +893,7 @@ static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out) static int spice_channel_read_wire(SpiceChannel *channel, void *data, size_t len) { SpiceChannelPrivate *c = channel->priv; - int ret; + gssize ret; GIOCondition cond; reread: @@ -908,7 +913,13 @@ reread: } } else { GError *error = NULL; - ret = g_socket_receive(c->sock, data, len, NULL, &error); +#if GLIB_CHECK_VERSION(2, 28, 0) + ret = g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(c->in), + data, len, NULL, &error); +#else + ret = g_socket_receive(c->socket, + data, len, NULL, &error); +#endif if (ret < 0) { if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { cond = G_IO_IN; @@ -922,7 +933,8 @@ reread: if (ret == -1) { if (cond != 0) { - g_coroutine_socket_wait(&c->coroutine, c->sock, cond); + // TODO: should use g_pollable_input/output_stream_create_source() ? + g_coroutine_socket_wait(&c->coroutine, c->socket, cond); goto reread; } else { c->has_error = TRUE; @@ -1351,7 +1363,7 @@ static gboolean spice_channel_perform_auth_sasl(SpiceChannel *channel) } /* Get local address in form IPADDR:PORT */ - addr = g_socket_get_local_address(c->sock, NULL); + addr = g_socket_get_local_address(c->socket, NULL); if (!addr) { g_critical("failed to get local address"); goto error; @@ -1363,7 +1375,7 @@ static gboolean spice_channel_perform_auth_sasl(SpiceChannel *channel) g_clear_object(&addr); /* Get remote address in form IPADDR:PORT */ - addr = g_socket_get_remote_address(c->sock, NULL); + addr = g_socket_get_remote_address(c->socket, NULL); if (!addr) { g_critical("failed to get peer address"); goto error; @@ -2062,14 +2074,17 @@ static void spice_channel_iterate_read(SpiceChannel *channel) { SpiceChannelPrivate *c = channel->priv; - g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_IN); + g_coroutine_socket_wait(&c->coroutine, c->socket, G_IO_IN); /* treat all incoming data (block on message completion) */ while (!c->has_error && c->state != SPICE_CHANNEL_STATE_MIGRATING && - g_socket_condition_check(c->sock, G_IO_IN) & G_IO_IN) { - - do +#if GLIB_CHECK_VERSION(2, 28, 0) + g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(c->in)) +#else + g_socket_condition_check(c->sock, G_IO_IN) & G_IO_IN +#endif + ) { do spice_channel_recv_msg(channel, (handler_msg_in)SPICE_CHANNEL_GET_CLASS(channel)->handle_msg, NULL); #if HAVE_SASL @@ -2228,17 +2243,19 @@ static void *spice_channel_coroutine(void *data) goto cleanup; } - if (!(c->sock = g_socket_new_from_fd(c->fd, NULL))) { + if (!(c->socket = g_socket_new_from_fd(c->fd, NULL))) { CHANNEL_DEBUG(channel, "Failed to open socket from fd %d", c->fd); emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_CONNECT); goto cleanup; } - g_socket_set_blocking(c->sock, FALSE); - g_socket_set_keepalive(c->sock, TRUE); + g_socket_set_blocking(c->socket, FALSE); + g_socket_set_keepalive(c->socket, TRUE); + c->conn = g_socket_connection_factory_create_connection(c->socket); goto connected; } + reconnect: c->conn = spice_session_channel_open_host(c->session, channel, &c->tls); if (c->conn == NULL) { @@ -2252,7 +2269,7 @@ reconnect: goto cleanup; } } - c->sock = g_object_ref(g_socket_connection_get_socket(c->conn)); + c->socket = g_object_ref(g_socket_connection_get_socket(c->conn)); c->has_error = FALSE; @@ -2299,7 +2316,11 @@ reconnect: } - BIO *bio = bio_new_gsocket(c->sock); +#if GLIB_CHECK_VERSION(2, 28, 0) + BIO *bio = bio_new_giostream(G_IO_STREAM(c->conn)); +#else + BIO *bio = bio_new_gsocket(c->socket); +#endif SSL_set_bio(c->ssl, bio, bio); { @@ -2318,7 +2339,7 @@ ssl_reconnect: if (rc <= 0) { rc = SSL_get_error(c->ssl, rc); if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) { - g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_OUT|G_IO_ERR|G_IO_HUP); + g_coroutine_socket_wait(&c->coroutine, c->socket, G_IO_OUT|G_IO_ERR|G_IO_HUP); goto ssl_reconnect; } else { g_warning("%s: SSL_connect: %s", @@ -2330,7 +2351,10 @@ ssl_reconnect: } connected: - rc = setsockopt(g_socket_get_fd(c->sock), IPPROTO_TCP, TCP_NODELAY, + c->in = g_io_stream_get_input_stream(G_IO_STREAM(c->conn)); + c->out = g_io_stream_get_output_stream(G_IO_STREAM(c->conn)); + + rc = setsockopt(g_socket_get_fd(c->socket), IPPROTO_TCP, TCP_NODELAY, (const char*)&delay_val, sizeof(delay_val)); if ((rc != 0) #ifdef ENOTSUP @@ -2415,7 +2439,7 @@ static gboolean channel_connect(SpiceChannel *channel) c->state = SPICE_CHANNEL_STATE_CONNECTING; c->xmit_queue_blocked = FALSE; - g_return_val_if_fail(c->sock == NULL, FALSE); + g_return_val_if_fail(c->socket == NULL, FALSE); g_object_ref(G_OBJECT(channel)); /* Unref'd when co-routine exits */ /* we connect in idle, to let previous coroutine exit, if present */ @@ -2503,10 +2527,9 @@ static void channel_reset(SpiceChannel *channel, gboolean migrating) g_object_unref(c->conn); c->conn = NULL; } - if (c->sock) { - g_object_unref(c->sock); - c->sock = NULL; - } + + g_clear_object(&c->socket); + c->fd = -1; free(c->peer_msg); @@ -2722,7 +2745,7 @@ void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap g_return_if_fail(s != NULL); g_return_if_fail(s->session != NULL); - g_return_if_fail(s->sock != NULL); + g_return_if_fail(s->socket != NULL); #define SWAP(Field) ({ \ typeof (c->Field) Field = c->Field; \ @@ -2732,8 +2755,10 @@ void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap /* TODO: split channel in 2 objects: a controller and a swappable state object */ + SWAP(socket); SWAP(conn); - SWAP(sock); + SWAP(in); + SWAP(out); SWAP(ctx); SWAP(ssl); SWAP(sslverify); -- 1.8.4.2 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel