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 | static inline uint32_t |
48 | div_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 | |
57 | struct 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 | |
67 | struct 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 | |
74 | static int |
75 | ring_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 | |
100 | static void |
101 | ring_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 | |
124 | static void |
125 | ring_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 | |
148 | static void |
149 | ring_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 | |
163 | static uint32_t |
164 | ring_buffer_size(struct wl_ring_buffer *b) |
165 | { |
166 | return b->head - b->tail; |
167 | } |
168 | |
169 | struct wl_connection * |
170 | wl_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 | |
183 | static void |
184 | close_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 | |
203 | void |
204 | wl_connection_close_fds_in(struct wl_connection *connection, int max) |
205 | { |
206 | close_fds(buffer: &connection->fds_in, max); |
207 | } |
208 | |
209 | int |
210 | wl_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 | |
221 | void |
222 | wl_connection_copy(struct wl_connection *connection, void *data, size_t size) |
223 | { |
224 | ring_buffer_copy(b: &connection->in, data, count: size); |
225 | } |
226 | |
227 | void |
228 | wl_connection_consume(struct wl_connection *connection, size_t size) |
229 | { |
230 | connection->in.tail += size; |
231 | } |
232 | |
233 | static void |
234 | build_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 | |
255 | static int |
256 | decode_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 | |
288 | int |
289 | wl_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 | |
332 | uint32_t |
333 | wl_connection_pending_input(struct wl_connection *connection) |
334 | { |
335 | return ring_buffer_size(b: &connection->in); |
336 | } |
337 | |
338 | int |
339 | wl_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 | |
377 | int |
378 | wl_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 | |
396 | int |
397 | wl_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 | |
410 | int |
411 | wl_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 | |
423 | int |
424 | wl_connection_get_fd(struct wl_connection *connection) |
425 | { |
426 | return connection->fd; |
427 | } |
428 | |
429 | static int |
430 | wl_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 | |
441 | const char * |
442 | get_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 | |
465 | int |
466 | arg_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 | |
485 | int |
486 | wl_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 | |
498 | void |
499 | wl_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 | |
541 | static void |
542 | wl_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 | |
555 | static struct wl_closure * |
556 | wl_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 | |
599 | struct wl_closure * |
600 | wl_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 | |
666 | err_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 | |
675 | struct wl_closure * |
676 | wl_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 | |
687 | struct wl_closure * |
688 | wl_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 *; |
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 | |
873 | bool |
874 | wl_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 | |
890 | int |
891 | wl_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 | |
939 | static void |
940 | convert_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 | |
997 | void |
998 | wl_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] = ⌖ |
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 | |
1030 | void |
1031 | wl_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 | |
1040 | static int |
1041 | copy_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 | |
1069 | static uint32_t |
1070 | buffer_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 | |
1119 | static int |
1120 | serialize_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 | |
1204 | overflow: |
1205 | errno = ERANGE; |
1206 | return -1; |
1207 | } |
1208 | |
1209 | int |
1210 | wl_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 | |
1237 | int |
1238 | wl_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 | |
1265 | void |
1266 | wl_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 | |
1352 | static int |
1353 | wl_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 | |
1368 | void |
1369 | wl_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 | |