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