xref: /qemu/io/channel-socket.c (revision 4e2d8bf6)
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 
32 SocketAddress *
33 qio_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 
41 SocketAddress *
42 qio_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 
50 QIOChannelSocket *
51 qio_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 
72 static int
73 qio_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 
120 QIOChannelSocket *
121 qio_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 
138 int 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 
161 static 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 
174 void 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 
198 int 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 
223 static void qio_channel_socket_listen_worker(QIOTask *task,
224                                              gpointer opaque)
225 {
226     QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
227     SocketAddress *addr = opaque;
228     Error *err = NULL;
229 
230     qio_channel_socket_listen_sync(ioc, addr, 1, &err);
231 
232     qio_task_set_error(task, err);
233 }
234 
235 
236 void qio_channel_socket_listen_async(QIOChannelSocket *ioc,
237                                      SocketAddress *addr,
238                                      QIOTaskFunc callback,
239                                      gpointer opaque,
240                                      GDestroyNotify destroy,
241                                      GMainContext *context)
242 {
243     QIOTask *task = qio_task_new(
244         OBJECT(ioc), callback, opaque, destroy);
245     SocketAddress *addrCopy;
246 
247     addrCopy = QAPI_CLONE(SocketAddress, 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                            context);
256 }
257 
258 
259 int qio_channel_socket_dgram_sync(QIOChannelSocket *ioc,
260                                   SocketAddress *localAddr,
261                                   SocketAddress *remoteAddr,
262                                   Error **errp)
263 {
264     int fd;
265 
266     trace_qio_channel_socket_dgram_sync(ioc, localAddr, remoteAddr);
267     fd = socket_dgram(remoteAddr, localAddr, errp);
268     if (fd < 0) {
269         trace_qio_channel_socket_dgram_fail(ioc);
270         return -1;
271     }
272 
273     trace_qio_channel_socket_dgram_complete(ioc, fd);
274     if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) {
275         close(fd);
276         return -1;
277     }
278 
279     return 0;
280 }
281 
282 
283 struct QIOChannelSocketDGramWorkerData {
284     SocketAddress *localAddr;
285     SocketAddress *remoteAddr;
286 };
287 
288 
289 static void qio_channel_socket_dgram_worker_free(gpointer opaque)
290 {
291     struct QIOChannelSocketDGramWorkerData *data = opaque;
292     qapi_free_SocketAddress(data->localAddr);
293     qapi_free_SocketAddress(data->remoteAddr);
294     g_free(data);
295 }
296 
297 static void qio_channel_socket_dgram_worker(QIOTask *task,
298                                             gpointer opaque)
299 {
300     QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
301     struct QIOChannelSocketDGramWorkerData *data = opaque;
302     Error *err = NULL;
303 
304     /* socket_dgram() blocks in DNS lookups, so we must use a thread */
305     qio_channel_socket_dgram_sync(ioc, data->localAddr,
306                                   data->remoteAddr, &err);
307 
308     qio_task_set_error(task, err);
309 }
310 
311 
312 void qio_channel_socket_dgram_async(QIOChannelSocket *ioc,
313                                     SocketAddress *localAddr,
314                                     SocketAddress *remoteAddr,
315                                     QIOTaskFunc callback,
316                                     gpointer opaque,
317                                     GDestroyNotify destroy,
318                                     GMainContext *context)
319 {
320     QIOTask *task = qio_task_new(
321         OBJECT(ioc), callback, opaque, destroy);
322     struct QIOChannelSocketDGramWorkerData *data = g_new0(
323         struct QIOChannelSocketDGramWorkerData, 1);
324 
325     data->localAddr = QAPI_CLONE(SocketAddress, localAddr);
326     data->remoteAddr = QAPI_CLONE(SocketAddress, remoteAddr);
327 
328     trace_qio_channel_socket_dgram_async(ioc, localAddr, remoteAddr);
329     qio_task_run_in_thread(task,
330                            qio_channel_socket_dgram_worker,
331                            data,
332                            qio_channel_socket_dgram_worker_free,
333                            context);
334 }
335 
336 
337 QIOChannelSocket *
338 qio_channel_socket_accept(QIOChannelSocket *ioc,
339                           Error **errp)
340 {
341     QIOChannelSocket *cioc;
342 
343     cioc = qio_channel_socket_new();
344     cioc->remoteAddrLen = sizeof(ioc->remoteAddr);
345     cioc->localAddrLen = sizeof(ioc->localAddr);
346 
347  retry:
348     trace_qio_channel_socket_accept(ioc);
349     cioc->fd = qemu_accept(ioc->fd, (struct sockaddr *)&cioc->remoteAddr,
350                            &cioc->remoteAddrLen);
351     if (cioc->fd < 0) {
352         if (errno == EINTR) {
353             goto retry;
354         }
355         error_setg_errno(errp, errno, "Unable to accept connection");
356         trace_qio_channel_socket_accept_fail(ioc);
357         goto error;
358     }
359 
360     if (getsockname(cioc->fd, (struct sockaddr *)&cioc->localAddr,
361                     &cioc->localAddrLen) < 0) {
362         error_setg_errno(errp, errno,
363                          "Unable to query local socket address");
364         goto error;
365     }
366 
367 #ifndef WIN32
368     if (cioc->localAddr.ss_family == AF_UNIX) {
369         QIOChannel *ioc_local = QIO_CHANNEL(cioc);
370         qio_channel_set_feature(ioc_local, QIO_CHANNEL_FEATURE_FD_PASS);
371     }
372 #endif /* WIN32 */
373 
374     trace_qio_channel_socket_accept_complete(ioc, cioc, cioc->fd);
375     return cioc;
376 
377  error:
378     object_unref(OBJECT(cioc));
379     return NULL;
380 }
381 
382 static void qio_channel_socket_init(Object *obj)
383 {
384     QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
385     ioc->fd = -1;
386 }
387 
388 static void qio_channel_socket_finalize(Object *obj)
389 {
390     QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
391 
392     if (ioc->fd != -1) {
393         QIOChannel *ioc_local = QIO_CHANNEL(ioc);
394         if (qio_channel_has_feature(ioc_local, QIO_CHANNEL_FEATURE_LISTEN)) {
395             Error *err = NULL;
396 
397             socket_listen_cleanup(ioc->fd, &err);
398             if (err) {
399                 error_report_err(err);
400                 err = NULL;
401             }
402         }
403 #ifdef WIN32
404         WSAEventSelect(ioc->fd, NULL, 0);
405 #endif
406         closesocket(ioc->fd);
407         ioc->fd = -1;
408     }
409 }
410 
411 
412 #ifndef WIN32
413 static void qio_channel_socket_copy_fds(struct msghdr *msg,
414                                         int **fds, size_t *nfds)
415 {
416     struct cmsghdr *cmsg;
417 
418     *nfds = 0;
419     *fds = NULL;
420 
421     for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
422         int fd_size, i;
423         int gotfds;
424 
425         if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) ||
426             cmsg->cmsg_level != SOL_SOCKET ||
427             cmsg->cmsg_type != SCM_RIGHTS) {
428             continue;
429         }
430 
431         fd_size = cmsg->cmsg_len - CMSG_LEN(0);
432 
433         if (!fd_size) {
434             continue;
435         }
436 
437         gotfds = fd_size / sizeof(int);
438         *fds = g_renew(int, *fds, *nfds + gotfds);
439         memcpy(*fds + *nfds, CMSG_DATA(cmsg), fd_size);
440 
441         for (i = 0; i < gotfds; i++) {
442             int fd = (*fds)[*nfds + i];
443             if (fd < 0) {
444                 continue;
445             }
446 
447             /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
448             qemu_set_block(fd);
449 
450 #ifndef MSG_CMSG_CLOEXEC
451             qemu_set_cloexec(fd);
452 #endif
453         }
454         *nfds += gotfds;
455     }
456 }
457 
458 
459 static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
460                                         const struct iovec *iov,
461                                         size_t niov,
462                                         int **fds,
463                                         size_t *nfds,
464                                         Error **errp)
465 {
466     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
467     ssize_t ret;
468     struct msghdr msg = { NULL, };
469     char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
470     int sflags = 0;
471 
472     memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
473 
474 #ifdef MSG_CMSG_CLOEXEC
475     sflags |= MSG_CMSG_CLOEXEC;
476 #endif
477 
478     msg.msg_iov = (struct iovec *)iov;
479     msg.msg_iovlen = niov;
480     if (fds && nfds) {
481         msg.msg_control = control;
482         msg.msg_controllen = sizeof(control);
483     }
484 
485  retry:
486     ret = recvmsg(sioc->fd, &msg, sflags);
487     if (ret < 0) {
488         if (errno == EAGAIN) {
489             return QIO_CHANNEL_ERR_BLOCK;
490         }
491         if (errno == EINTR) {
492             goto retry;
493         }
494 
495         error_setg_errno(errp, errno,
496                          "Unable to read from socket");
497         return -1;
498     }
499 
500     if (fds && nfds) {
501         qio_channel_socket_copy_fds(&msg, fds, nfds);
502     }
503 
504     return ret;
505 }
506 
507 static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
508                                          const struct iovec *iov,
509                                          size_t niov,
510                                          int *fds,
511                                          size_t nfds,
512                                          Error **errp)
513 {
514     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
515     ssize_t ret;
516     struct msghdr msg = { NULL, };
517     char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
518     size_t fdsize = sizeof(int) * nfds;
519     struct cmsghdr *cmsg;
520 
521     memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
522 
523     msg.msg_iov = (struct iovec *)iov;
524     msg.msg_iovlen = niov;
525 
526     if (nfds) {
527         if (nfds > SOCKET_MAX_FDS) {
528             error_setg_errno(errp, EINVAL,
529                              "Only %d FDs can be sent, got %zu",
530                              SOCKET_MAX_FDS, nfds);
531             return -1;
532         }
533 
534         msg.msg_control = control;
535         msg.msg_controllen = CMSG_SPACE(sizeof(int) * nfds);
536 
537         cmsg = CMSG_FIRSTHDR(&msg);
538         cmsg->cmsg_len = CMSG_LEN(fdsize);
539         cmsg->cmsg_level = SOL_SOCKET;
540         cmsg->cmsg_type = SCM_RIGHTS;
541         memcpy(CMSG_DATA(cmsg), fds, fdsize);
542     }
543 
544  retry:
545     ret = sendmsg(sioc->fd, &msg, 0);
546     if (ret <= 0) {
547         if (errno == EAGAIN) {
548             return QIO_CHANNEL_ERR_BLOCK;
549         }
550         if (errno == EINTR) {
551             goto retry;
552         }
553         error_setg_errno(errp, errno,
554                          "Unable to write to socket");
555         return -1;
556     }
557     return ret;
558 }
559 #else /* WIN32 */
560 static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
561                                         const struct iovec *iov,
562                                         size_t niov,
563                                         int **fds,
564                                         size_t *nfds,
565                                         Error **errp)
566 {
567     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
568     ssize_t done = 0;
569     ssize_t i;
570 
571     for (i = 0; i < niov; i++) {
572         ssize_t ret;
573     retry:
574         ret = recv(sioc->fd,
575                    iov[i].iov_base,
576                    iov[i].iov_len,
577                    0);
578         if (ret < 0) {
579             if (errno == EAGAIN) {
580                 if (done) {
581                     return done;
582                 } else {
583                     return QIO_CHANNEL_ERR_BLOCK;
584                 }
585             } else if (errno == EINTR) {
586                 goto retry;
587             } else {
588                 error_setg_errno(errp, errno,
589                                  "Unable to read from socket");
590                 return -1;
591             }
592         }
593         done += ret;
594         if (ret < iov[i].iov_len) {
595             return done;
596         }
597     }
598 
599     return done;
600 }
601 
602 static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
603                                          const struct iovec *iov,
604                                          size_t niov,
605                                          int *fds,
606                                          size_t nfds,
607                                          Error **errp)
608 {
609     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
610     ssize_t done = 0;
611     ssize_t i;
612 
613     for (i = 0; i < niov; i++) {
614         ssize_t ret;
615     retry:
616         ret = send(sioc->fd,
617                    iov[i].iov_base,
618                    iov[i].iov_len,
619                    0);
620         if (ret < 0) {
621             if (errno == EAGAIN) {
622                 if (done) {
623                     return done;
624                 } else {
625                     return QIO_CHANNEL_ERR_BLOCK;
626                 }
627             } else if (errno == EINTR) {
628                 goto retry;
629             } else {
630                 error_setg_errno(errp, errno,
631                                  "Unable to write to socket");
632                 return -1;
633             }
634         }
635         done += ret;
636         if (ret < iov[i].iov_len) {
637             return done;
638         }
639     }
640 
641     return done;
642 }
643 #endif /* WIN32 */
644 
645 static int
646 qio_channel_socket_set_blocking(QIOChannel *ioc,
647                                 bool enabled,
648                                 Error **errp)
649 {
650     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
651 
652     if (enabled) {
653         qemu_set_block(sioc->fd);
654     } else {
655         qemu_set_nonblock(sioc->fd);
656     }
657     return 0;
658 }
659 
660 
661 static void
662 qio_channel_socket_set_delay(QIOChannel *ioc,
663                              bool enabled)
664 {
665     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
666     int v = enabled ? 0 : 1;
667 
668     qemu_setsockopt(sioc->fd,
669                     IPPROTO_TCP, TCP_NODELAY,
670                     &v, sizeof(v));
671 }
672 
673 
674 static void
675 qio_channel_socket_set_cork(QIOChannel *ioc,
676                             bool enabled)
677 {
678     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
679     int v = enabled ? 1 : 0;
680 
681     socket_set_cork(sioc->fd, v);
682 }
683 
684 
685 static int
686 qio_channel_socket_close(QIOChannel *ioc,
687                          Error **errp)
688 {
689     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
690     int rc = 0;
691 
692     if (sioc->fd != -1) {
693 #ifdef WIN32
694         WSAEventSelect(sioc->fd, NULL, 0);
695 #endif
696         if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) {
697             socket_listen_cleanup(sioc->fd, errp);
698         }
699 
700         if (closesocket(sioc->fd) < 0) {
701             sioc->fd = -1;
702             error_setg_errno(errp, errno,
703                              "Unable to close socket");
704             return -1;
705         }
706         sioc->fd = -1;
707     }
708     return rc;
709 }
710 
711 static int
712 qio_channel_socket_shutdown(QIOChannel *ioc,
713                             QIOChannelShutdown how,
714                             Error **errp)
715 {
716     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
717     int sockhow;
718 
719     switch (how) {
720     case QIO_CHANNEL_SHUTDOWN_READ:
721         sockhow = SHUT_RD;
722         break;
723     case QIO_CHANNEL_SHUTDOWN_WRITE:
724         sockhow = SHUT_WR;
725         break;
726     case QIO_CHANNEL_SHUTDOWN_BOTH:
727     default:
728         sockhow = SHUT_RDWR;
729         break;
730     }
731 
732     if (shutdown(sioc->fd, sockhow) < 0) {
733         error_setg_errno(errp, errno,
734                          "Unable to shutdown socket");
735         return -1;
736     }
737     return 0;
738 }
739 
740 static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc,
741                                                   AioContext *ctx,
742                                                   IOHandler *io_read,
743                                                   IOHandler *io_write,
744                                                   void *opaque)
745 {
746     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
747     aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, NULL, opaque);
748 }
749 
750 static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
751                                                 GIOCondition condition)
752 {
753     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
754     return qio_channel_create_socket_watch(ioc,
755                                            sioc->fd,
756                                            condition);
757 }
758 
759 static void qio_channel_socket_class_init(ObjectClass *klass,
760                                           void *class_data G_GNUC_UNUSED)
761 {
762     QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
763 
764     ioc_klass->io_writev = qio_channel_socket_writev;
765     ioc_klass->io_readv = qio_channel_socket_readv;
766     ioc_klass->io_set_blocking = qio_channel_socket_set_blocking;
767     ioc_klass->io_close = qio_channel_socket_close;
768     ioc_klass->io_shutdown = qio_channel_socket_shutdown;
769     ioc_klass->io_set_cork = qio_channel_socket_set_cork;
770     ioc_klass->io_set_delay = qio_channel_socket_set_delay;
771     ioc_klass->io_create_watch = qio_channel_socket_create_watch;
772     ioc_klass->io_set_aio_fd_handler = qio_channel_socket_set_aio_fd_handler;
773 }
774 
775 static const TypeInfo qio_channel_socket_info = {
776     .parent = TYPE_QIO_CHANNEL,
777     .name = TYPE_QIO_CHANNEL_SOCKET,
778     .instance_size = sizeof(QIOChannelSocket),
779     .instance_init = qio_channel_socket_init,
780     .instance_finalize = qio_channel_socket_finalize,
781     .class_init = qio_channel_socket_class_init,
782 };
783 
784 static void qio_channel_socket_register_types(void)
785 {
786     type_register_static(&qio_channel_socket_info);
787 }
788 
789 type_init(qio_channel_socket_register_types);
790