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