/* -*- 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 . */ #include #include #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; }