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
47 #define DIV_ROUNDUP(n, a) ( ((n) + ((a) - 1)) / (a) )
48
49 struct wl_buffer {
50 char data[4096];
51 uint32_t head, tail;
52 };
53
54 #define MASK(i) ((i) & 4095)
55
56 #define MAX_FDS_OUT 28
57 #define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
58
59 struct wl_connection {
60 struct wl_buffer in, out;
61 struct wl_buffer fds_in, fds_out;
62 int fd;
63 int want_flush;
64 };
65
66 static int
wl_buffer_put(struct wl_buffer * b,const void * data,size_t count)67 wl_buffer_put(struct wl_buffer *b, const void *data, size_t count)
68 {
69 uint32_t head, size;
70
71 if (count > sizeof(b->data)) {
72 wl_log("Data too big for buffer (%d > %d).\n",
73 count, sizeof(b->data));
74 errno = E2BIG;
75 return -1;
76 }
77
78 head = MASK(b->head);
79 if (head + count <= sizeof b->data) {
80 memcpy(b->data + head, data, count);
81 } else {
82 size = sizeof b->data - head;
83 memcpy(b->data + head, data, size);
84 memcpy(b->data, (const char *) data + size, count - size);
85 }
86
87 b->head += count;
88
89 return 0;
90 }
91
92 static void
wl_buffer_put_iov(struct wl_buffer * b,struct iovec * iov,int * count)93 wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count)
94 {
95 uint32_t head, tail;
96
97 head = MASK(b->head);
98 tail = MASK(b->tail);
99 if (head < tail) {
100 iov[0].iov_base = b->data + head;
101 iov[0].iov_len = tail - head;
102 *count = 1;
103 } else if (tail == 0) {
104 iov[0].iov_base = b->data + head;
105 iov[0].iov_len = sizeof b->data - head;
106 *count = 1;
107 } else {
108 iov[0].iov_base = b->data + head;
109 iov[0].iov_len = sizeof b->data - head;
110 iov[1].iov_base = b->data;
111 iov[1].iov_len = tail;
112 *count = 2;
113 }
114 }
115
116 static void
wl_buffer_get_iov(struct wl_buffer * b,struct iovec * iov,int * count)117 wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count)
118 {
119 uint32_t head, tail;
120
121 head = MASK(b->head);
122 tail = MASK(b->tail);
123 if (tail < head) {
124 iov[0].iov_base = b->data + tail;
125 iov[0].iov_len = head - tail;
126 *count = 1;
127 } else if (head == 0) {
128 iov[0].iov_base = b->data + tail;
129 iov[0].iov_len = sizeof b->data - tail;
130 *count = 1;
131 } else {
132 iov[0].iov_base = b->data + tail;
133 iov[0].iov_len = sizeof b->data - tail;
134 iov[1].iov_base = b->data;
135 iov[1].iov_len = head;
136 *count = 2;
137 }
138 }
139
140 static void
wl_buffer_copy(struct wl_buffer * b,void * data,size_t count)141 wl_buffer_copy(struct wl_buffer *b, void *data, size_t count)
142 {
143 uint32_t tail, size;
144
145 tail = MASK(b->tail);
146 if (tail + count <= sizeof b->data) {
147 memcpy(data, b->data + tail, count);
148 } else {
149 size = sizeof b->data - tail;
150 memcpy(data, b->data + tail, size);
151 memcpy((char *) data + size, b->data, count - size);
152 }
153 }
154
155 static uint32_t
wl_buffer_size(struct wl_buffer * b)156 wl_buffer_size(struct wl_buffer *b)
157 {
158 return b->head - b->tail;
159 }
160
161 struct wl_connection *
wl_connection_create(int fd)162 wl_connection_create(int fd)
163 {
164 struct wl_connection *connection;
165
166 connection = zalloc(sizeof *connection);
167 if (connection == NULL)
168 return NULL;
169
170 connection->fd = fd;
171
172 return connection;
173 }
174
175 static void
close_fds(struct wl_buffer * buffer,int max)176 close_fds(struct wl_buffer *buffer, int max)
177 {
178 int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
179 size_t size;
180
181 size = buffer->head - buffer->tail;
182 if (size == 0)
183 return;
184
185 wl_buffer_copy(buffer, fds, size);
186 count = size / sizeof fds[0];
187 if (max > 0 && max < count)
188 count = max;
189 for (i = 0; i < count; i++)
190 close(fds[i]);
191 buffer->tail += size;
192 }
193
194 int
wl_connection_destroy(struct wl_connection * connection)195 wl_connection_destroy(struct wl_connection *connection)
196 {
197 int fd = connection->fd;
198
199 close_fds(&connection->fds_out, -1);
200 close_fds(&connection->fds_in, -1);
201 free(connection);
202
203 return fd;
204 }
205
206 void
wl_connection_copy(struct wl_connection * connection,void * data,size_t size)207 wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
208 {
209 wl_buffer_copy(&connection->in, data, size);
210 }
211
212 void
wl_connection_consume(struct wl_connection * connection,size_t size)213 wl_connection_consume(struct wl_connection *connection, size_t size)
214 {
215 connection->in.tail += size;
216 }
217
218 static void
build_cmsg(struct wl_buffer * buffer,char * data,int * clen)219 build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
220 {
221 struct cmsghdr *cmsg;
222 size_t size;
223
224 size = buffer->head - buffer->tail;
225 if (size > MAX_FDS_OUT * sizeof(int32_t))
226 size = MAX_FDS_OUT * sizeof(int32_t);
227
228 if (size > 0) {
229 cmsg = (struct cmsghdr *) data;
230 cmsg->cmsg_level = SOL_SOCKET;
231 cmsg->cmsg_type = SCM_RIGHTS;
232 cmsg->cmsg_len = CMSG_LEN(size);
233 wl_buffer_copy(buffer, CMSG_DATA(cmsg), size);
234 *clen = cmsg->cmsg_len;
235 } else {
236 *clen = 0;
237 }
238 }
239
240 static int
decode_cmsg(struct wl_buffer * buffer,struct msghdr * msg)241 decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
242 {
243 struct cmsghdr *cmsg;
244 size_t size, max, i;
245 int overflow = 0;
246
247 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
248 cmsg = CMSG_NXTHDR(msg, cmsg)) {
249 if (cmsg->cmsg_level != SOL_SOCKET ||
250 cmsg->cmsg_type != SCM_RIGHTS)
251 continue;
252
253 size = cmsg->cmsg_len - CMSG_LEN(0);
254 max = sizeof(buffer->data) - wl_buffer_size(buffer);
255 if (size > max || overflow) {
256 overflow = 1;
257 size /= sizeof(int32_t);
258 for (i = 0; i < size; i++)
259 close(((int*)CMSG_DATA(cmsg))[i]);
260 } else if (wl_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) {
261 return -1;
262 }
263 }
264
265 if (overflow) {
266 errno = EOVERFLOW;
267 return -1;
268 }
269
270 return 0;
271 }
272
273 int
wl_connection_flush(struct wl_connection * connection)274 wl_connection_flush(struct wl_connection *connection)
275 {
276 struct iovec iov[2];
277 struct msghdr msg;
278 char cmsg[CLEN];
279 int len = 0, count, clen;
280 uint32_t tail;
281
282 if (!connection->want_flush)
283 return 0;
284
285 tail = connection->out.tail;
286 while (connection->out.head - connection->out.tail > 0) {
287 wl_buffer_get_iov(&connection->out, iov, &count);
288
289 build_cmsg(&connection->fds_out, cmsg, &clen);
290
291 msg.msg_name = NULL;
292 msg.msg_namelen = 0;
293 msg.msg_iov = iov;
294 msg.msg_iovlen = count;
295 msg.msg_control = (clen > 0) ? cmsg : NULL;
296 msg.msg_controllen = clen;
297 msg.msg_flags = 0;
298
299 do {
300 len = sendmsg(connection->fd, &msg,
301 MSG_NOSIGNAL | MSG_DONTWAIT);
302 } while (len == -1 && errno == EINTR);
303
304 if (len == -1)
305 return -1;
306
307 close_fds(&connection->fds_out, MAX_FDS_OUT);
308
309 connection->out.tail += len;
310 }
311
312 connection->want_flush = 0;
313
314 return connection->out.head - tail;
315 }
316
317 uint32_t
wl_connection_pending_input(struct wl_connection * connection)318 wl_connection_pending_input(struct wl_connection *connection)
319 {
320 return wl_buffer_size(&connection->in);
321 }
322
323 int
wl_connection_read(struct wl_connection * connection)324 wl_connection_read(struct wl_connection *connection)
325 {
326 struct iovec iov[2];
327 struct msghdr msg;
328 char cmsg[CLEN];
329 int len, count, ret;
330
331 if (wl_buffer_size(&connection->in) >= sizeof(connection->in.data)) {
332 errno = EOVERFLOW;
333 return -1;
334 }
335
336 wl_buffer_put_iov(&connection->in, iov, &count);
337
338 msg.msg_name = NULL;
339 msg.msg_namelen = 0;
340 msg.msg_iov = iov;
341 msg.msg_iovlen = count;
342 msg.msg_control = cmsg;
343 msg.msg_controllen = sizeof cmsg;
344 msg.msg_flags = 0;
345
346 do {
347 len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT);
348 } while (len < 0 && errno == EINTR);
349
350 if (len <= 0)
351 return len;
352
353 ret = decode_cmsg(&connection->fds_in, &msg);
354 if (ret)
355 return -1;
356
357 connection->in.head += len;
358
359 return wl_connection_pending_input(connection);
360 }
361
362 int
wl_connection_write(struct wl_connection * connection,const void * data,size_t count)363 wl_connection_write(struct wl_connection *connection,
364 const void *data, size_t count)
365 {
366 if (connection->out.head - connection->out.tail +
367 count > ARRAY_LENGTH(connection->out.data)) {
368 connection->want_flush = 1;
369 if (wl_connection_flush(connection) < 0)
370 return -1;
371 }
372
373 if (wl_buffer_put(&connection->out, data, count) < 0)
374 return -1;
375
376 connection->want_flush = 1;
377
378 return 0;
379 }
380
381 int
wl_connection_queue(struct wl_connection * connection,const void * data,size_t count)382 wl_connection_queue(struct wl_connection *connection,
383 const void *data, size_t count)
384 {
385 if (connection->out.head - connection->out.tail +
386 count > ARRAY_LENGTH(connection->out.data)) {
387 connection->want_flush = 1;
388 if (wl_connection_flush(connection) < 0)
389 return -1;
390 }
391
392 return wl_buffer_put(&connection->out, data, count);
393 }
394
395 int
wl_message_count_arrays(const struct wl_message * message)396 wl_message_count_arrays(const struct wl_message *message)
397 {
398 int i, arrays;
399
400 for (i = 0, arrays = 0; message->signature[i]; i++) {
401 if (message->signature[i] == 'a')
402 arrays++;
403 }
404
405 return arrays;
406 }
407
408 int
wl_connection_get_fd(struct wl_connection * connection)409 wl_connection_get_fd(struct wl_connection *connection)
410 {
411 return connection->fd;
412 }
413
414 static int
wl_connection_put_fd(struct wl_connection * connection,int32_t fd)415 wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
416 {
417 if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) {
418 connection->want_flush = 1;
419 if (wl_connection_flush(connection) < 0)
420 return -1;
421 }
422
423 return wl_buffer_put(&connection->fds_out, &fd, sizeof fd);
424 }
425
426 const char *
get_next_argument(const char * signature,struct argument_details * details)427 get_next_argument(const char *signature, struct argument_details *details)
428 {
429 details->nullable = 0;
430 for(; *signature; ++signature) {
431 switch(*signature) {
432 case 'i':
433 case 'u':
434 case 'f':
435 case 's':
436 case 'o':
437 case 'n':
438 case 'a':
439 case 'h':
440 details->type = *signature;
441 return signature + 1;
442 case '?':
443 details->nullable = 1;
444 }
445 }
446 details->type = '\0';
447 return signature;
448 }
449
450 int
arg_count_for_signature(const char * signature)451 arg_count_for_signature(const char *signature)
452 {
453 int count = 0;
454 for(; *signature; ++signature) {
455 switch(*signature) {
456 case 'i':
457 case 'u':
458 case 'f':
459 case 's':
460 case 'o':
461 case 'n':
462 case 'a':
463 case 'h':
464 ++count;
465 }
466 }
467 return count;
468 }
469
470 int
wl_message_get_since(const struct wl_message * message)471 wl_message_get_since(const struct wl_message *message)
472 {
473 int since;
474
475 since = atoi(message->signature);
476
477 if (since == 0)
478 since = 1;
479
480 return since;
481 }
482
483 void
wl_argument_from_va_list(const char * signature,union wl_argument * args,int count,va_list ap)484 wl_argument_from_va_list(const char *signature, union wl_argument *args,
485 int count, va_list ap)
486 {
487 int i;
488 const char *sig_iter;
489 struct argument_details arg;
490
491 sig_iter = signature;
492 for (i = 0; i < count; i++) {
493 sig_iter = get_next_argument(sig_iter, &arg);
494
495 switch(arg.type) {
496 case 'i':
497 args[i].i = va_arg(ap, int32_t);
498 break;
499 case 'u':
500 args[i].u = va_arg(ap, uint32_t);
501 break;
502 case 'f':
503 args[i].f = va_arg(ap, wl_fixed_t);
504 break;
505 case 's':
506 args[i].s = va_arg(ap, const char *);
507 break;
508 case 'o':
509 args[i].o = va_arg(ap, struct wl_object *);
510 break;
511 case 'n':
512 args[i].o = va_arg(ap, struct wl_object *);
513 break;
514 case 'a':
515 args[i].a = va_arg(ap, struct wl_array *);
516 break;
517 case 'h':
518 args[i].h = va_arg(ap, int32_t);
519 break;
520 case '\0':
521 return;
522 }
523 }
524 }
525
526 struct wl_closure *
wl_closure_marshal(struct wl_object * sender,uint32_t opcode,union wl_argument * args,const struct wl_message * message)527 wl_closure_marshal(struct wl_object *sender, uint32_t opcode,
528 union wl_argument *args,
529 const struct wl_message *message)
530 {
531 struct wl_closure *closure;
532 struct wl_object *object;
533 int i, count, fd, dup_fd;
534 const char *signature;
535 struct argument_details arg;
536
537 count = arg_count_for_signature(message->signature);
538 if (count > WL_CLOSURE_MAX_ARGS) {
539 wl_log("too many args (%d)\n", count);
540 errno = EINVAL;
541 return NULL;
542 }
543
544 closure = malloc(sizeof *closure);
545 if (closure == NULL) {
546 errno = ENOMEM;
547 return NULL;
548 }
549
550 memcpy(closure->args, args, count * sizeof *args);
551
552 signature = message->signature;
553 for (i = 0; i < count; i++) {
554 signature = get_next_argument(signature, &arg);
555
556 switch (arg.type) {
557 case 'f':
558 case 'u':
559 case 'i':
560 break;
561 case 's':
562 if (!arg.nullable && args[i].s == NULL)
563 goto err_null;
564 break;
565 case 'o':
566 if (!arg.nullable && args[i].o == NULL)
567 goto err_null;
568 break;
569 case 'n':
570 object = args[i].o;
571 if (!arg.nullable && object == NULL)
572 goto err_null;
573
574 closure->args[i].n = object ? object->id : 0;
575 break;
576 case 'a':
577 if (!arg.nullable && args[i].a == NULL)
578 goto err_null;
579 break;
580 case 'h':
581 fd = args[i].h;
582 dup_fd = wl_os_dupfd_cloexec(fd, 0);
583 if (dup_fd < 0)
584 wl_abort("dup failed: %s\n", strerror(errno));
585 closure->args[i].h = dup_fd;
586 break;
587 default:
588 wl_abort("unhandled format code: '%c'\n", arg.type);
589 break;
590 }
591 }
592
593 closure->sender_id = sender->id;
594 closure->opcode = opcode;
595 closure->message = message;
596 closure->count = count;
597
598 return closure;
599
600 err_null:
601 wl_closure_destroy(closure);
602 wl_log("error marshalling arguments for %s (signature %s): "
603 "null value passed for arg %i\n", message->name,
604 message->signature, i);
605 errno = EINVAL;
606 return NULL;
607 }
608
609 struct wl_closure *
wl_closure_vmarshal(struct wl_object * sender,uint32_t opcode,va_list ap,const struct wl_message * message)610 wl_closure_vmarshal(struct wl_object *sender, uint32_t opcode, va_list ap,
611 const struct wl_message *message)
612 {
613 union wl_argument args[WL_CLOSURE_MAX_ARGS];
614
615 wl_argument_from_va_list(message->signature, args,
616 WL_CLOSURE_MAX_ARGS, ap);
617
618 return wl_closure_marshal(sender, opcode, args, message);
619 }
620
621 struct wl_closure *
wl_connection_demarshal(struct wl_connection * connection,uint32_t size,struct wl_map * objects,const struct wl_message * message)622 wl_connection_demarshal(struct wl_connection *connection,
623 uint32_t size,
624 struct wl_map *objects,
625 const struct wl_message *message)
626 {
627 uint32_t *p, *next, *end, length, id;
628 int fd;
629 char *s;
630 unsigned int i, count, num_arrays;
631 const char *signature;
632 struct argument_details arg;
633 struct wl_closure *closure;
634 struct wl_array *array, *array_extra;
635
636 count = arg_count_for_signature(message->signature);
637 if (count > WL_CLOSURE_MAX_ARGS) {
638 wl_log("too many args (%d)\n", count);
639 errno = EINVAL;
640 wl_connection_consume(connection, size);
641 return NULL;
642 }
643
644 num_arrays = wl_message_count_arrays(message);
645 closure = malloc(sizeof *closure + size + num_arrays * sizeof *array);
646 if (closure == NULL) {
647 errno = ENOMEM;
648 wl_connection_consume(connection, size);
649 return NULL;
650 }
651
652 array_extra = closure->extra;
653 p = (uint32_t *)(closure->extra + num_arrays);
654 end = p + size / sizeof *p;
655
656 wl_connection_copy(connection, p, size);
657 closure->sender_id = *p++;
658 closure->opcode = *p++ & 0x0000ffff;
659
660 signature = message->signature;
661 for (i = 0; i < count; i++) {
662 signature = get_next_argument(signature, &arg);
663
664 if (arg.type != 'h' && p + 1 > end) {
665 wl_log("message too short, "
666 "object (%d), message %s(%s)\n",
667 *p, message->name, message->signature);
668 errno = EINVAL;
669 goto err;
670 }
671
672 switch (arg.type) {
673 case 'u':
674 closure->args[i].u = *p++;
675 break;
676 case 'i':
677 closure->args[i].i = *p++;
678 break;
679 case 'f':
680 closure->args[i].f = *p++;
681 break;
682 case 's':
683 length = *p++;
684
685 if (length == 0) {
686 closure->args[i].s = NULL;
687 break;
688 }
689
690 next = p + DIV_ROUNDUP(length, sizeof *p);
691 if (next > end) {
692 wl_log("message too short, "
693 "object (%d), message %s(%s)\n",
694 closure->sender_id, message->name,
695 message->signature);
696 errno = EINVAL;
697 goto err;
698 }
699
700 s = (char *) p;
701
702 if (length > 0 && s[length - 1] != '\0') {
703 wl_log("string not nul-terminated, "
704 "message %s(%s)\n",
705 message->name, message->signature);
706 errno = EINVAL;
707 goto err;
708 }
709
710 closure->args[i].s = s;
711 p = next;
712 break;
713 case 'o':
714 id = *p++;
715 closure->args[i].n = id;
716
717 if (id == 0 && !arg.nullable) {
718 wl_log("NULL object received on non-nullable "
719 "type, message %s(%s)\n", message->name,
720 message->signature);
721 errno = EINVAL;
722 goto err;
723 }
724 break;
725 case 'n':
726 id = *p++;
727 closure->args[i].n = id;
728
729 if (id == 0 && !arg.nullable) {
730 wl_log("NULL new ID received on non-nullable "
731 "type, message %s(%s)\n", message->name,
732 message->signature);
733 errno = EINVAL;
734 goto err;
735 }
736
737 if (wl_map_reserve_new(objects, id) < 0) {
738 wl_log("not a valid new object id (%u), "
739 "message %s(%s)\n",
740 id, message->name, message->signature);
741 errno = EINVAL;
742 goto err;
743 }
744
745 break;
746 case 'a':
747 length = *p++;
748
749 next = p + DIV_ROUNDUP(length, sizeof *p);
750 if (next > end) {
751 wl_log("message too short, "
752 "object (%d), message %s(%s)\n",
753 closure->sender_id, message->name,
754 message->signature);
755 errno = EINVAL;
756 goto err;
757 }
758
759 array_extra->size = length;
760 array_extra->alloc = 0;
761 array_extra->data = p;
762
763 closure->args[i].a = array_extra++;
764 p = next;
765 break;
766 case 'h':
767 if (connection->fds_in.tail == connection->fds_in.head) {
768 wl_log("file descriptor expected, "
769 "object (%d), message %s(%s)\n",
770 closure->sender_id, message->name,
771 message->signature);
772 errno = EINVAL;
773 goto err;
774 }
775
776 wl_buffer_copy(&connection->fds_in, &fd, sizeof fd);
777 connection->fds_in.tail += sizeof fd;
778 closure->args[i].h = fd;
779 break;
780 default:
781 wl_abort("unknown type\n");
782 break;
783 }
784 }
785
786 closure->count = count;
787 closure->message = message;
788
789 wl_connection_consume(connection, size);
790
791 return closure;
792
793 err:
794 wl_closure_destroy(closure);
795 wl_connection_consume(connection, size);
796
797 return NULL;
798 }
799
800 int
wl_closure_lookup_objects(struct wl_closure * closure,struct wl_map * objects)801 wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects)
802 {
803 struct wl_object *object;
804 const struct wl_message *message;
805 const char *signature;
806 struct argument_details arg;
807 int i, count;
808 uint32_t id;
809
810 message = closure->message;
811 signature = message->signature;
812 count = arg_count_for_signature(signature);
813 for (i = 0; i < count; i++) {
814 signature = get_next_argument(signature, &arg);
815 switch (arg.type) {
816 case 'o':
817 id = closure->args[i].n;
818 closure->args[i].o = NULL;
819
820 object = wl_map_lookup(objects, id);
821 if (object == WL_ZOMBIE_OBJECT) {
822 /* references object we've already
823 * destroyed client side */
824 object = NULL;
825 } else if (object == NULL && id != 0) {
826 wl_log("unknown object (%u), message %s(%s)\n",
827 id, message->name, message->signature);
828 errno = EINVAL;
829 return -1;
830 }
831
832 if (object != NULL && message->types[i] != NULL &&
833 !wl_interface_equal((object)->interface,
834 message->types[i])) {
835 wl_log("invalid object (%u), type (%s), "
836 "message %s(%s)\n",
837 id, (object)->interface->name,
838 message->name, message->signature);
839 errno = EINVAL;
840 return -1;
841 }
842 closure->args[i].o = object;
843 }
844 }
845
846 return 0;
847 }
848
849 static void
convert_arguments_to_ffi(const char * signature,uint32_t flags,union wl_argument * args,int count,ffi_type ** ffi_types,void ** ffi_args)850 convert_arguments_to_ffi(const char *signature, uint32_t flags,
851 union wl_argument *args,
852 int count, ffi_type **ffi_types, void** ffi_args)
853 {
854 int i;
855 const char *sig_iter;
856 struct argument_details arg;
857
858 sig_iter = signature;
859 for (i = 0; i < count; i++) {
860 sig_iter = get_next_argument(sig_iter, &arg);
861
862 switch(arg.type) {
863 case 'i':
864 ffi_types[i] = &ffi_type_sint32;
865 ffi_args[i] = &args[i].i;
866 break;
867 case 'u':
868 ffi_types[i] = &ffi_type_uint32;
869 ffi_args[i] = &args[i].u;
870 break;
871 case 'f':
872 ffi_types[i] = &ffi_type_sint32;
873 ffi_args[i] = &args[i].f;
874 break;
875 case 's':
876 ffi_types[i] = &ffi_type_pointer;
877 ffi_args[i] = &args[i].s;
878 break;
879 case 'o':
880 ffi_types[i] = &ffi_type_pointer;
881 ffi_args[i] = &args[i].o;
882 break;
883 case 'n':
884 if (flags & WL_CLOSURE_INVOKE_CLIENT) {
885 ffi_types[i] = &ffi_type_pointer;
886 ffi_args[i] = &args[i].o;
887 } else {
888 ffi_types[i] = &ffi_type_uint32;
889 ffi_args[i] = &args[i].n;
890 }
891 break;
892 case 'a':
893 ffi_types[i] = &ffi_type_pointer;
894 ffi_args[i] = &args[i].a;
895 break;
896 case 'h':
897 ffi_types[i] = &ffi_type_sint32;
898 ffi_args[i] = &args[i].h;
899 break;
900 default:
901 wl_abort("unknown type\n");
902 break;
903 }
904 }
905 }
906
907 void
wl_closure_invoke(struct wl_closure * closure,uint32_t flags,struct wl_object * target,uint32_t opcode,void * data)908 wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
909 struct wl_object *target, uint32_t opcode, void *data)
910 {
911 int count;
912 ffi_cif cif;
913 ffi_type *ffi_types[WL_CLOSURE_MAX_ARGS + 2];
914 void * ffi_args[WL_CLOSURE_MAX_ARGS + 2];
915 void (* const *implementation)(void);
916
917 count = arg_count_for_signature(closure->message->signature);
918
919 ffi_types[0] = &ffi_type_pointer;
920 ffi_args[0] = &data;
921 ffi_types[1] = &ffi_type_pointer;
922 ffi_args[1] = ⌖
923
924 convert_arguments_to_ffi(closure->message->signature, flags, closure->args,
925 count, ffi_types + 2, ffi_args + 2);
926
927 ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
928 count + 2, &ffi_type_void, ffi_types);
929
930 implementation = target->implementation;
931 if (!implementation[opcode]) {
932 wl_abort("listener function for opcode %u of %s is NULL\n",
933 opcode, target->interface->name);
934 }
935 ffi_call(&cif, implementation[opcode], NULL, ffi_args);
936 }
937
938 void
wl_closure_dispatch(struct wl_closure * closure,wl_dispatcher_func_t dispatcher,struct wl_object * target,uint32_t opcode)939 wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
940 struct wl_object *target, uint32_t opcode)
941 {
942 dispatcher(target->implementation, target, opcode, closure->message,
943 closure->args);
944 }
945
946 static int
copy_fds_to_connection(struct wl_closure * closure,struct wl_connection * connection)947 copy_fds_to_connection(struct wl_closure *closure,
948 struct wl_connection *connection)
949 {
950 const struct wl_message *message = closure->message;
951 uint32_t i, count;
952 struct argument_details arg;
953 const char *signature = message->signature;
954 int fd;
955
956 count = arg_count_for_signature(signature);
957 for (i = 0; i < count; i++) {
958 signature = get_next_argument(signature, &arg);
959 if (arg.type != 'h')
960 continue;
961
962 fd = closure->args[i].h;
963 if (wl_connection_put_fd(connection, fd)) {
964 wl_log("request could not be marshaled: "
965 "can't send file descriptor");
966 return -1;
967 }
968 }
969
970 return 0;
971 }
972
973
974 static uint32_t
buffer_size_for_closure(struct wl_closure * closure)975 buffer_size_for_closure(struct wl_closure *closure)
976 {
977 const struct wl_message *message = closure->message;
978 int i, count;
979 struct argument_details arg;
980 const char *signature;
981 uint32_t size, buffer_size = 0;
982
983 signature = message->signature;
984 count = arg_count_for_signature(signature);
985 for (i = 0; i < count; i++) {
986 signature = get_next_argument(signature, &arg);
987
988 switch (arg.type) {
989 case 'h':
990 break;
991 case 'u':
992 case 'i':
993 case 'f':
994 case 'o':
995 case 'n':
996 buffer_size++;
997 break;
998 case 's':
999 if (closure->args[i].s == NULL) {
1000 buffer_size++;
1001 break;
1002 }
1003
1004 size = strlen(closure->args[i].s) + 1;
1005 buffer_size += 1 + DIV_ROUNDUP(size, sizeof(uint32_t));
1006 break;
1007 case 'a':
1008 if (closure->args[i].a == NULL) {
1009 buffer_size++;
1010 break;
1011 }
1012
1013 size = closure->args[i].a->size;
1014 buffer_size += (1 + DIV_ROUNDUP(size, sizeof(uint32_t)));
1015 break;
1016 default:
1017 break;
1018 }
1019 }
1020
1021 return buffer_size + 2;
1022 }
1023
1024 static int
serialize_closure(struct wl_closure * closure,uint32_t * buffer,size_t buffer_count)1025 serialize_closure(struct wl_closure *closure, uint32_t *buffer,
1026 size_t buffer_count)
1027 {
1028 const struct wl_message *message = closure->message;
1029 unsigned int i, count, size;
1030 uint32_t *p, *end;
1031 struct argument_details arg;
1032 const char *signature;
1033
1034 if (buffer_count < 2)
1035 goto overflow;
1036
1037 p = buffer + 2;
1038 end = buffer + buffer_count;
1039
1040 signature = message->signature;
1041 count = arg_count_for_signature(signature);
1042 for (i = 0; i < count; i++) {
1043 signature = get_next_argument(signature, &arg);
1044
1045 if (arg.type == 'h')
1046 continue;
1047
1048 if (p + 1 > end)
1049 goto overflow;
1050
1051 switch (arg.type) {
1052 case 'u':
1053 *p++ = closure->args[i].u;
1054 break;
1055 case 'i':
1056 *p++ = closure->args[i].i;
1057 break;
1058 case 'f':
1059 *p++ = closure->args[i].f;
1060 break;
1061 case 'o':
1062 *p++ = closure->args[i].o ? closure->args[i].o->id : 0;
1063 break;
1064 case 'n':
1065 *p++ = closure->args[i].n;
1066 break;
1067 case 's':
1068 if (closure->args[i].s == NULL) {
1069 *p++ = 0;
1070 break;
1071 }
1072
1073 size = strlen(closure->args[i].s) + 1;
1074 *p++ = size;
1075
1076 if (p + DIV_ROUNDUP(size, sizeof *p) > end)
1077 goto overflow;
1078
1079 memcpy(p, closure->args[i].s, size);
1080 p += DIV_ROUNDUP(size, sizeof *p);
1081 break;
1082 case 'a':
1083 if (closure->args[i].a == NULL) {
1084 *p++ = 0;
1085 break;
1086 }
1087
1088 size = closure->args[i].a->size;
1089 *p++ = size;
1090
1091 if (p + DIV_ROUNDUP(size, sizeof *p) > end)
1092 goto overflow;
1093
1094 memcpy(p, closure->args[i].a->data, size);
1095 p += DIV_ROUNDUP(size, sizeof *p);
1096 break;
1097 default:
1098 break;
1099 }
1100 }
1101
1102 size = (p - buffer) * sizeof *p;
1103
1104 buffer[0] = closure->sender_id;
1105 buffer[1] = size << 16 | (closure->opcode & 0x0000ffff);
1106
1107 return size;
1108
1109 overflow:
1110 errno = ERANGE;
1111 return -1;
1112 }
1113
1114 int
wl_closure_send(struct wl_closure * closure,struct wl_connection * connection)1115 wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
1116 {
1117 int size;
1118 uint32_t buffer_size;
1119 uint32_t *buffer;
1120 int result;
1121
1122 if (copy_fds_to_connection(closure, connection))
1123 return -1;
1124
1125 buffer_size = buffer_size_for_closure(closure);
1126 buffer = zalloc(buffer_size * sizeof buffer[0]);
1127 if (buffer == NULL)
1128 return -1;
1129
1130 size = serialize_closure(closure, buffer, buffer_size);
1131 if (size < 0) {
1132 free(buffer);
1133 return -1;
1134 }
1135
1136 result = wl_connection_write(connection, buffer, size);
1137 free(buffer);
1138
1139 return result;
1140 }
1141
1142 int
wl_closure_queue(struct wl_closure * closure,struct wl_connection * connection)1143 wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
1144 {
1145 int size;
1146 uint32_t buffer_size;
1147 uint32_t *buffer;
1148 int result;
1149
1150 if (copy_fds_to_connection(closure, connection))
1151 return -1;
1152
1153 buffer_size = buffer_size_for_closure(closure);
1154 buffer = malloc(buffer_size * sizeof buffer[0]);
1155 if (buffer == NULL)
1156 return -1;
1157
1158 size = serialize_closure(closure, buffer, buffer_size);
1159 if (size < 0) {
1160 free(buffer);
1161 return -1;
1162 }
1163
1164 result = wl_connection_queue(connection, buffer, size);
1165 free(buffer);
1166
1167 return result;
1168 }
1169
1170 void
wl_closure_print(struct wl_closure * closure,struct wl_object * target,int send)1171 wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
1172 {
1173 int i;
1174 struct argument_details arg;
1175 const char *signature = closure->message->signature;
1176 struct timespec tp;
1177 unsigned int time;
1178
1179 clock_gettime(CLOCK_REALTIME, &tp);
1180 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
1181
1182 fprintf(stderr, "[%10.3f] %s%s@%u.%s(",
1183 time / 1000.0,
1184 send ? " -> " : "",
1185 target->interface->name, target->id,
1186 closure->message->name);
1187
1188 for (i = 0; i < closure->count; i++) {
1189 signature = get_next_argument(signature, &arg);
1190 if (i > 0)
1191 fprintf(stderr, ", ");
1192
1193 switch (arg.type) {
1194 case 'u':
1195 fprintf(stderr, "%u", closure->args[i].u);
1196 break;
1197 case 'i':
1198 fprintf(stderr, "%d", closure->args[i].i);
1199 break;
1200 case 'f':
1201 fprintf(stderr, "%f",
1202 wl_fixed_to_double(closure->args[i].f));
1203 break;
1204 case 's':
1205 fprintf(stderr, "\"%s\"", closure->args[i].s);
1206 break;
1207 case 'o':
1208 if (closure->args[i].o)
1209 fprintf(stderr, "%s@%u",
1210 closure->args[i].o->interface->name,
1211 closure->args[i].o->id);
1212 else
1213 fprintf(stderr, "nil");
1214 break;
1215 case 'n':
1216 fprintf(stderr, "new id %s@",
1217 (closure->message->types[i]) ?
1218 closure->message->types[i]->name :
1219 "[unknown]");
1220 if (closure->args[i].n != 0)
1221 fprintf(stderr, "%u", closure->args[i].n);
1222 else
1223 fprintf(stderr, "nil");
1224 break;
1225 case 'a':
1226 fprintf(stderr, "array");
1227 break;
1228 case 'h':
1229 fprintf(stderr, "fd %d", closure->args[i].h);
1230 break;
1231 }
1232 }
1233
1234 fprintf(stderr, ")\n");
1235 }
1236
1237 void
wl_closure_destroy(struct wl_closure * closure)1238 wl_closure_destroy(struct wl_closure *closure)
1239 {
1240 free(closure);
1241 }
1242