qemu/io/channel-socket.c
<<
>>
Prefs
   1/*
   2 * QEMU I/O channels sockets driver
   3 *
   4 * Copyright (c) 2015 Red Hat, Inc.
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "qemu/osdep.h"
  21#include "qemu-common.h"
  22#include "qapi/error.h"
  23#include "qapi/qapi-visit-sockets.h"
  24#include "qemu/module.h"
  25#include "io/channel-socket.h"
  26#include "io/channel-watch.h"
  27#include "trace.h"
  28#include "qapi/clone-visitor.h"
  29
  30#define SOCKET_MAX_FDS 16
  31
  32SocketAddress *
  33qio_channel_socket_get_local_address(QIOChannelSocket *ioc,
  34                                     Error **errp)
  35{
  36    return socket_sockaddr_to_address(&ioc->localAddr,
  37                                      ioc->localAddrLen,
  38                                      errp);
  39}
  40
  41SocketAddress *
  42qio_channel_socket_get_remote_address(QIOChannelSocket *ioc,
  43                                      Error **errp)
  44{
  45    return socket_sockaddr_to_address(&ioc->remoteAddr,
  46                                      ioc->remoteAddrLen,
  47                                      errp);
  48}
  49
  50QIOChannelSocket *
  51qio_channel_socket_new(void)
  52{
  53    QIOChannelSocket *sioc;
  54    QIOChannel *ioc;
  55
  56    sioc = QIO_CHANNEL_SOCKET(object_new(TYPE_QIO_CHANNEL_SOCKET));
  57    sioc->fd = -1;
  58
  59    ioc = QIO_CHANNEL(sioc);
  60    qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
  61
  62#ifdef WIN32
  63    ioc->event = CreateEvent(NULL, FALSE, FALSE, NULL);
  64#endif
  65
  66    trace_qio_channel_socket_new(sioc);
  67
  68    return sioc;
  69}
  70
  71
  72static int
  73qio_channel_socket_set_fd(QIOChannelSocket *sioc,
  74                          int fd,
  75                          Error **errp)
  76{
  77    if (sioc->fd != -1) {
  78        error_setg(errp, "Socket is already open");
  79        return -1;
  80    }
  81
  82    sioc->fd = fd;
  83    sioc->remoteAddrLen = sizeof(sioc->remoteAddr);
  84    sioc->localAddrLen = sizeof(sioc->localAddr);
  85
  86
  87    if (getpeername(fd, (struct sockaddr *)&sioc->remoteAddr,
  88                    &sioc->remoteAddrLen) < 0) {
  89        if (errno == ENOTCONN) {
  90            memset(&sioc->remoteAddr, 0, sizeof(sioc->remoteAddr));
  91            sioc->remoteAddrLen = sizeof(sioc->remoteAddr);
  92        } else {
  93            error_setg_errno(errp, errno,
  94                             "Unable to query remote socket address");
  95            goto error;
  96        }
  97    }
  98
  99    if (getsockname(fd, (struct sockaddr *)&sioc->localAddr,
 100                    &sioc->localAddrLen) < 0) {
 101        error_setg_errno(errp, errno,
 102                         "Unable to query local socket address");
 103        goto error;
 104    }
 105
 106#ifndef WIN32
 107    if (sioc->localAddr.ss_family == AF_UNIX) {
 108        QIOChannel *ioc = QIO_CHANNEL(sioc);
 109        qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS);
 110    }
 111#endif /* WIN32 */
 112
 113    return 0;
 114
 115 error:
 116    sioc->fd = -1; /* Let the caller close FD on failure */
 117    return -1;
 118}
 119
 120QIOChannelSocket *
 121qio_channel_socket_new_fd(int fd,
 122                          Error **errp)
 123{
 124    QIOChannelSocket *ioc;
 125
 126    ioc = qio_channel_socket_new();
 127    if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) {
 128        object_unref(OBJECT(ioc));
 129        return NULL;
 130    }
 131
 132    trace_qio_channel_socket_new_fd(ioc, fd);
 133
 134    return ioc;
 135}
 136
 137
 138int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
 139                                    SocketAddress *addr,
 140                                    Error **errp)
 141{
 142    int fd;
 143
 144    trace_qio_channel_socket_connect_sync(ioc, addr);
 145    fd = socket_connect(addr, errp);
 146    if (fd < 0) {
 147        trace_qio_channel_socket_connect_fail(ioc);
 148        return -1;
 149    }
 150
 151    trace_qio_channel_socket_connect_complete(ioc, fd);
 152    if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) {
 153        close(fd);
 154        return -1;
 155    }
 156
 157    return 0;
 158}
 159
 160
 161static void qio_channel_socket_connect_worker(QIOTask *task,
 162                                              gpointer opaque)
 163{
 164    QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
 165    SocketAddress *addr = opaque;
 166    Error *err = NULL;
 167
 168    qio_channel_socket_connect_sync(ioc, addr, &err);
 169
 170    qio_task_set_error(task, err);
 171}
 172
 173
 174void qio_channel_socket_connect_async(QIOChannelSocket *ioc,
 175                                      SocketAddress *addr,
 176                                      QIOTaskFunc callback,
 177                                      gpointer opaque,
 178                                      GDestroyNotify destroy,
 179                                      GMainContext *context)
 180{
 181    QIOTask *task = qio_task_new(
 182        OBJECT(ioc), callback, opaque, destroy);
 183    SocketAddress *addrCopy;
 184
 185    addrCopy = QAPI_CLONE(SocketAddress, addr);
 186
 187    /* socket_connect() does a non-blocking connect(), but it
 188     * still blocks in DNS lookups, so we must use a thread */
 189    trace_qio_channel_socket_connect_async(ioc, addr);
 190    qio_task_run_in_thread(task,
 191                           qio_channel_socket_connect_worker,
 192                           addrCopy,
 193                           (GDestroyNotify)qapi_free_SocketAddress,
 194                           context);
 195}
 196
 197
 198int qio_channel_socket_listen_sync(QIOChannelSocket *ioc,
 199                                   SocketAddress *addr,
 200                                   int num,
 201                                   Error **errp)
 202{
 203    int fd;
 204
 205    trace_qio_channel_socket_listen_sync(ioc, addr, num);
 206    fd = socket_listen(addr, num, errp);
 207    if (fd < 0) {
 208        trace_qio_channel_socket_listen_fail(ioc);
 209        return -1;
 210    }
 211
 212    trace_qio_channel_socket_listen_complete(ioc, fd);
 213    if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) {
 214        close(fd);
 215        return -1;
 216    }
 217    qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_LISTEN);
 218
 219    return 0;
 220}
 221
 222
 223struct QIOChannelListenWorkerData {
 224    SocketAddress *addr;
 225    int num; /* amount of expected connections */
 226};
 227
 228static void qio_channel_listen_worker_free(gpointer opaque)
 229{
 230    struct QIOChannelListenWorkerData *data = opaque;
 231
 232    qapi_free_SocketAddress(data->addr);
 233    g_free(data);
 234}
 235
 236static void qio_channel_socket_listen_worker(QIOTask *task,
 237                                             gpointer opaque)
 238{
 239    QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
 240    struct QIOChannelListenWorkerData *data = opaque;
 241    Error *err = NULL;
 242
 243    qio_channel_socket_listen_sync(ioc, data->addr, data->num, &err);
 244
 245    qio_task_set_error(task, err);
 246}
 247
 248
 249void qio_channel_socket_listen_async(QIOChannelSocket *ioc,
 250                                     SocketAddress *addr,
 251                                     int num,
 252                                     QIOTaskFunc callback,
 253                                     gpointer opaque,
 254                                     GDestroyNotify destroy,
 255                                     GMainContext *context)
 256{
 257    QIOTask *task = qio_task_new(
 258        OBJECT(ioc), callback, opaque, destroy);
 259    struct QIOChannelListenWorkerData *data;
 260
 261    data = g_new0(struct QIOChannelListenWorkerData, 1);
 262    data->addr = QAPI_CLONE(SocketAddress, addr);
 263    data->num = num;
 264
 265    /* socket_listen() blocks in DNS lookups, so we must use a thread */
 266    trace_qio_channel_socket_listen_async(ioc, addr, num);
 267    qio_task_run_in_thread(task,
 268                           qio_channel_socket_listen_worker,
 269                           data,
 270                           qio_channel_listen_worker_free,
 271                           context);
 272}
 273
 274
 275int qio_channel_socket_dgram_sync(QIOChannelSocket *ioc,
 276                                  SocketAddress *localAddr,
 277                                  SocketAddress *remoteAddr,
 278                                  Error **errp)
 279{
 280    int fd;
 281
 282    trace_qio_channel_socket_dgram_sync(ioc, localAddr, remoteAddr);
 283    fd = socket_dgram(remoteAddr, localAddr, errp);
 284    if (fd < 0) {
 285        trace_qio_channel_socket_dgram_fail(ioc);
 286        return -1;
 287    }
 288
 289    trace_qio_channel_socket_dgram_complete(ioc, fd);
 290    if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) {
 291        close(fd);
 292        return -1;
 293    }
 294
 295    return 0;
 296}
 297
 298
 299struct QIOChannelSocketDGramWorkerData {
 300    SocketAddress *localAddr;
 301    SocketAddress *remoteAddr;
 302};
 303
 304
 305static void qio_channel_socket_dgram_worker_free(gpointer opaque)
 306{
 307    struct QIOChannelSocketDGramWorkerData *data = opaque;
 308    qapi_free_SocketAddress(data->localAddr);
 309    qapi_free_SocketAddress(data->remoteAddr);
 310    g_free(data);
 311}
 312
 313static void qio_channel_socket_dgram_worker(QIOTask *task,
 314                                            gpointer opaque)
 315{
 316    QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
 317    struct QIOChannelSocketDGramWorkerData *data = opaque;
 318    Error *err = NULL;
 319
 320    /* socket_dgram() blocks in DNS lookups, so we must use a thread */
 321    qio_channel_socket_dgram_sync(ioc, data->localAddr,
 322                                  data->remoteAddr, &err);
 323
 324    qio_task_set_error(task, err);
 325}
 326
 327
 328void qio_channel_socket_dgram_async(QIOChannelSocket *ioc,
 329                                    SocketAddress *localAddr,
 330                                    SocketAddress *remoteAddr,
 331                                    QIOTaskFunc callback,
 332                                    gpointer opaque,
 333                                    GDestroyNotify destroy,
 334                                    GMainContext *context)
 335{
 336    QIOTask *task = qio_task_new(
 337        OBJECT(ioc), callback, opaque, destroy);
 338    struct QIOChannelSocketDGramWorkerData *data = g_new0(
 339        struct QIOChannelSocketDGramWorkerData, 1);
 340
 341    data->localAddr = QAPI_CLONE(SocketAddress, localAddr);
 342    data->remoteAddr = QAPI_CLONE(SocketAddress, remoteAddr);
 343
 344    trace_qio_channel_socket_dgram_async(ioc, localAddr, remoteAddr);
 345    qio_task_run_in_thread(task,
 346                           qio_channel_socket_dgram_worker,
 347                           data,
 348                           qio_channel_socket_dgram_worker_free,
 349                           context);
 350}
 351
 352
 353QIOChannelSocket *
 354qio_channel_socket_accept(QIOChannelSocket *ioc,
 355                          Error **errp)
 356{
 357    QIOChannelSocket *cioc;
 358
 359    cioc = qio_channel_socket_new();
 360    cioc->remoteAddrLen = sizeof(ioc->remoteAddr);
 361    cioc->localAddrLen = sizeof(ioc->localAddr);
 362
 363 retry:
 364    trace_qio_channel_socket_accept(ioc);
 365    cioc->fd = qemu_accept(ioc->fd, (struct sockaddr *)&cioc->remoteAddr,
 366                           &cioc->remoteAddrLen);
 367    if (cioc->fd < 0) {
 368        if (errno == EINTR) {
 369            goto retry;
 370        }
 371        error_setg_errno(errp, errno, "Unable to accept connection");
 372        trace_qio_channel_socket_accept_fail(ioc);
 373        goto error;
 374    }
 375
 376    if (getsockname(cioc->fd, (struct sockaddr *)&cioc->localAddr,
 377                    &cioc->localAddrLen) < 0) {
 378        error_setg_errno(errp, errno,
 379                         "Unable to query local socket address");
 380        goto error;
 381    }
 382
 383#ifndef WIN32
 384    if (cioc->localAddr.ss_family == AF_UNIX) {
 385        QIOChannel *ioc_local = QIO_CHANNEL(cioc);
 386        qio_channel_set_feature(ioc_local, QIO_CHANNEL_FEATURE_FD_PASS);
 387    }
 388#endif /* WIN32 */
 389
 390    trace_qio_channel_socket_accept_complete(ioc, cioc, cioc->fd);
 391    return cioc;
 392
 393 error:
 394    object_unref(OBJECT(cioc));
 395    return NULL;
 396}
 397
 398static void qio_channel_socket_init(Object *obj)
 399{
 400    QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
 401    ioc->fd = -1;
 402}
 403
 404static void qio_channel_socket_finalize(Object *obj)
 405{
 406    QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
 407
 408    if (ioc->fd != -1) {
 409        QIOChannel *ioc_local = QIO_CHANNEL(ioc);
 410        if (qio_channel_has_feature(ioc_local, QIO_CHANNEL_FEATURE_LISTEN)) {
 411            Error *err = NULL;
 412
 413            socket_listen_cleanup(ioc->fd, &err);
 414            if (err) {
 415                error_report_err(err);
 416                err = NULL;
 417            }
 418        }
 419#ifdef WIN32
 420        WSAEventSelect(ioc->fd, NULL, 0);
 421#endif
 422        closesocket(ioc->fd);
 423        ioc->fd = -1;
 424    }
 425}
 426
 427
 428#ifndef WIN32
 429static void qio_channel_socket_copy_fds(struct msghdr *msg,
 430                                        int **fds, size_t *nfds)
 431{
 432    struct cmsghdr *cmsg;
 433
 434    *nfds = 0;
 435    *fds = NULL;
 436
 437    for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
 438        int fd_size, i;
 439        int gotfds;
 440
 441        if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) ||
 442            cmsg->cmsg_level != SOL_SOCKET ||
 443            cmsg->cmsg_type != SCM_RIGHTS) {
 444            continue;
 445        }
 446
 447        fd_size = cmsg->cmsg_len - CMSG_LEN(0);
 448
 449        if (!fd_size) {
 450            continue;
 451        }
 452
 453        gotfds = fd_size / sizeof(int);
 454        *fds = g_renew(int, *fds, *nfds + gotfds);
 455        memcpy(*fds + *nfds, CMSG_DATA(cmsg), fd_size);
 456
 457        for (i = 0; i < gotfds; i++) {
 458            int fd = (*fds)[*nfds + i];
 459            if (fd < 0) {
 460                continue;
 461            }
 462
 463            /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
 464            qemu_set_block(fd);
 465
 466#ifndef MSG_CMSG_CLOEXEC
 467            qemu_set_cloexec(fd);
 468#endif
 469        }
 470        *nfds += gotfds;
 471    }
 472}
 473
 474
 475static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
 476                                        const struct iovec *iov,
 477                                        size_t niov,
 478                                        int **fds,
 479                                        size_t *nfds,
 480                                        Error **errp)
 481{
 482    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 483    ssize_t ret;
 484    struct msghdr msg = { NULL, };
 485    char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
 486    int sflags = 0;
 487
 488    memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
 489
 490#ifdef MSG_CMSG_CLOEXEC
 491    sflags |= MSG_CMSG_CLOEXEC;
 492#endif
 493
 494    msg.msg_iov = (struct iovec *)iov;
 495    msg.msg_iovlen = niov;
 496    if (fds && nfds) {
 497        msg.msg_control = control;
 498        msg.msg_controllen = sizeof(control);
 499    }
 500
 501 retry:
 502    ret = recvmsg(sioc->fd, &msg, sflags);
 503    if (ret < 0) {
 504        if (errno == EAGAIN) {
 505            return QIO_CHANNEL_ERR_BLOCK;
 506        }
 507        if (errno == EINTR) {
 508            goto retry;
 509        }
 510
 511        error_setg_errno(errp, errno,
 512                         "Unable to read from socket");
 513        return -1;
 514    }
 515
 516    if (fds && nfds) {
 517        qio_channel_socket_copy_fds(&msg, fds, nfds);
 518    }
 519
 520    return ret;
 521}
 522
 523static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
 524                                         const struct iovec *iov,
 525                                         size_t niov,
 526                                         int *fds,
 527                                         size_t nfds,
 528                                         Error **errp)
 529{
 530    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 531    ssize_t ret;
 532    struct msghdr msg = { NULL, };
 533    char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
 534    size_t fdsize = sizeof(int) * nfds;
 535    struct cmsghdr *cmsg;
 536
 537    memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
 538
 539    msg.msg_iov = (struct iovec *)iov;
 540    msg.msg_iovlen = niov;
 541
 542    if (nfds) {
 543        if (nfds > SOCKET_MAX_FDS) {
 544            error_setg_errno(errp, EINVAL,
 545                             "Only %d FDs can be sent, got %zu",
 546                             SOCKET_MAX_FDS, nfds);
 547            return -1;
 548        }
 549
 550        msg.msg_control = control;
 551        msg.msg_controllen = CMSG_SPACE(sizeof(int) * nfds);
 552
 553        cmsg = CMSG_FIRSTHDR(&msg);
 554        cmsg->cmsg_len = CMSG_LEN(fdsize);
 555        cmsg->cmsg_level = SOL_SOCKET;
 556        cmsg->cmsg_type = SCM_RIGHTS;
 557        memcpy(CMSG_DATA(cmsg), fds, fdsize);
 558    }
 559
 560 retry:
 561    ret = sendmsg(sioc->fd, &msg, 0);
 562    if (ret <= 0) {
 563        if (errno == EAGAIN) {
 564            return QIO_CHANNEL_ERR_BLOCK;
 565        }
 566        if (errno == EINTR) {
 567            goto retry;
 568        }
 569        error_setg_errno(errp, errno,
 570                         "Unable to write to socket");
 571        return -1;
 572    }
 573    return ret;
 574}
 575#else /* WIN32 */
 576static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
 577                                        const struct iovec *iov,
 578                                        size_t niov,
 579                                        int **fds,
 580                                        size_t *nfds,
 581                                        Error **errp)
 582{
 583    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 584    ssize_t done = 0;
 585    ssize_t i;
 586
 587    for (i = 0; i < niov; i++) {
 588        ssize_t ret;
 589    retry:
 590        ret = recv(sioc->fd,
 591                   iov[i].iov_base,
 592                   iov[i].iov_len,
 593                   0);
 594        if (ret < 0) {
 595            if (errno == EAGAIN) {
 596                if (done) {
 597                    return done;
 598                } else {
 599                    return QIO_CHANNEL_ERR_BLOCK;
 600                }
 601            } else if (errno == EINTR) {
 602                goto retry;
 603            } else {
 604                error_setg_errno(errp, errno,
 605                                 "Unable to read from socket");
 606                return -1;
 607            }
 608        }
 609        done += ret;
 610        if (ret < iov[i].iov_len) {
 611            return done;
 612        }
 613    }
 614
 615    return done;
 616}
 617
 618static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
 619                                         const struct iovec *iov,
 620                                         size_t niov,
 621                                         int *fds,
 622                                         size_t nfds,
 623                                         Error **errp)
 624{
 625    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 626    ssize_t done = 0;
 627    ssize_t i;
 628
 629    for (i = 0; i < niov; i++) {
 630        ssize_t ret;
 631    retry:
 632        ret = send(sioc->fd,
 633                   iov[i].iov_base,
 634                   iov[i].iov_len,
 635                   0);
 636        if (ret < 0) {
 637            if (errno == EAGAIN) {
 638                if (done) {
 639                    return done;
 640                } else {
 641                    return QIO_CHANNEL_ERR_BLOCK;
 642                }
 643            } else if (errno == EINTR) {
 644                goto retry;
 645            } else {
 646                error_setg_errno(errp, errno,
 647                                 "Unable to write to socket");
 648                return -1;
 649            }
 650        }
 651        done += ret;
 652        if (ret < iov[i].iov_len) {
 653            return done;
 654        }
 655    }
 656
 657    return done;
 658}
 659#endif /* WIN32 */
 660
 661static int
 662qio_channel_socket_set_blocking(QIOChannel *ioc,
 663                                bool enabled,
 664                                Error **errp)
 665{
 666    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 667
 668    if (enabled) {
 669        qemu_set_block(sioc->fd);
 670    } else {
 671        qemu_set_nonblock(sioc->fd);
 672    }
 673    return 0;
 674}
 675
 676
 677static void
 678qio_channel_socket_set_delay(QIOChannel *ioc,
 679                             bool enabled)
 680{
 681    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 682    int v = enabled ? 0 : 1;
 683
 684    qemu_setsockopt(sioc->fd,
 685                    IPPROTO_TCP, TCP_NODELAY,
 686                    &v, sizeof(v));
 687}
 688
 689
 690static void
 691qio_channel_socket_set_cork(QIOChannel *ioc,
 692                            bool enabled)
 693{
 694    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 695    int v = enabled ? 1 : 0;
 696
 697    socket_set_cork(sioc->fd, v);
 698}
 699
 700
 701static int
 702qio_channel_socket_close(QIOChannel *ioc,
 703                         Error **errp)
 704{
 705    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 706    int rc = 0;
 707
 708    if (sioc->fd != -1) {
 709#ifdef WIN32
 710        WSAEventSelect(sioc->fd, NULL, 0);
 711#endif
 712        if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) {
 713            socket_listen_cleanup(sioc->fd, errp);
 714        }
 715
 716        if (closesocket(sioc->fd) < 0) {
 717            sioc->fd = -1;
 718            error_setg_errno(errp, errno,
 719                             "Unable to close socket");
 720            return -1;
 721        }
 722        sioc->fd = -1;
 723    }
 724    return rc;
 725}
 726
 727static int
 728qio_channel_socket_shutdown(QIOChannel *ioc,
 729                            QIOChannelShutdown how,
 730                            Error **errp)
 731{
 732    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 733    int sockhow;
 734
 735    switch (how) {
 736    case QIO_CHANNEL_SHUTDOWN_READ:
 737        sockhow = SHUT_RD;
 738        break;
 739    case QIO_CHANNEL_SHUTDOWN_WRITE:
 740        sockhow = SHUT_WR;
 741        break;
 742    case QIO_CHANNEL_SHUTDOWN_BOTH:
 743    default:
 744        sockhow = SHUT_RDWR;
 745        break;
 746    }
 747
 748    if (shutdown(sioc->fd, sockhow) < 0) {
 749        error_setg_errno(errp, errno,
 750                         "Unable to shutdown socket");
 751        return -1;
 752    }
 753    return 0;
 754}
 755
 756static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc,
 757                                                  AioContext *ctx,
 758                                                  IOHandler *io_read,
 759                                                  IOHandler *io_write,
 760                                                  void *opaque)
 761{
 762    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 763    aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, NULL, opaque);
 764}
 765
 766static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
 767                                                GIOCondition condition)
 768{
 769    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
 770    return qio_channel_create_socket_watch(ioc,
 771                                           sioc->fd,
 772                                           condition);
 773}
 774
 775static void qio_channel_socket_class_init(ObjectClass *klass,
 776                                          void *class_data G_GNUC_UNUSED)
 777{
 778    QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
 779
 780    ioc_klass->io_writev = qio_channel_socket_writev;
 781    ioc_klass->io_readv = qio_channel_socket_readv;
 782    ioc_klass->io_set_blocking = qio_channel_socket_set_blocking;
 783    ioc_klass->io_close = qio_channel_socket_close;
 784    ioc_klass->io_shutdown = qio_channel_socket_shutdown;
 785    ioc_klass->io_set_cork = qio_channel_socket_set_cork;
 786    ioc_klass->io_set_delay = qio_channel_socket_set_delay;
 787    ioc_klass->io_create_watch = qio_channel_socket_create_watch;
 788    ioc_klass->io_set_aio_fd_handler = qio_channel_socket_set_aio_fd_handler;
 789}
 790
 791static const TypeInfo qio_channel_socket_info = {
 792    .parent = TYPE_QIO_CHANNEL,
 793    .name = TYPE_QIO_CHANNEL_SOCKET,
 794    .instance_size = sizeof(QIOChannelSocket),
 795    .instance_init = qio_channel_socket_init,
 796    .instance_finalize = qio_channel_socket_finalize,
 797    .class_init = qio_channel_socket_class_init,
 798};
 799
 800static void qio_channel_socket_register_types(void)
 801{
 802    type_register_static(&qio_channel_socket_info);
 803}
 804
 805type_init(qio_channel_socket_register_types);
 806