1/*
2 * Copyright © 2008 Kristian Høgsberg
3 * Copyright © 2013 Jason Ekstrand
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27#define _GNU_SOURCE
28
29#include <math.h>
30#include <stdlib.h>
31#include <stdint.h>
32#include <string.h>
33#include <stdio.h>
34#include <errno.h>
35#include <sys/uio.h>
36#include <fcntl.h>
37#include <unistd.h>
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <time.h>
41#include <ffi.h>
42
43#include "wayland-util.h"
44#include "wayland-private.h"
45#include "wayland-os.h"
46
47static inline uint32_t
48div_roundup(uint32_t n, size_t a)
49{
50 /* The cast to uint64_t is necessary to prevent overflow when rounding
51 * values close to UINT32_MAX. After the division it is again safe to
52 * cast back to uint32_t.
53 */
54 return (uint32_t) (((uint64_t) n + (a - 1)) / a);
55}
56
57struct wl_ring_buffer {
58 char data[4096];
59 uint32_t head, tail;
60};
61
62#define MASK(i) ((i) & 4095)
63
64#define MAX_FDS_OUT 28
65#define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
66
67struct wl_connection {
68 struct wl_ring_buffer in, out;
69 struct wl_ring_buffer fds_in, fds_out;
70 int fd;
71 int want_flush;
72};
73
74static int
75ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
76{
77 uint32_t head, size;
78
79 if (count > sizeof(b->data)) {
80 wl_log(fmt: "Data too big for buffer (%d > %d).\n",
81 count, sizeof(b->data));
82 errno = E2BIG;
83 return -1;
84 }
85
86 head = MASK(b->head);
87 if (head + count <= sizeof b->data) {
88 memcpy(dest: b->data + head, src: data, n: count);
89 } else {
90 size = sizeof b->data - head;
91 memcpy(dest: b->data + head, src: data, n: size);
92 memcpy(dest: b->data, src: (const char *) data + size, n: count - size);
93 }
94
95 b->head += count;
96
97 return 0;
98}
99
100static void
101ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
102{
103 uint32_t head, tail;
104
105 head = MASK(b->head);
106 tail = MASK(b->tail);
107 if (head < tail) {
108 iov[0].iov_base = b->data + head;
109 iov[0].iov_len = tail - head;
110 *count = 1;
111 } else if (tail == 0) {
112 iov[0].iov_base = b->data + head;
113 iov[0].iov_len = sizeof b->data - head;
114 *count = 1;
115 } else {
116 iov[0].iov_base = b->data + head;
117 iov[0].iov_len = sizeof b->data - head;
118 iov[1].iov_base = b->data;
119 iov[1].iov_len = tail;
120 *count = 2;
121 }
122}
123
124static void
125ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
126{
127 uint32_t head, tail;
128
129 head = MASK(b->head);
130 tail = MASK(b->tail);
131 if (tail < head) {
132 iov[0].iov_base = b->data + tail;
133 iov[0].iov_len = head - tail;
134 *count = 1;
135 } else if (head == 0) {
136 iov[0].iov_base = b->data + tail;
137 iov[0].iov_len = sizeof b->data - tail;
138 *count = 1;
139 } else {
140 iov[0].iov_base = b->data + tail;
141 iov[0].iov_len = sizeof b->data - tail;
142 iov[1].iov_base = b->data;
143 iov[1].iov_len = head;
144 *count = 2;
145 }
146}
147
148static void
149ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count)
150{
151 uint32_t tail, size;
152
153 tail = MASK(b->tail);
154 if (tail + count <= sizeof b->data) {
155 memcpy(dest: data, src: b->data + tail, n: count);
156 } else {
157 size = sizeof b->data - tail;
158 memcpy(dest: data, src: b->data + tail, n: size);
159 memcpy(dest: (char *) data + size, src: b->data, n: count - size);
160 }
161}
162
163static uint32_t
164ring_buffer_size(struct wl_ring_buffer *b)
165{
166 return b->head - b->tail;
167}
168
169struct wl_connection *
170wl_connection_create(int fd)
171{
172 struct wl_connection *connection;
173
174 connection = zalloc(s: sizeof *connection);
175 if (connection == NULL)
176 return NULL;
177
178 connection->fd = fd;
179
180 return connection;
181}
182
183static void
184close_fds(struct wl_ring_buffer *buffer, int max)
185{
186 int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
187 size_t size;
188
189 size = ring_buffer_size(b: buffer);
190 if (size == 0)
191 return;
192
193 ring_buffer_copy(b: buffer, data: fds, count: size);
194 count = size / sizeof fds[0];
195 if (max > 0 && max < count)
196 count = max;
197 size = count * sizeof fds[0];
198 for (i = 0; i < count; i++)
199 close(fd: fds[i]);
200 buffer->tail += size;
201}
202
203void
204wl_connection_close_fds_in(struct wl_connection *connection, int max)
205{
206 close_fds(buffer: &connection->fds_in, max);
207}
208
209int
210wl_connection_destroy(struct wl_connection *connection)
211{
212 int fd = connection->fd;
213
214 close_fds(buffer: &connection->fds_out, max: -1);
215 close_fds(buffer: &connection->fds_in, max: -1);
216 free(ptr: connection);
217
218 return fd;
219}
220
221void
222wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
223{
224 ring_buffer_copy(b: &connection->in, data, count: size);
225}
226
227void
228wl_connection_consume(struct wl_connection *connection, size_t size)
229{
230 connection->in.tail += size;
231}
232
233static void
234build_cmsg(struct wl_ring_buffer *buffer, char *data, int *clen)
235{
236 struct cmsghdr *cmsg;
237 size_t size;
238
239 size = ring_buffer_size(b: buffer);
240 if (size > MAX_FDS_OUT * sizeof(int32_t))
241 size = MAX_FDS_OUT * sizeof(int32_t);
242
243 if (size > 0) {
244 cmsg = (struct cmsghdr *) data;
245 cmsg->cmsg_level = SOL_SOCKET;
246 cmsg->cmsg_type = SCM_RIGHTS;
247 cmsg->cmsg_len = CMSG_LEN(size);
248 ring_buffer_copy(b: buffer, CMSG_DATA(cmsg), count: size);
249 *clen = cmsg->cmsg_len;
250 } else {
251 *clen = 0;
252 }
253}
254
255static int
256decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
257{
258 struct cmsghdr *cmsg;
259 size_t size, max, i;
260 int overflow = 0;
261
262 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
263 cmsg = CMSG_NXTHDR(msg, cmsg)) {
264 if (cmsg->cmsg_level != SOL_SOCKET ||
265 cmsg->cmsg_type != SCM_RIGHTS)
266 continue;
267
268 size = cmsg->cmsg_len - CMSG_LEN(0);
269 max = sizeof(buffer->data) - ring_buffer_size(b: buffer);
270 if (size > max || overflow) {
271 overflow = 1;
272 size /= sizeof(int32_t);
273 for (i = 0; i < size; i++)
274 close(fd: ((int*)CMSG_DATA(cmsg))[i]);
275 } else if (ring_buffer_put(b: buffer, CMSG_DATA(cmsg), count: size) < 0) {
276 return -1;
277 }
278 }
279
280 if (overflow) {
281 errno = EOVERFLOW;
282 return -1;
283 }
284
285 return 0;
286}
287
288int
289wl_connection_flush(struct wl_connection *connection)
290{
291 struct iovec iov[2];
292 struct msghdr msg;
293 char cmsg[CLEN];
294 int len = 0, count, clen;
295 uint32_t tail;
296
297 if (!connection->want_flush)
298 return 0;
299
300 tail = connection->out.tail;
301 while (connection->out.head - connection->out.tail > 0) {
302 ring_buffer_get_iov(b: &connection->out, iov, count: &count);
303
304 build_cmsg(buffer: &connection->fds_out, data: cmsg, clen: &clen);
305
306 msg.msg_name = NULL;
307 msg.msg_namelen = 0;
308 msg.msg_iov = iov;
309 msg.msg_iovlen = count;
310 msg.msg_control = (clen > 0) ? cmsg : NULL;
311 msg.msg_controllen = clen;
312 msg.msg_flags = 0;
313
314 do {
315 len = sendmsg(fd: connection->fd, message: &msg,
316 MSG_NOSIGNAL | MSG_DONTWAIT);
317 } while (len == -1 && errno == EINTR);
318
319 if (len == -1)
320 return -1;
321
322 close_fds(buffer: &connection->fds_out, MAX_FDS_OUT);
323
324 connection->out.tail += len;
325 }
326
327 connection->want_flush = 0;
328
329 return connection->out.head - tail;
330}
331
332uint32_t
333wl_connection_pending_input(struct wl_connection *connection)
334{
335 return ring_buffer_size(b: &connection->in);
336}
337
338int
339wl_connection_read(struct wl_connection *connection)
340{
341 struct iovec iov[2];
342 struct msghdr msg;
343 char cmsg[CLEN];
344 int len, count, ret;
345
346 if (ring_buffer_size(b: &connection->in) >= sizeof(connection->in.data)) {
347 errno = EOVERFLOW;
348 return -1;
349 }
350
351 ring_buffer_put_iov(b: &connection->in, iov, count: &count);
352
353 msg.msg_name = NULL;
354 msg.msg_namelen = 0;
355 msg.msg_iov = iov;
356 msg.msg_iovlen = count;
357 msg.msg_control = cmsg;
358 msg.msg_controllen = sizeof cmsg;
359 msg.msg_flags = 0;
360
361 do {
362 len = wl_os_recvmsg_cloexec(sockfd: connection->fd, msg: &msg, MSG_DONTWAIT);
363 } while (len < 0 && errno == EINTR);
364
365 if (len <= 0)
366 return len;
367
368 ret = decode_cmsg(buffer: &connection->fds_in, msg: &msg);
369 if (ret)
370 return -1;
371
372 connection->in.head += len;
373
374 return wl_connection_pending_input(connection);
375}
376
377int
378wl_connection_write(struct wl_connection *connection,
379 const void *data, size_t count)
380{
381 if (connection->out.head - connection->out.tail +
382 count > ARRAY_LENGTH(connection->out.data)) {
383 connection->want_flush = 1;
384 if (wl_connection_flush(connection) < 0)
385 return -1;
386 }
387
388 if (ring_buffer_put(b: &connection->out, data, count) < 0)
389 return -1;
390
391 connection->want_flush = 1;
392
393 return 0;
394}
395
396int
397wl_connection_queue(struct wl_connection *connection,
398 const void *data, size_t count)
399{
400 if (connection->out.head - connection->out.tail +
401 count > ARRAY_LENGTH(connection->out.data)) {
402 connection->want_flush = 1;
403 if (wl_connection_flush(connection) < 0)
404 return -1;
405 }
406
407 return ring_buffer_put(b: &connection->out, data, count);
408}
409
410int
411wl_message_count_arrays(const struct wl_message *message)
412{
413 int i, arrays;
414
415 for (i = 0, arrays = 0; message->signature[i]; i++) {
416 if (message->signature[i] == 'a')
417 arrays++;
418 }
419
420 return arrays;
421}
422
423int
424wl_connection_get_fd(struct wl_connection *connection)
425{
426 return connection->fd;
427}
428
429static int
430wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
431{
432 if (ring_buffer_size(b: &connection->fds_out) == MAX_FDS_OUT * sizeof fd) {
433 connection->want_flush = 1;
434 if (wl_connection_flush(connection) < 0)
435 return -1;
436 }
437
438 return ring_buffer_put(b: &connection->fds_out, data: &fd, count: sizeof fd);
439}
440
441const char *
442get_next_argument(const char *signature, struct argument_details *details)
443{
444 details->nullable = 0;
445 for(; *signature; ++signature) {
446 switch(*signature) {
447 case 'i':
448 case 'u':
449 case 'f':
450 case 's':
451 case 'o':
452 case 'n':
453 case 'a':
454 case 'h':
455 details->type = *signature;
456 return signature + 1;
457 case '?':
458 details->nullable = 1;
459 }
460 }
461 details->type = '\0';
462 return signature;
463}
464
465int
466arg_count_for_signature(const char *signature)
467{
468 int count = 0;
469 for(; *signature; ++signature) {
470 switch(*signature) {
471 case 'i':
472 case 'u':
473 case 'f':
474 case 's':
475 case 'o':
476 case 'n':
477 case 'a':
478 case 'h':
479 ++count;
480 }
481 }
482 return count;
483}
484
485int
486wl_message_get_since(const struct wl_message *message)
487{
488 int since;
489
490 since = atoi(nptr: message->signature);
491
492 if (since == 0)
493 since = 1;
494
495 return since;
496}
497
498void
499wl_argument_from_va_list(const char *signature, union wl_argument *args,
500 int count, va_list ap)
501{
502 int i;
503 const char *sig_iter;
504 struct argument_details arg;
505
506 sig_iter = signature;
507 for (i = 0; i < count; i++) {
508 sig_iter = get_next_argument(signature: sig_iter, details: &arg);
509
510 switch(arg.type) {
511 case 'i':
512 args[i].i = va_arg(ap, int32_t);
513 break;
514 case 'u':
515 args[i].u = va_arg(ap, uint32_t);
516 break;
517 case 'f':
518 args[i].f = va_arg(ap, wl_fixed_t);
519 break;
520 case 's':
521 args[i].s = va_arg(ap, const char *);
522 break;
523 case 'o':
524 args[i].o = va_arg(ap, struct wl_object *);
525 break;
526 case 'n':
527 args[i].o = va_arg(ap, struct wl_object *);
528 break;
529 case 'a':
530 args[i].a = va_arg(ap, struct wl_array *);
531 break;
532 case 'h':
533 args[i].h = va_arg(ap, int32_t);
534 break;
535 case '\0':
536 return;
537 }
538 }
539}
540
541static void
542wl_closure_clear_fds(struct wl_closure *closure)
543{
544 const char *signature = closure->message->signature;
545 struct argument_details arg;
546 int i;
547
548 for (i = 0; i < closure->count; i++) {
549 signature = get_next_argument(signature, details: &arg);
550 if (arg.type == 'h')
551 closure->args[i].h = -1;
552 }
553}
554
555static struct wl_closure *
556wl_closure_init(const struct wl_message *message, uint32_t size,
557 int *num_arrays, union wl_argument *args)
558{
559 struct wl_closure *closure;
560 int count;
561
562 count = arg_count_for_signature(signature: message->signature);
563 if (count > WL_CLOSURE_MAX_ARGS) {
564 wl_log(fmt: "too many args (%d)\n", count);
565 errno = EINVAL;
566 return NULL;
567 }
568
569 if (size) {
570 *num_arrays = wl_message_count_arrays(message);
571 closure = malloc(size: sizeof *closure + size +
572 *num_arrays * sizeof(struct wl_array));
573 } else {
574 closure = malloc(size: sizeof *closure);
575 }
576
577 if (!closure) {
578 errno = ENOMEM;
579 return NULL;
580 }
581
582 if (args)
583 memcpy(dest: closure->args, src: args, n: count * sizeof *args);
584
585 closure->message = message;
586 closure->count = count;
587
588 /* Set these all to -1 so we can close any that have been
589 * set to a real value during wl_closure_destroy().
590 * We may have copied a bunch of fds into the closure with
591 * memcpy previously, but those are undup()d client fds
592 * that we would have replaced anyway.
593 */
594 wl_closure_clear_fds(closure);
595
596 return closure;
597}
598
599struct wl_closure *
600wl_closure_marshal(struct wl_object *sender, uint32_t opcode,
601 union wl_argument *args,
602 const struct wl_message *message)
603{
604 struct wl_closure *closure;
605 struct wl_object *object;
606 int i, count, fd, dup_fd;
607 const char *signature;
608 struct argument_details arg;
609
610 closure = wl_closure_init(message, size: 0, NULL, args);
611 if (closure == NULL)
612 return NULL;
613
614 count = closure->count;
615
616 signature = message->signature;
617 for (i = 0; i < count; i++) {
618 signature = get_next_argument(signature, details: &arg);
619
620 switch (arg.type) {
621 case 'f':
622 case 'u':
623 case 'i':
624 break;
625 case 's':
626 if (!arg.nullable && args[i].s == NULL)
627 goto err_null;
628 break;
629 case 'o':
630 if (!arg.nullable && args[i].o == NULL)
631 goto err_null;
632 break;
633 case 'n':
634 object = args[i].o;
635 if (!arg.nullable && object == NULL)
636 goto err_null;
637
638 closure->args[i].n = object ? object->id : 0;
639 break;
640 case 'a':
641 if (!arg.nullable && args[i].a == NULL)
642 goto err_null;
643 break;
644 case 'h':
645 fd = args[i].h;
646 dup_fd = wl_os_dupfd_cloexec(fd, minfd: 0);
647 if (dup_fd < 0) {
648 wl_closure_destroy(closure);
649 wl_log(fmt: "error marshalling arguments for %s: dup failed: %s\n",
650 message->name, strerror(errno));
651 return NULL;
652 }
653 closure->args[i].h = dup_fd;
654 break;
655 default:
656 wl_abort(fmt: "unhandled format code: '%c'\n", arg.type);
657 break;
658 }
659 }
660
661 closure->sender_id = sender->id;
662 closure->opcode = opcode;
663
664 return closure;
665
666err_null:
667 wl_closure_destroy(closure);
668 wl_log(fmt: "error marshalling arguments for %s (signature %s): "
669 "null value passed for arg %i\n", message->name,
670 message->signature, i);
671 errno = EINVAL;
672 return NULL;
673}
674
675struct wl_closure *
676wl_closure_vmarshal(struct wl_object *sender, uint32_t opcode, va_list ap,
677 const struct wl_message *message)
678{
679 union wl_argument args[WL_CLOSURE_MAX_ARGS];
680
681 wl_argument_from_va_list(signature: message->signature, args,
682 WL_CLOSURE_MAX_ARGS, ap);
683
684 return wl_closure_marshal(sender, opcode, args, message);
685}
686
687struct wl_closure *
688wl_connection_demarshal(struct wl_connection *connection,
689 uint32_t size,
690 struct wl_map *objects,
691 const struct wl_message *message)
692{
693 uint32_t *p, *next, *end, length, length_in_u32, id;
694 int fd;
695 char *s;
696 int i, count, num_arrays;
697 const char *signature;
698 struct argument_details arg;
699 struct wl_closure *closure;
700 struct wl_array *array_extra;
701
702 /* Space for sender_id and opcode */
703 if (size < 2 * sizeof *p) {
704 wl_log(fmt: "message too short, invalid header\n");
705 wl_connection_consume(connection, size);
706 errno = EINVAL;
707 return NULL;
708 }
709
710 closure = wl_closure_init(message, size, num_arrays: &num_arrays, NULL);
711 if (closure == NULL) {
712 wl_connection_consume(connection, size);
713 return NULL;
714 }
715
716 count = closure->count;
717
718 array_extra = closure->extra;
719 p = (uint32_t *)(closure->extra + num_arrays);
720 end = p + size / sizeof *p;
721
722 wl_connection_copy(connection, data: p, size);
723 closure->sender_id = *p++;
724 closure->opcode = *p++ & 0x0000ffff;
725
726 signature = message->signature;
727 for (i = 0; i < count; i++) {
728 signature = get_next_argument(signature, details: &arg);
729
730 if (arg.type != 'h' && p + 1 > end) {
731 wl_log(fmt: "message too short, "
732 "object (%d), message %s(%s)\n",
733 closure->sender_id, message->name,
734 message->signature);
735 errno = EINVAL;
736 goto err;
737 }
738
739 switch (arg.type) {
740 case 'u':
741 closure->args[i].u = *p++;
742 break;
743 case 'i':
744 closure->args[i].i = *p++;
745 break;
746 case 'f':
747 closure->args[i].f = *p++;
748 break;
749 case 's':
750 length = *p++;
751
752 if (length == 0 && !arg.nullable) {
753 wl_log(fmt: "NULL string received on non-nullable "
754 "type, message %s(%s)\n", message->name,
755 message->signature);
756 errno = EINVAL;
757 goto err;
758 }
759 if (length == 0) {
760 closure->args[i].s = NULL;
761 break;
762 }
763
764 length_in_u32 = div_roundup(n: length, a: sizeof *p);
765 if ((uint32_t) (end - p) < length_in_u32) {
766 wl_log(fmt: "message too short, "
767 "object (%d), message %s(%s)\n",
768 closure->sender_id, message->name,
769 message->signature);
770 errno = EINVAL;
771 goto err;
772 }
773 next = p + length_in_u32;
774
775 s = (char *) p;
776
777 if (length > 0 && s[length - 1] != '\0') {
778 wl_log(fmt: "string not nul-terminated, "
779 "message %s(%s)\n",
780 message->name, message->signature);
781 errno = EINVAL;
782 goto err;
783 }
784
785 closure->args[i].s = s;
786 p = next;
787 break;
788 case 'o':
789 id = *p++;
790 closure->args[i].n = id;
791
792 if (id == 0 && !arg.nullable) {
793 wl_log(fmt: "NULL object received on non-nullable "
794 "type, message %s(%s)\n", message->name,
795 message->signature);
796 errno = EINVAL;
797 goto err;
798 }
799 break;
800 case 'n':
801 id = *p++;
802 closure->args[i].n = id;
803
804 if (id == 0 && !arg.nullable) {
805 wl_log(fmt: "NULL new ID received on non-nullable "
806 "type, message %s(%s)\n", message->name,
807 message->signature);
808 errno = EINVAL;
809 goto err;
810 }
811
812 if (wl_map_reserve_new(map: objects, i: id) < 0) {
813 wl_log(fmt: "not a valid new object id (%u), "
814 "message %s(%s)\n",
815 id, message->name, message->signature);
816 errno = EINVAL;
817 goto err;
818 }
819
820 break;
821 case 'a':
822 length = *p++;
823
824 length_in_u32 = div_roundup(n: length, a: sizeof *p);
825 if ((uint32_t) (end - p) < length_in_u32) {
826 wl_log(fmt: "message too short, "
827 "object (%d), message %s(%s)\n",
828 closure->sender_id, message->name,
829 message->signature);
830 errno = EINVAL;
831 goto err;
832 }
833 next = p + length_in_u32;
834
835 array_extra->size = length;
836 array_extra->alloc = 0;
837 array_extra->data = p;
838
839 closure->args[i].a = array_extra++;
840 p = next;
841 break;
842 case 'h':
843 if (connection->fds_in.tail == connection->fds_in.head) {
844 wl_log(fmt: "file descriptor expected, "
845 "object (%d), message %s(%s)\n",
846 closure->sender_id, message->name,
847 message->signature);
848 errno = EINVAL;
849 goto err;
850 }
851
852 ring_buffer_copy(b: &connection->fds_in, data: &fd, count: sizeof fd);
853 connection->fds_in.tail += sizeof fd;
854 closure->args[i].h = fd;
855 break;
856 default:
857 wl_abort(fmt: "unknown type\n");
858 break;
859 }
860 }
861
862 wl_connection_consume(connection, size);
863
864 return closure;
865
866 err:
867 wl_closure_destroy(closure);
868 wl_connection_consume(connection, size);
869
870 return NULL;
871}
872
873bool
874wl_object_is_zombie(struct wl_map *map, uint32_t id)
875{
876 uint32_t flags;
877
878 /* Zombie objects only exist on the client side. */
879 if (map->side == WL_MAP_SERVER_SIDE)
880 return false;
881
882 /* Zombie objects can only have been created by the client. */
883 if (id >= WL_SERVER_ID_START)
884 return false;
885
886 flags = wl_map_lookup_flags(map, i: id);
887 return !!(flags & WL_MAP_ENTRY_ZOMBIE);
888}
889
890int
891wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects)
892{
893 struct wl_object *object;
894 const struct wl_message *message;
895 const char *signature;
896 struct argument_details arg;
897 int i, count;
898 uint32_t id;
899
900 message = closure->message;
901 signature = message->signature;
902 count = arg_count_for_signature(signature);
903 for (i = 0; i < count; i++) {
904 signature = get_next_argument(signature, details: &arg);
905 switch (arg.type) {
906 case 'o':
907 id = closure->args[i].n;
908 closure->args[i].o = NULL;
909
910 object = wl_map_lookup(map: objects, i: id);
911 if (wl_object_is_zombie(map: objects, id)) {
912 /* references object we've already
913 * destroyed client side */
914 object = NULL;
915 } else if (object == NULL && id != 0) {
916 wl_log(fmt: "unknown object (%u), message %s(%s)\n",
917 id, message->name, message->signature);
918 errno = EINVAL;
919 return -1;
920 }
921
922 if (object != NULL && message->types[i] != NULL &&
923 !wl_interface_equal(iface1: (object)->interface,
924 iface2: message->types[i])) {
925 wl_log(fmt: "invalid object (%u), type (%s), "
926 "message %s(%s)\n",
927 id, (object)->interface->name,
928 message->name, message->signature);
929 errno = EINVAL;
930 return -1;
931 }
932 closure->args[i].o = object;
933 }
934 }
935
936 return 0;
937}
938
939static void
940convert_arguments_to_ffi(const char *signature, uint32_t flags,
941 union wl_argument *args,
942 int count, ffi_type **ffi_types, void** ffi_args)
943{
944 int i;
945 const char *sig_iter;
946 struct argument_details arg;
947
948 sig_iter = signature;
949 for (i = 0; i < count; i++) {
950 sig_iter = get_next_argument(signature: sig_iter, details: &arg);
951
952 switch(arg.type) {
953 case 'i':
954 ffi_types[i] = &ffi_type_sint32;
955 ffi_args[i] = &args[i].i;
956 break;
957 case 'u':
958 ffi_types[i] = &ffi_type_uint32;
959 ffi_args[i] = &args[i].u;
960 break;
961 case 'f':
962 ffi_types[i] = &ffi_type_sint32;
963 ffi_args[i] = &args[i].f;
964 break;
965 case 's':
966 ffi_types[i] = &ffi_type_pointer;
967 ffi_args[i] = &args[i].s;
968 break;
969 case 'o':
970 ffi_types[i] = &ffi_type_pointer;
971 ffi_args[i] = &args[i].o;
972 break;
973 case 'n':
974 if (flags & WL_CLOSURE_INVOKE_CLIENT) {
975 ffi_types[i] = &ffi_type_pointer;
976 ffi_args[i] = &args[i].o;
977 } else {
978 ffi_types[i] = &ffi_type_uint32;
979 ffi_args[i] = &args[i].n;
980 }
981 break;
982 case 'a':
983 ffi_types[i] = &ffi_type_pointer;
984 ffi_args[i] = &args[i].a;
985 break;
986 case 'h':
987 ffi_types[i] = &ffi_type_sint32;
988 ffi_args[i] = &args[i].h;
989 break;
990 default:
991 wl_abort(fmt: "unknown type\n");
992 break;
993 }
994 }
995}
996
997void
998wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
999 struct wl_object *target, uint32_t opcode, void *data)
1000{
1001 int count;
1002 ffi_cif cif;
1003 ffi_type *ffi_types[WL_CLOSURE_MAX_ARGS + 2];
1004 void * ffi_args[WL_CLOSURE_MAX_ARGS + 2];
1005 void (* const *implementation)(void);
1006
1007 count = arg_count_for_signature(signature: closure->message->signature);
1008
1009 ffi_types[0] = &ffi_type_pointer;
1010 ffi_args[0] = &data;
1011 ffi_types[1] = &ffi_type_pointer;
1012 ffi_args[1] = &target;
1013
1014 convert_arguments_to_ffi(signature: closure->message->signature, flags, args: closure->args,
1015 count, ffi_types: ffi_types + 2, ffi_args: ffi_args + 2);
1016
1017 ffi_prep_cif(cif: &cif, abi: FFI_DEFAULT_ABI,
1018 nargs: count + 2, rtype: &ffi_type_void, atypes: ffi_types);
1019
1020 implementation = target->implementation;
1021 if (!implementation[opcode]) {
1022 wl_abort(fmt: "listener function for opcode %u of %s is NULL\n",
1023 opcode, target->interface->name);
1024 }
1025 ffi_call(cif: &cif, fn: implementation[opcode], NULL, avalue: ffi_args);
1026
1027 wl_closure_clear_fds(closure);
1028}
1029
1030void
1031wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
1032 struct wl_object *target, uint32_t opcode)
1033{
1034 dispatcher(target->implementation, target, opcode, closure->message,
1035 closure->args);
1036
1037 wl_closure_clear_fds(closure);
1038}
1039
1040static int
1041copy_fds_to_connection(struct wl_closure *closure,
1042 struct wl_connection *connection)
1043{
1044 const struct wl_message *message = closure->message;
1045 uint32_t i, count;
1046 struct argument_details arg;
1047 const char *signature = message->signature;
1048 int fd;
1049
1050 count = arg_count_for_signature(signature);
1051 for (i = 0; i < count; i++) {
1052 signature = get_next_argument(signature, details: &arg);
1053 if (arg.type != 'h')
1054 continue;
1055
1056 fd = closure->args[i].h;
1057 if (wl_connection_put_fd(connection, fd)) {
1058 wl_log(fmt: "request could not be marshaled: "
1059 "can't send file descriptor\n");
1060 return -1;
1061 }
1062 closure->args[i].h = -1;
1063 }
1064
1065 return 0;
1066}
1067
1068
1069static uint32_t
1070buffer_size_for_closure(struct wl_closure *closure)
1071{
1072 const struct wl_message *message = closure->message;
1073 int i, count;
1074 struct argument_details arg;
1075 const char *signature;
1076 uint32_t size, buffer_size = 0;
1077
1078 signature = message->signature;
1079 count = arg_count_for_signature(signature);
1080 for (i = 0; i < count; i++) {
1081 signature = get_next_argument(signature, details: &arg);
1082
1083 switch (arg.type) {
1084 case 'h':
1085 break;
1086 case 'u':
1087 case 'i':
1088 case 'f':
1089 case 'o':
1090 case 'n':
1091 buffer_size++;
1092 break;
1093 case 's':
1094 if (closure->args[i].s == NULL) {
1095 buffer_size++;
1096 break;
1097 }
1098
1099 size = strlen(s: closure->args[i].s) + 1;
1100 buffer_size += 1 + div_roundup(n: size, a: sizeof(uint32_t));
1101 break;
1102 case 'a':
1103 if (closure->args[i].a == NULL) {
1104 buffer_size++;
1105 break;
1106 }
1107
1108 size = closure->args[i].a->size;
1109 buffer_size += (1 + div_roundup(n: size, a: sizeof(uint32_t)));
1110 break;
1111 default:
1112 break;
1113 }
1114 }
1115
1116 return buffer_size + 2;
1117}
1118
1119static int
1120serialize_closure(struct wl_closure *closure, uint32_t *buffer,
1121 size_t buffer_count)
1122{
1123 const struct wl_message *message = closure->message;
1124 unsigned int i, count, size;
1125 uint32_t *p, *end;
1126 struct argument_details arg;
1127 const char *signature;
1128
1129 if (buffer_count < 2)
1130 goto overflow;
1131
1132 p = buffer + 2;
1133 end = buffer + buffer_count;
1134
1135 signature = message->signature;
1136 count = arg_count_for_signature(signature);
1137 for (i = 0; i < count; i++) {
1138 signature = get_next_argument(signature, details: &arg);
1139
1140 if (arg.type == 'h')
1141 continue;
1142
1143 if (p + 1 > end)
1144 goto overflow;
1145
1146 switch (arg.type) {
1147 case 'u':
1148 *p++ = closure->args[i].u;
1149 break;
1150 case 'i':
1151 *p++ = closure->args[i].i;
1152 break;
1153 case 'f':
1154 *p++ = closure->args[i].f;
1155 break;
1156 case 'o':
1157 *p++ = closure->args[i].o ? closure->args[i].o->id : 0;
1158 break;
1159 case 'n':
1160 *p++ = closure->args[i].n;
1161 break;
1162 case 's':
1163 if (closure->args[i].s == NULL) {
1164 *p++ = 0;
1165 break;
1166 }
1167
1168 size = strlen(s: closure->args[i].s) + 1;
1169 *p++ = size;
1170
1171 if (p + div_roundup(n: size, a: sizeof *p) > end)
1172 goto overflow;
1173
1174 memcpy(dest: p, src: closure->args[i].s, n: size);
1175 p += div_roundup(n: size, a: sizeof *p);
1176 break;
1177 case 'a':
1178 if (closure->args[i].a == NULL) {
1179 *p++ = 0;
1180 break;
1181 }
1182
1183 size = closure->args[i].a->size;
1184 *p++ = size;
1185
1186 if (p + div_roundup(n: size, a: sizeof *p) > end)
1187 goto overflow;
1188
1189 memcpy(dest: p, src: closure->args[i].a->data, n: size);
1190 p += div_roundup(n: size, a: sizeof *p);
1191 break;
1192 default:
1193 break;
1194 }
1195 }
1196
1197 size = (p - buffer) * sizeof *p;
1198
1199 buffer[0] = closure->sender_id;
1200 buffer[1] = size << 16 | (closure->opcode & 0x0000ffff);
1201
1202 return size;
1203
1204overflow:
1205 errno = ERANGE;
1206 return -1;
1207}
1208
1209int
1210wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
1211{
1212 int size;
1213 uint32_t buffer_size;
1214 uint32_t *buffer;
1215 int result;
1216
1217 if (copy_fds_to_connection(closure, connection))
1218 return -1;
1219
1220 buffer_size = buffer_size_for_closure(closure);
1221 buffer = zalloc(s: buffer_size * sizeof buffer[0]);
1222 if (buffer == NULL)
1223 return -1;
1224
1225 size = serialize_closure(closure, buffer, buffer_count: buffer_size);
1226 if (size < 0) {
1227 free(ptr: buffer);
1228 return -1;
1229 }
1230
1231 result = wl_connection_write(connection, data: buffer, count: size);
1232 free(ptr: buffer);
1233
1234 return result;
1235}
1236
1237int
1238wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
1239{
1240 int size;
1241 uint32_t buffer_size;
1242 uint32_t *buffer;
1243 int result;
1244
1245 if (copy_fds_to_connection(closure, connection))
1246 return -1;
1247
1248 buffer_size = buffer_size_for_closure(closure);
1249 buffer = malloc(size: buffer_size * sizeof buffer[0]);
1250 if (buffer == NULL)
1251 return -1;
1252
1253 size = serialize_closure(closure, buffer, buffer_count: buffer_size);
1254 if (size < 0) {
1255 free(ptr: buffer);
1256 return -1;
1257 }
1258
1259 result = wl_connection_queue(connection, data: buffer, count: size);
1260 free(ptr: buffer);
1261
1262 return result;
1263}
1264
1265void
1266wl_closure_print(struct wl_closure *closure, struct wl_object *target,
1267 int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg))
1268{
1269 int i;
1270 struct argument_details arg;
1271 const char *signature = closure->message->signature;
1272 struct timespec tp;
1273 unsigned int time;
1274 uint32_t nval;
1275
1276 clock_gettime(CLOCK_REALTIME, tp: &tp);
1277 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
1278
1279 fprintf(stderr, format: "[%7u.%03u] %s%s%s@%u.%s(",
1280 time / 1000, time % 1000,
1281 discarded ? "discarded " : "",
1282 send ? " -> " : "",
1283 target->interface->name, target->id,
1284 closure->message->name);
1285
1286 for (i = 0; i < closure->count; i++) {
1287 signature = get_next_argument(signature, details: &arg);
1288 if (i > 0)
1289 fprintf(stderr, format: ", ");
1290
1291 switch (arg.type) {
1292 case 'u':
1293 fprintf(stderr, format: "%u", closure->args[i].u);
1294 break;
1295 case 'i':
1296 fprintf(stderr, format: "%d", closure->args[i].i);
1297 break;
1298 case 'f':
1299 /* The magic number 390625 is 1e8 / 256 */
1300 if (closure->args[i].f >= 0) {
1301 fprintf(stderr, format: "%d.%08d",
1302 closure->args[i].f / 256,
1303 390625 * (closure->args[i].f % 256));
1304 } else {
1305
1306 fprintf(stderr, format: "-%d.%08d",
1307 closure->args[i].f / -256,
1308 -390625 * (closure->args[i].f % 256));
1309 }
1310 break;
1311 case 's':
1312 if (closure->args[i].s)
1313 fprintf(stderr, format: "\"%s\"", closure->args[i].s);
1314 else
1315 fprintf(stderr, format: "nil");
1316 break;
1317 case 'o':
1318 if (closure->args[i].o)
1319 fprintf(stderr, format: "%s@%u",
1320 closure->args[i].o->interface->name,
1321 closure->args[i].o->id);
1322 else
1323 fprintf(stderr, format: "nil");
1324 break;
1325 case 'n':
1326 if (n_parse)
1327 nval = n_parse(&closure->args[i]);
1328 else
1329 nval = closure->args[i].n;
1330
1331 fprintf(stderr, format: "new id %s@",
1332 (closure->message->types[i]) ?
1333 closure->message->types[i]->name :
1334 "[unknown]");
1335 if (nval != 0)
1336 fprintf(stderr, format: "%u", nval);
1337 else
1338 fprintf(stderr, format: "nil");
1339 break;
1340 case 'a':
1341 fprintf(stderr, format: "array[%zu]", closure->args[i].a->size);
1342 break;
1343 case 'h':
1344 fprintf(stderr, format: "fd %d", closure->args[i].h);
1345 break;
1346 }
1347 }
1348
1349 fprintf(stderr, format: ")\n");
1350}
1351
1352static int
1353wl_closure_close_fds(struct wl_closure *closure)
1354{
1355 int i;
1356 struct argument_details arg;
1357 const char *signature = closure->message->signature;
1358
1359 for (i = 0; i < closure->count; i++) {
1360 signature = get_next_argument(signature, details: &arg);
1361 if (arg.type == 'h' && closure->args[i].h != -1)
1362 close(fd: closure->args[i].h);
1363 }
1364
1365 return 0;
1366}
1367
1368void
1369wl_closure_destroy(struct wl_closure *closure)
1370{
1371 /* wl_closure_destroy has free() semantics */
1372 if (!closure)
1373 return;
1374
1375 wl_closure_close_fds(closure);
1376 free(ptr: closure);
1377}
1378

source code of gtk/subprojects/wayland/src/connection.c