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