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