Looks good, ACK. On 02/12/2012 07:04 PM, Marc-André Lureau wrote:
Until now, the BIO object used by openssl to read& write was using the socket fd directly. But the mainloop integration is done with GSocket.On Windows, the read/write events are cleared after g_socket_send()/receive() with private function _win32_unset_event_mask. If the glib functions aren't cleared, glib source will keep notifying of data available in or out. On Windows, this causes a busy loop when doing SSL_read() for example (glib POLL_IN data condition is reached and SSL_read() return needs data). Instead, openssl should read/write using GSocket methods. --- gtk/Makefile.am | 2 + gtk/bio-gsocket.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ gtk/bio-gsocket.h | 30 ++++++++++++++ gtk/spice-channel.c | 9 ++-- gtk/spice-client.h | 4 ++ gtk/spice-util.h | 2 +- 6 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 gtk/bio-gsocket.c create mode 100644 gtk/bio-gsocket.h diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 9e6af17..788a145 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -186,6 +186,8 @@ USB_ACL_HELPER_SRCS = endif libspice_client_glib_2_0_la_SOURCES = \ + bio-gsocket.c \ + bio-gsocket.h \ glib-compat.c \ glib-compat.h \ spice-audio.c \ diff --git a/gtk/bio-gsocket.c b/gtk/bio-gsocket.c new file mode 100644 index 0000000..ce94afe --- /dev/null +++ b/gtk/bio-gsocket.c @@ -0,0 +1,111 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see<http://www.gnu.org/licenses/>. +*/ + +#include<string.h> +#include<glib.h> + +#include "spice-util.h" +#include "bio-gsocket.h" + +typedef struct bio_gsocket_method { + BIO_METHOD method; + GSocket *gsocket; +} bio_gsocket_method; + +#define BIO_GET_GSOCKET(bio) (((bio_gsocket_method*)bio->method)->gsocket) + +static int bio_gsocket_bwrite(BIO *bio, const char *in, int inl) +{ + int ret; + GError *error = NULL; + + ret = g_socket_send(BIO_GET_GSOCKET(bio), + in, inl, NULL,&error); + BIO_clear_retry_flags(bio); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + BIO_set_retry_write(bio); + if (error != NULL) { + g_warning("%s", error->message); + g_clear_error(&error); + } + + return ret; +} + +static int bio_gsocket_bread(BIO *bio, char *out, int outl) +{ + int ret; + GError *error = NULL; + + ret = g_socket_receive(BIO_GET_GSOCKET(bio), + out, outl, NULL,&error); + BIO_clear_retry_flags(bio); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + BIO_set_retry_read(bio); + else if (error != NULL) { + g_warning("%s", error->message); + g_clear_error(&error); + } + + return ret; +} + +static int bio_gsocket_destroy(BIO *bio) +{ + if (bio == NULL || bio->method == NULL) + return 0; + + SPICE_DEBUG("bio gsocket destroy"); + g_free(bio->method); + bio->method = NULL;; + + return 1; +} + +static int bio_gsocket_bputs(BIO *bio, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = bio_gsocket_bwrite(bio, str, n); + + return ret; +} + +G_GNUC_INTERNAL +BIO* bio_new_gsocket(GSocket *gsocket) +{ + BIO *bio = BIO_new_socket(g_socket_get_fd(gsocket), BIO_NOCLOSE); + + bio_gsocket_method *bio_method = g_new(bio_gsocket_method, 1); + bio_method->method = *bio->method; + bio_method->gsocket = gsocket; + + bio->method->destroy(bio); + bio->method = (BIO_METHOD*)bio_method; + + bio->method->bwrite = bio_gsocket_bwrite; + bio->method->bread = bio_gsocket_bread; + bio->method->bputs = bio_gsocket_bputs; + bio->method->destroy = bio_gsocket_destroy; + + return bio; +} + diff --git a/gtk/bio-gsocket.h b/gtk/bio-gsocket.h new file mode 100644 index 0000000..7ee5e64 --- /dev/null +++ b/gtk/bio-gsocket.h @@ -0,0 +1,30 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see<http://www.gnu.org/licenses/>. +*/ +#ifndef BIO_GSOCKET_H_ +# define BIO_GSOCKET_H_ + +#include<openssl/bio.h> +#include<gio/gio.h> + +G_BEGIN_DECLS + +BIO* bio_new_gsocket(GSocket *gsocket); + +G_END_DECLS + +#endif /* !BIO_GSOCKET_H_ */ diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c index de60363..afcee98 100644 --- a/gtk/spice-channel.c +++ b/gtk/spice-channel.c @@ -21,6 +21,7 @@ #include "spice-channel-priv.h" #include "spice-session-priv.h" #include "spice-marshal.h" +#include "bio-gsocket.h" #include<openssl/rsa.h> #include<openssl/evp.h> @@ -2156,13 +2157,11 @@ reconnect: g_critical("SSL_new failed"); goto cleanup; } - rc = SSL_set_fd(c->ssl, g_socket_get_fd(c->sock)); - if (rc<= 0) { - g_critical("SSL_set_fd failed"); - goto cleanup; - } + BIO *bio = bio_new_gsocket(c->sock); + SSL_set_bio(c->ssl, bio, bio); + { guint8 *pubkey; guint pubkey_len; diff --git a/gtk/spice-client.h b/gtk/spice-client.h index e77c970..2d7c622 100644 --- a/gtk/spice-client.h +++ b/gtk/spice-client.h @@ -45,6 +45,8 @@ #include "usb-device-manager.h" #include "spice-audio.h" +G_BEGIN_DECLS + #define SPICE_CLIENT_ERROR spice_client_error_quark() /** @@ -60,4 +62,6 @@ typedef enum GQuark spice_client_error_quark(void); +G_END_DECLS + #endif /* __SPICE_CLIENT_CLIENT_H__ */ diff --git a/gtk/spice-util.h b/gtk/spice-util.h index 5029bc1..aace4b6 100644 --- a/gtk/spice-util.h +++ b/gtk/spice-util.h @@ -18,7 +18,7 @@ #ifndef SPICE_UTIL_H #define SPICE_UTIL_H -#include<glib.h> +#include<glib-object.h> G_BEGIN_DECLS
_______________________________________________ Spice-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/spice-devel
