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