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_socket_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 int flags, 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 */ 576 static 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 618 static 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 int flags, 624 Error **errp) 625 { 626 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 627 ssize_t done = 0; 628 ssize_t i; 629 630 for (i = 0; i < niov; i++) { 631 ssize_t ret; 632 retry: 633 ret = send(sioc->fd, 634 iov[i].iov_base, 635 iov[i].iov_len, 636 0); 637 if (ret < 0) { 638 if (errno == EAGAIN) { 639 if (done) { 640 return done; 641 } else { 642 return QIO_CHANNEL_ERR_BLOCK; 643 } 644 } else if (errno == EINTR) { 645 goto retry; 646 } else { 647 error_setg_errno(errp, errno, 648 "Unable to write to socket"); 649 return -1; 650 } 651 } 652 done += ret; 653 if (ret < iov[i].iov_len) { 654 return done; 655 } 656 } 657 658 return done; 659 } 660 #endif /* WIN32 */ 661 662 static int 663 qio_channel_socket_set_blocking(QIOChannel *ioc, 664 bool enabled, 665 Error **errp) 666 { 667 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 668 669 if (enabled) { 670 qemu_socket_set_block(sioc->fd); 671 } else { 672 qemu_socket_set_nonblock(sioc->fd); 673 } 674 return 0; 675 } 676 677 678 static void 679 qio_channel_socket_set_delay(QIOChannel *ioc, 680 bool enabled) 681 { 682 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 683 int v = enabled ? 0 : 1; 684 685 setsockopt(sioc->fd, 686 IPPROTO_TCP, TCP_NODELAY, 687 &v, sizeof(v)); 688 } 689 690 691 static void 692 qio_channel_socket_set_cork(QIOChannel *ioc, 693 bool enabled) 694 { 695 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 696 int v = enabled ? 1 : 0; 697 698 socket_set_cork(sioc->fd, v); 699 } 700 701 702 static int 703 qio_channel_socket_close(QIOChannel *ioc, 704 Error **errp) 705 { 706 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 707 int rc = 0; 708 Error *err = NULL; 709 710 if (sioc->fd != -1) { 711 #ifdef WIN32 712 WSAEventSelect(sioc->fd, NULL, 0); 713 #endif 714 if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) { 715 socket_listen_cleanup(sioc->fd, errp); 716 } 717 718 if (closesocket(sioc->fd) < 0) { 719 sioc->fd = -1; 720 error_setg_errno(&err, errno, "Unable to close socket"); 721 error_propagate(errp, err); 722 return -1; 723 } 724 sioc->fd = -1; 725 } 726 return rc; 727 } 728 729 static int 730 qio_channel_socket_shutdown(QIOChannel *ioc, 731 QIOChannelShutdown how, 732 Error **errp) 733 { 734 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 735 int sockhow; 736 737 switch (how) { 738 case QIO_CHANNEL_SHUTDOWN_READ: 739 sockhow = SHUT_RD; 740 break; 741 case QIO_CHANNEL_SHUTDOWN_WRITE: 742 sockhow = SHUT_WR; 743 break; 744 case QIO_CHANNEL_SHUTDOWN_BOTH: 745 default: 746 sockhow = SHUT_RDWR; 747 break; 748 } 749 750 if (shutdown(sioc->fd, sockhow) < 0) { 751 error_setg_errno(errp, errno, 752 "Unable to shutdown socket"); 753 return -1; 754 } 755 return 0; 756 } 757 758 static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc, 759 AioContext *ctx, 760 IOHandler *io_read, 761 IOHandler *io_write, 762 void *opaque) 763 { 764 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 765 aio_set_fd_handler(ctx, sioc->fd, false, 766 io_read, io_write, NULL, NULL, opaque); 767 } 768 769 static GSource *qio_channel_socket_create_watch(QIOChannel *ioc, 770 GIOCondition condition) 771 { 772 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); 773 return qio_channel_create_socket_watch(ioc, 774 sioc->fd, 775 condition); 776 } 777 778 static void qio_channel_socket_class_init(ObjectClass *klass, 779 void *class_data G_GNUC_UNUSED) 780 { 781 QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); 782 783 ioc_klass->io_writev = qio_channel_socket_writev; 784 ioc_klass->io_readv = qio_channel_socket_readv; 785 ioc_klass->io_set_blocking = qio_channel_socket_set_blocking; 786 ioc_klass->io_close = qio_channel_socket_close; 787 ioc_klass->io_shutdown = qio_channel_socket_shutdown; 788 ioc_klass->io_set_cork = qio_channel_socket_set_cork; 789 ioc_klass->io_set_delay = qio_channel_socket_set_delay; 790 ioc_klass->io_create_watch = qio_channel_socket_create_watch; 791 ioc_klass->io_set_aio_fd_handler = qio_channel_socket_set_aio_fd_handler; 792 } 793 794 static const TypeInfo qio_channel_socket_info = { 795 .parent = TYPE_QIO_CHANNEL, 796 .name = TYPE_QIO_CHANNEL_SOCKET, 797 .instance_size = sizeof(QIOChannelSocket), 798 .instance_init = qio_channel_socket_init, 799 .instance_finalize = qio_channel_socket_finalize, 800 .class_init = qio_channel_socket_class_init, 801 }; 802 803 static void qio_channel_socket_register_types(void) 804 { 805 type_register_static(&qio_channel_socket_info); 806 } 807 808 type_init(qio_channel_socket_register_types); 809