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