]> git.proxmox.com Git - mirror_qemu.git/blame - io/channel-socket.c
Remove qemu-common.h include from most units
[mirror_qemu.git] / io / channel-socket.c
CommitLineData
559607ea
DB
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
c8198bd5 9 * version 2.1 of the License, or (at your option) any later version.
559607ea
DB
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/>.
559607ea
DB
18 */
19
cae9fc56 20#include "qemu/osdep.h"
da34e65c 21#include "qapi/error.h"
9af23989 22#include "qapi/qapi-visit-sockets.h"
0b8fa32f 23#include "qemu/module.h"
559607ea
DB
24#include "io/channel-socket.h"
25#include "io/channel-watch.h"
26#include "trace.h"
37f9e0a2 27#include "qapi/clone-visitor.h"
559607ea
DB
28
29#define SOCKET_MAX_FDS 16
30
31SocketAddress *
32qio_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
40SocketAddress *
41qio_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
49QIOChannelSocket *
50qio_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);
d8d3c7cc 59 qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
559607ea 60
a5897205
PB
61#ifdef WIN32
62 ioc->event = CreateEvent(NULL, FALSE, FALSE, NULL);
63#endif
64
559607ea
DB
65 trace_qio_channel_socket_new(sioc);
66
67 return sioc;
68}
69
70
71static int
72qio_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) {
b16a44e1 88 if (errno == ENOTCONN) {
559607ea
DB
89 memset(&sioc->remoteAddr, 0, sizeof(sioc->remoteAddr));
90 sioc->remoteAddrLen = sizeof(sioc->remoteAddr);
91 } else {
b16a44e1 92 error_setg_errno(errp, errno,
559607ea
DB
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) {
b16a44e1 100 error_setg_errno(errp, errno,
559607ea
DB
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);
d8d3c7cc 108 qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS);
559607ea
DB
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
119QIOChannelSocket *
120qio_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
137int 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);
b2587932 144 fd = socket_connect(addr, errp);
559607ea
DB
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
59de517d
DB
160static void qio_channel_socket_connect_worker(QIOTask *task,
161 gpointer opaque)
559607ea
DB
162{
163 QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
164 SocketAddress *addr = opaque;
59de517d 165 Error *err = NULL;
559607ea 166
59de517d 167 qio_channel_socket_connect_sync(ioc, addr, &err);
559607ea 168
59de517d 169 qio_task_set_error(task, err);
559607ea
DB
170}
171
172
173void qio_channel_socket_connect_async(QIOChannelSocket *ioc,
174 SocketAddress *addr,
175 QIOTaskFunc callback,
176 gpointer opaque,
8005fdd8
PX
177 GDestroyNotify destroy,
178 GMainContext *context)
559607ea
DB
179{
180 QIOTask *task = qio_task_new(
181 OBJECT(ioc), callback, opaque, destroy);
182 SocketAddress *addrCopy;
183
37f9e0a2 184 addrCopy = QAPI_CLONE(SocketAddress, addr);
559607ea
DB
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,
a17536c5 192 (GDestroyNotify)qapi_free_SocketAddress,
8005fdd8 193 context);
559607ea
DB
194}
195
196
197int qio_channel_socket_listen_sync(QIOChannelSocket *ioc,
198 SocketAddress *addr,
4e2d8bf6 199 int num,
559607ea
DB
200 Error **errp)
201{
202 int fd;
203
4e2d8bf6
JQ
204 trace_qio_channel_socket_listen_sync(ioc, addr, num);
205 fd = socket_listen(addr, num, errp);
559607ea
DB
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 }
bf535208 216 qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_LISTEN);
559607ea
DB
217
218 return 0;
219}
220
221
7959e29e
JQ
222struct QIOChannelListenWorkerData {
223 SocketAddress *addr;
224 int num; /* amount of expected connections */
225};
226
227static 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
59de517d
DB
235static void qio_channel_socket_listen_worker(QIOTask *task,
236 gpointer opaque)
559607ea
DB
237{
238 QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
7959e29e 239 struct QIOChannelListenWorkerData *data = opaque;
59de517d 240 Error *err = NULL;
559607ea 241
7959e29e 242 qio_channel_socket_listen_sync(ioc, data->addr, data->num, &err);
559607ea 243
59de517d 244 qio_task_set_error(task, err);
559607ea
DB
245}
246
247
248void qio_channel_socket_listen_async(QIOChannelSocket *ioc,
249 SocketAddress *addr,
7959e29e 250 int num,
559607ea
DB
251 QIOTaskFunc callback,
252 gpointer opaque,
8005fdd8
PX
253 GDestroyNotify destroy,
254 GMainContext *context)
559607ea
DB
255{
256 QIOTask *task = qio_task_new(
257 OBJECT(ioc), callback, opaque, destroy);
7959e29e 258 struct QIOChannelListenWorkerData *data;
559607ea 259
7959e29e
JQ
260 data = g_new0(struct QIOChannelListenWorkerData, 1);
261 data->addr = QAPI_CLONE(SocketAddress, addr);
262 data->num = num;
559607ea
DB
263
264 /* socket_listen() blocks in DNS lookups, so we must use a thread */
7959e29e 265 trace_qio_channel_socket_listen_async(ioc, addr, num);
559607ea
DB
266 qio_task_run_in_thread(task,
267 qio_channel_socket_listen_worker,
7959e29e
JQ
268 data,
269 qio_channel_listen_worker_free,
8005fdd8 270 context);
559607ea
DB
271}
272
273
274int 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);
150dcd1a 282 fd = socket_dgram(remoteAddr, localAddr, errp);
559607ea
DB
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
298struct QIOChannelSocketDGramWorkerData {
299 SocketAddress *localAddr;
300 SocketAddress *remoteAddr;
301};
302
303
304static 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
59de517d
DB
312static void qio_channel_socket_dgram_worker(QIOTask *task,
313 gpointer opaque)
559607ea
DB
314{
315 QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
316 struct QIOChannelSocketDGramWorkerData *data = opaque;
59de517d 317 Error *err = NULL;
559607ea
DB
318
319 /* socket_dgram() blocks in DNS lookups, so we must use a thread */
59de517d
DB
320 qio_channel_socket_dgram_sync(ioc, data->localAddr,
321 data->remoteAddr, &err);
559607ea 322
59de517d 323 qio_task_set_error(task, err);
559607ea
DB
324}
325
326
327void qio_channel_socket_dgram_async(QIOChannelSocket *ioc,
328 SocketAddress *localAddr,
329 SocketAddress *remoteAddr,
330 QIOTaskFunc callback,
331 gpointer opaque,
8005fdd8
PX
332 GDestroyNotify destroy,
333 GMainContext *context)
559607ea
DB
334{
335 QIOTask *task = qio_task_new(
336 OBJECT(ioc), callback, opaque, destroy);
337 struct QIOChannelSocketDGramWorkerData *data = g_new0(
338 struct QIOChannelSocketDGramWorkerData, 1);
339
37f9e0a2
EB
340 data->localAddr = QAPI_CLONE(SocketAddress, localAddr);
341 data->remoteAddr = QAPI_CLONE(SocketAddress, remoteAddr);
559607ea
DB
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,
a17536c5 347 qio_channel_socket_dgram_worker_free,
8005fdd8 348 context);
559607ea
DB
349}
350
351
352QIOChannelSocket *
353qio_channel_socket_accept(QIOChannelSocket *ioc,
354 Error **errp)
355{
356 QIOChannelSocket *cioc;
357
0e5d6327 358 cioc = qio_channel_socket_new();
559607ea
DB
359 cioc->remoteAddrLen = sizeof(ioc->remoteAddr);
360 cioc->localAddrLen = sizeof(ioc->localAddr);
361
362 retry:
363 trace_qio_channel_socket_accept(ioc);
de7971ff
DB
364 cioc->fd = qemu_accept(ioc->fd, (struct sockaddr *)&cioc->remoteAddr,
365 &cioc->remoteAddrLen);
559607ea 366 if (cioc->fd < 0) {
b16a44e1 367 if (errno == EINTR) {
559607ea
DB
368 goto retry;
369 }
8bd9c4e6
PX
370 error_setg_errno(errp, errno, "Unable to accept connection");
371 trace_qio_channel_socket_accept_fail(ioc);
559607ea
DB
372 goto error;
373 }
374
bead5994
DB
375 if (getsockname(cioc->fd, (struct sockaddr *)&cioc->localAddr,
376 &cioc->localAddrLen) < 0) {
b16a44e1 377 error_setg_errno(errp, errno,
559607ea
DB
378 "Unable to query local socket address");
379 goto error;
380 }
381
bead5994
DB
382#ifndef WIN32
383 if (cioc->localAddr.ss_family == AF_UNIX) {
d8d3c7cc
FF
384 QIOChannel *ioc_local = QIO_CHANNEL(cioc);
385 qio_channel_set_feature(ioc_local, QIO_CHANNEL_FEATURE_FD_PASS);
bead5994
DB
386 }
387#endif /* WIN32 */
388
559607ea
DB
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
397static void qio_channel_socket_init(Object *obj)
398{
399 QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
400 ioc->fd = -1;
401}
402
403static void qio_channel_socket_finalize(Object *obj)
404{
405 QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
74b6ce43 406
559607ea 407 if (ioc->fd != -1) {
e413ae0c
FF
408 QIOChannel *ioc_local = QIO_CHANNEL(ioc);
409 if (qio_channel_has_feature(ioc_local, QIO_CHANNEL_FEATURE_LISTEN)) {
74b6ce43
MAL
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 }
a5897205
PB
418#ifdef WIN32
419 WSAEventSelect(ioc->fd, NULL, 0);
420#endif
421 closesocket(ioc->fd);
559607ea
DB
422 ioc->fd = -1;
423 }
424}
425
426
427#ifndef WIN32
428static 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
474static 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
ccf1e2dc
DB
487 memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
488
559607ea
DB
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);
d80f54ce
DDAG
494#ifdef MSG_CMSG_CLOEXEC
495 sflags |= MSG_CMSG_CLOEXEC;
496#endif
497
559607ea
DB
498 }
499
500 retry:
501 ret = recvmsg(sioc->fd, &msg, sflags);
502 if (ret < 0) {
b16a44e1 503 if (errno == EAGAIN) {
559607ea
DB
504 return QIO_CHANNEL_ERR_BLOCK;
505 }
b16a44e1 506 if (errno == EINTR) {
559607ea
DB
507 goto retry;
508 }
509
b16a44e1 510 error_setg_errno(errp, errno,
559607ea
DB
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
522static 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, };
ccf1e2dc 532 char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
7b3c618a
DB
533 size_t fdsize = sizeof(int) * nfds;
534 struct cmsghdr *cmsg;
559607ea 535
ccf1e2dc
DB
536 memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
537
559607ea
DB
538 msg.msg_iov = (struct iovec *)iov;
539 msg.msg_iovlen = niov;
540
541 if (nfds) {
559607ea 542 if (nfds > SOCKET_MAX_FDS) {
cc75a50c 543 error_setg_errno(errp, EINVAL,
559607ea
DB
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) {
b16a44e1 562 if (errno == EAGAIN) {
559607ea
DB
563 return QIO_CHANNEL_ERR_BLOCK;
564 }
b16a44e1 565 if (errno == EINTR) {
559607ea
DB
566 goto retry;
567 }
b16a44e1 568 error_setg_errno(errp, errno,
559607ea
DB
569 "Unable to write to socket");
570 return -1;
571 }
572 return ret;
573}
574#else /* WIN32 */
575static 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) {
b16a44e1 594 if (errno == EAGAIN) {
559607ea
DB
595 if (done) {
596 return done;
597 } else {
598 return QIO_CHANNEL_ERR_BLOCK;
599 }
b16a44e1 600 } else if (errno == EINTR) {
559607ea
DB
601 goto retry;
602 } else {
b16a44e1 603 error_setg_errno(errp, errno,
5151d23e 604 "Unable to read from socket");
559607ea
DB
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
617static 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) {
b16a44e1 636 if (errno == EAGAIN) {
559607ea
DB
637 if (done) {
638 return done;
639 } else {
640 return QIO_CHANNEL_ERR_BLOCK;
641 }
b16a44e1 642 } else if (errno == EINTR) {
559607ea
DB
643 goto retry;
644 } else {
b16a44e1 645 error_setg_errno(errp, errno,
559607ea
DB
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
660static int
661qio_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
676static void
677qio_channel_socket_set_delay(QIOChannel *ioc,
678 bool enabled)
679{
680 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
681 int v = enabled ? 0 : 1;
682
e7b79428
MAL
683 setsockopt(sioc->fd,
684 IPPROTO_TCP, TCP_NODELAY,
685 &v, sizeof(v));
559607ea
DB
686}
687
688
689static void
690qio_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
700static int
701qio_channel_socket_close(QIOChannel *ioc,
702 Error **errp)
703{
704 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
d66f78e1 705 int rc = 0;
fdceb4ab 706 Error *err = NULL;
559607ea 707
a5897205
PB
708 if (sioc->fd != -1) {
709#ifdef WIN32
710 WSAEventSelect(sioc->fd, NULL, 0);
711#endif
73564c40
DB
712 if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) {
713 socket_listen_cleanup(sioc->fd, errp);
714 }
715
a5897205
PB
716 if (closesocket(sioc->fd) < 0) {
717 sioc->fd = -1;
fdceb4ab
MA
718 error_setg_errno(&err, errno, "Unable to close socket");
719 error_propagate(errp, err);
a5897205
PB
720 return -1;
721 }
559607ea 722 sioc->fd = -1;
559607ea 723 }
d66f78e1 724 return rc;
559607ea
DB
725}
726
727static int
728qio_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) {
b16a44e1 749 error_setg_errno(errp, errno,
559607ea
DB
750 "Unable to shutdown socket");
751 return -1;
752 }
753 return 0;
754}
755
bf88c124
PB
756static 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);
826cc324
SH
763 aio_set_fd_handler(ctx, sioc->fd, false,
764 io_read, io_write, NULL, NULL, opaque);
bf88c124
PB
765}
766
559607ea
DB
767static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
768 GIOCondition condition)
769{
770 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
b83b68a0
PB
771 return qio_channel_create_socket_watch(ioc,
772 sioc->fd,
773 condition);
559607ea
DB
774}
775
776static 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;
bf88c124 789 ioc_klass->io_set_aio_fd_handler = qio_channel_socket_set_aio_fd_handler;
559607ea
DB
790}
791
792static 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
801static void qio_channel_socket_register_types(void)
802{
803 type_register_static(&qio_channel_socket_info);
804}
805
806type_init(qio_channel_socket_register_types);