9a5381e6564891cf0e631e91c83a0b903ee60ac1
[profile/ivi/wayland.git] / src / connection.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #define _GNU_SOURCE
24
25 #include <math.h>
26 #include <stdlib.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <sys/uio.h>
32 #include <assert.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <time.h>
38
39 #include "wayland-util.h"
40 #include "wayland-private.h"
41 #include "wayland-os.h"
42
43 #define DIV_ROUNDUP(n, a) ( ((n) + ((a) - 1)) / (a) )
44
45 struct wl_buffer {
46         char data[4096];
47         int head, tail;
48 };
49
50 #define MASK(i) ((i) & 4095)
51
52 #define MAX_FDS_OUT     28
53 #define CLEN            (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
54
55 struct wl_connection {
56         struct wl_buffer in, out;
57         struct wl_buffer fds_in, fds_out;
58         int fd;
59         void *data;
60         wl_connection_update_func_t update;
61         struct wl_closure receive_closure, send_closure;
62         int write_signalled;
63 };
64
65 union wl_value {
66         uint32_t uint32;
67         char *string;
68         struct wl_object *object;
69         uint32_t new_id;
70         struct wl_array *array;
71 };
72
73 static void
74 wl_buffer_put(struct wl_buffer *b, const void *data, size_t count)
75 {
76         int head, size;
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
90 static void
91 wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count)
92 {
93         int head, tail;
94
95         head = MASK(b->head);
96         tail = MASK(b->tail);
97         if (head < tail) {
98                 iov[0].iov_base = b->data + head;
99                 iov[0].iov_len = tail - head;
100                 *count = 1;
101         } else if (tail == 0) {
102                 iov[0].iov_base = b->data + head;
103                 iov[0].iov_len = sizeof b->data - head;
104                 *count = 1;
105         } else {
106                 iov[0].iov_base = b->data + head;
107                 iov[0].iov_len = sizeof b->data - head;
108                 iov[1].iov_base = b->data;
109                 iov[1].iov_len = tail;
110                 *count = 2;
111         }
112 }
113
114 static void
115 wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count)
116 {
117         int head, tail;
118
119         head = MASK(b->head);
120         tail = MASK(b->tail);
121         if (tail < head) {
122                 iov[0].iov_base = b->data + tail;
123                 iov[0].iov_len = head - tail;
124                 *count = 1;
125         } else if (head == 0) {
126                 iov[0].iov_base = b->data + tail;
127                 iov[0].iov_len = sizeof b->data - tail;
128                 *count = 1;
129         } else {
130                 iov[0].iov_base = b->data + tail;
131                 iov[0].iov_len = sizeof b->data - tail;
132                 iov[1].iov_base = b->data;
133                 iov[1].iov_len = head;
134                 *count = 2;
135         }
136 }
137
138 static void
139 wl_buffer_copy(struct wl_buffer *b, void *data, size_t count)
140 {
141         int tail, size;
142
143         tail = MASK(b->tail);
144         if (tail + count <= sizeof b->data) {
145                 memcpy(data, b->data + tail, count);
146         } else {
147                 size = sizeof b->data - tail;
148                 memcpy(data, b->data + tail, size);
149                 memcpy((char *) data + size, b->data, count - size);
150         }
151 }
152
153 static int
154 wl_buffer_size(struct wl_buffer *b)
155 {
156         return b->head - b->tail;
157 }
158
159 struct wl_connection *
160 wl_connection_create(int fd,
161                      wl_connection_update_func_t update,
162                      void *data)
163 {
164         struct wl_connection *connection;
165
166         connection = malloc(sizeof *connection);
167         if (connection == NULL)
168                 return NULL;
169         memset(connection, 0, sizeof *connection);
170         connection->fd = fd;
171         connection->update = update;
172         connection->data = data;
173
174         connection->update(connection,
175                            WL_CONNECTION_READABLE,
176                            connection->data);
177
178         return connection;
179 }
180
181 void
182 wl_connection_destroy(struct wl_connection *connection)
183 {
184         close(connection->fd);
185         free(connection);
186 }
187
188 void
189 wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
190 {
191         wl_buffer_copy(&connection->in, data, size);
192 }
193
194 void
195 wl_connection_consume(struct wl_connection *connection, size_t size)
196 {
197         connection->in.tail += size;
198 }
199
200 static void
201 build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
202 {
203         struct cmsghdr *cmsg;
204         size_t size;
205
206         size = buffer->head - buffer->tail;
207         if (size > 0) {
208                 cmsg = (struct cmsghdr *) data;
209                 cmsg->cmsg_level = SOL_SOCKET;
210                 cmsg->cmsg_type = SCM_RIGHTS;
211                 cmsg->cmsg_len = CMSG_LEN(size);
212                 wl_buffer_copy(buffer, CMSG_DATA(cmsg), size);
213                 *clen = cmsg->cmsg_len;
214         } else {
215                 *clen = 0;
216         }
217 }
218
219 static void
220 close_fds(struct wl_buffer *buffer)
221 {
222         int fds[MAX_FDS_OUT], i, count;
223         size_t size;
224
225         size = buffer->head - buffer->tail;
226         if (size == 0)
227                 return;
228
229         wl_buffer_copy(buffer, fds, size);
230         count = size / sizeof fds[0];
231         for (i = 0; i < count; i++)
232                 close(fds[i]);
233         buffer->tail += size;
234 }
235
236 static void
237 decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
238 {
239         struct cmsghdr *cmsg;
240         size_t size;
241
242         for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
243              cmsg = CMSG_NXTHDR(msg, cmsg)) {
244                 if (cmsg->cmsg_level == SOL_SOCKET &&
245                     cmsg->cmsg_type == SCM_RIGHTS) {
246                         size = cmsg->cmsg_len - CMSG_LEN(0);
247                         wl_buffer_put(buffer, CMSG_DATA(cmsg), size);
248                 }
249         }
250 }
251
252 int
253 wl_connection_data(struct wl_connection *connection, uint32_t mask)
254 {
255         struct iovec iov[2];
256         struct msghdr msg;
257         char cmsg[CLEN];
258         int len, count, clen;
259
260         if (mask & WL_CONNECTION_WRITABLE) {
261                 wl_buffer_get_iov(&connection->out, iov, &count);
262
263                 build_cmsg(&connection->fds_out, cmsg, &clen);
264
265                 msg.msg_name = NULL;
266                 msg.msg_namelen = 0;
267                 msg.msg_iov = iov;
268                 msg.msg_iovlen = count;
269                 msg.msg_control = cmsg;
270                 msg.msg_controllen = clen;
271                 msg.msg_flags = 0;
272
273                 do {
274                         len = sendmsg(connection->fd, &msg,
275                                       MSG_NOSIGNAL | MSG_DONTWAIT);
276                 } while (len < 0 && errno == EINTR);
277
278                 if (len == -1 && errno == EPIPE) {
279                         return -1;
280                 } else if (len < 0) {
281                         fprintf(stderr,
282                                 "write error for connection %p, fd %d: %m\n",
283                                 connection, connection->fd);
284                         return -1;
285                 }
286
287                 close_fds(&connection->fds_out);
288
289                 connection->out.tail += len;
290                 if (connection->out.tail == connection->out.head &&
291                     connection->write_signalled) {
292                         connection->update(connection,
293                                            WL_CONNECTION_READABLE,
294                                            connection->data);
295                         connection->write_signalled = 0;
296                 }
297         }
298
299         if (mask & WL_CONNECTION_READABLE) {
300                 wl_buffer_put_iov(&connection->in, iov, &count);
301
302                 msg.msg_name = NULL;
303                 msg.msg_namelen = 0;
304                 msg.msg_iov = iov;
305                 msg.msg_iovlen = count;
306                 msg.msg_control = cmsg;
307                 msg.msg_controllen = sizeof cmsg;
308                 msg.msg_flags = 0;
309
310                 do {
311                         len = wl_os_recvmsg_cloexec(connection->fd, &msg, 0);
312                 } while (len < 0 && errno == EINTR);
313
314                 if (len < 0) {
315                         fprintf(stderr,
316                                 "read error from connection %p: %m (%d)\n",
317                                 connection, errno);
318                         return -1;
319                 } else if (len == 0) {
320                         /* FIXME: Handle this better? */
321                         return -1;
322                 }
323
324                 decode_cmsg(&connection->fds_in, &msg);
325
326                 connection->in.head += len;
327         }       
328
329         return connection->in.head - connection->in.tail;
330 }
331
332 int
333 wl_connection_write(struct wl_connection *connection,
334                     const void *data, size_t count)
335 {
336         if (connection->out.head - connection->out.tail +
337             count > ARRAY_LENGTH(connection->out.data))
338                 if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
339                         return -1;
340
341         wl_buffer_put(&connection->out, data, count);
342
343         if (!connection->write_signalled) {
344                 connection->update(connection,
345                                    WL_CONNECTION_READABLE |
346                                    WL_CONNECTION_WRITABLE,
347                                    connection->data);
348                 connection->write_signalled = 1;
349         }
350
351         return 0;
352 }
353
354 int
355 wl_connection_queue(struct wl_connection *connection,
356                     const void *data, size_t count)
357 {
358         if (connection->out.head - connection->out.tail +
359             count > ARRAY_LENGTH(connection->out.data))
360                 if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
361                         return -1;
362
363         wl_buffer_put(&connection->out, data, count);
364
365         return 0;
366 }
367
368 static int
369 wl_message_size_extra(const struct wl_message *message)
370 {
371         int i, extra;
372
373         for (i = 0, extra = 0; message->signature[i]; i++) {
374
375                 switch (message->signature[i]) {
376                 case 's':
377                 case 'o':
378                 case 'n':
379                         extra += sizeof (void *);
380                         break;
381                 case 'a':
382                         extra += sizeof (void *) + sizeof (struct wl_array);
383                         break;
384                 case 'h':
385                         extra += sizeof (int);
386                         break;
387                 default:
388                         break;
389                 }
390         }
391
392         return extra;
393 }
394
395 static int
396 wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
397 {
398         if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd)
399                 if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
400                         return -1;
401
402         wl_buffer_put(&connection->fds_out, &fd, sizeof fd);
403
404         return 0;
405 }
406
407 const char *
408 get_next_argument(const char *signature, struct argument_details *details)
409 {
410         if (*signature == '?') {
411                 details->nullable = 1;
412                 signature++;
413         } else
414                 details->nullable = 0;
415
416         details->type = *signature;
417         return signature + 1;
418 }
419
420 int
421 arg_count_for_signature(const char *signature)
422 {
423         int count = 0;
424         while (*signature) {
425                 if (*signature != '?')
426                         count++;
427                 signature++;
428         }
429         return count;
430 }
431
432 struct wl_closure *
433 wl_closure_vmarshal(struct wl_object *sender,
434                     uint32_t opcode, va_list ap,
435                     const struct wl_message *message)
436 {
437         struct wl_closure *closure;
438         struct wl_object **objectp, *object;
439         uint32_t length, aligned, *p, *start, size, *end;
440         int dup_fd;
441         struct wl_array **arrayp, *array;
442         const char **sp, *s;
443         const char *signature = message->signature;
444         struct argument_details arg;
445         char *extra;
446         int i, count, fd, extra_size, *fd_ptr;
447
448         /* FIXME: Match old fixed allocation for now */
449         closure = malloc(sizeof *closure + 1024);
450         if (closure == NULL)
451                 return NULL;
452
453         extra_size = wl_message_size_extra(message);
454         count = arg_count_for_signature(signature) + 2;
455         extra = (char *) closure->buffer;
456         start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
457         end = &closure->buffer[256];
458         p = &start[2];
459
460         closure->types[0] = &ffi_type_pointer;
461         closure->types[1] = &ffi_type_pointer;
462
463         for (i = 2; i < count; i++) {
464                 signature = get_next_argument(signature, &arg);
465
466                 switch (arg.type) {
467                 case 'f':
468                         closure->types[i] = &ffi_type_sint32;
469                         closure->args[i] = p;
470                         if (end - p < 1)
471                                 goto err;
472                         *p++ = va_arg(ap, wl_fixed_t);
473                         break;
474                 case 'u':
475                         closure->types[i] = &ffi_type_uint32;
476                         closure->args[i] = p;
477                         if (end - p < 1)
478                                 goto err;
479                         *p++ = va_arg(ap, uint32_t);
480                         break;
481                 case 'i':
482                         closure->types[i] = &ffi_type_sint32;
483                         closure->args[i] = p;
484                         if (end - p < 1)
485                                 goto err;
486                         *p++ = va_arg(ap, int32_t);
487                         break;
488                 case 's':
489                         closure->types[i] = &ffi_type_pointer;
490                         closure->args[i] = extra;
491                         sp = (const char **) extra;
492                         extra += sizeof *sp;
493
494                         s = va_arg(ap, const char *);
495
496                         if (!arg.nullable && s == NULL)
497                                 goto err_null;
498
499                         length = s ? strlen(s) + 1: 0;
500                         aligned = (length + 3) & ~3;
501                         if (p + aligned / sizeof *p + 1 > end)
502                                 goto err;
503                         *p++ = length;
504
505                         if (length > 0)
506                                 *sp = (const char *) p;
507                         else
508                                 *sp = NULL;
509
510                         memcpy(p, s, length);
511                         memset((char *) p + length, 0, aligned - length);
512                         p += aligned / sizeof *p;
513                         break;
514                 case 'o':
515                         closure->types[i] = &ffi_type_pointer;
516                         closure->args[i] = extra;
517                         objectp = (struct wl_object **) extra;
518                         extra += sizeof *objectp;
519
520                         object = va_arg(ap, struct wl_object *);
521
522                         if (!arg.nullable && object == NULL)
523                                 goto err_null;
524
525                         *objectp = object;
526                         if (end - p < 1)
527                                 goto err;
528                         *p++ = object ? object->id : 0;
529                         break;
530
531                 case 'n':
532                         closure->types[i] = &ffi_type_uint32;
533                         closure->args[i] = p;
534                         object = va_arg(ap, struct wl_object *);
535                         if (end - p < 1)
536                                 goto err;
537
538                         if (!arg.nullable && object == NULL)
539                                 goto err_null;
540
541                         *p++ = object ? object->id : 0;
542                         break;
543
544                 case 'a':
545                         closure->types[i] = &ffi_type_pointer;
546                         closure->args[i] = extra;
547                         arrayp = (struct wl_array **) extra;
548                         extra += sizeof *arrayp;
549
550                         *arrayp = (struct wl_array *) extra;
551                         extra += sizeof **arrayp;
552
553                         array = va_arg(ap, struct wl_array *);
554
555                         if (!arg.nullable && array == NULL)
556                                 goto err_null;
557
558                         if (array == NULL || array->size == 0) {
559                                 if (end - p < 1)
560                                         goto err;
561                                 *p++ = 0;
562                                 break;
563                         }
564                         if (p + DIV_ROUNDUP(array->size, sizeof *p) + 1 > end)
565                                 goto err;
566                         *p++ = array->size;
567                         memcpy(p, array->data, array->size);
568
569                         (*arrayp)->size = array->size;
570                         (*arrayp)->alloc = array->alloc;
571                         (*arrayp)->data = p;
572
573                         p += DIV_ROUNDUP(array->size, sizeof *p);
574                         break;
575
576                 case 'h':
577                         closure->types[i] = &ffi_type_sint;
578                         closure->args[i] = extra;
579                         fd_ptr = (int *) extra;
580                         extra += sizeof *fd_ptr;
581
582                         fd = va_arg(ap, int);
583                         dup_fd = wl_os_dupfd_cloexec(fd, 0);
584                         if (dup_fd < 0) {
585                                 fprintf(stderr, "dup failed: %m");
586                                 abort();
587                         }
588                         *fd_ptr = dup_fd;
589                         break;
590                 default:
591                         fprintf(stderr, "unhandled format code: '%c'\n",
592                                 arg.type);
593                         assert(0);
594                         break;
595                 }
596         }
597
598         size = (p - start) * sizeof *p;
599         start[0] = sender->id;
600         start[1] = opcode | (size << 16);
601
602         closure->start = start;
603         closure->message = message;
604         closure->count = count;
605
606         ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
607                      closure->count, &ffi_type_void, closure->types);
608
609         return closure;
610
611 err:
612         printf("request too big to marshal, maximum size is %zu\n",
613                sizeof closure->buffer);
614         errno = ENOMEM;
615
616         return NULL;
617
618 err_null:
619         free(closure);
620         wl_log("error marshalling arguments for %s:%i.%s (signature %s): "
621                "null value passed for arg %i\n",
622                sender->interface->name, sender->id, message->name,
623                message->signature, i);
624         errno = EINVAL;
625         return NULL;
626 }
627
628 struct wl_closure *
629 wl_connection_demarshal(struct wl_connection *connection,
630                         uint32_t size,
631                         struct wl_map *objects,
632                         const struct wl_message *message)
633 {
634         uint32_t *p, *next, *end, length, **id;
635         int *fd;
636         char *extra, **s;
637         unsigned int i, count, extra_space;
638         const char *signature = message->signature;
639         struct argument_details arg;
640         struct wl_object **object;
641         struct wl_array **array;
642         struct wl_closure *closure;
643
644         count = arg_count_for_signature(signature) + 2;
645         if (count > ARRAY_LENGTH(closure->types)) {
646                 printf("too many args (%d)\n", count);
647                 errno = EINVAL;
648                 wl_connection_consume(connection, size);
649                 return NULL;
650         }
651
652         extra_space = wl_message_size_extra(message);
653         closure = malloc(sizeof *closure + 8 + size + extra_space);
654         if (closure == NULL)
655                 return NULL;
656
657         closure->message = message;
658         closure->types[0] = &ffi_type_pointer;
659         closure->types[1] = &ffi_type_pointer;
660         closure->start = closure->buffer;
661
662         wl_connection_copy(connection, closure->buffer, size);
663         p = &closure->buffer[2];
664         end = (uint32_t *) ((char *) p + size);
665         extra = (char *) end;
666         for (i = 2; i < count; i++) {
667                 signature = get_next_argument(signature, &arg);
668
669                 if (p + 1 > end) {
670                         printf("message too short, "
671                                "object (%d), message %s(%s)\n",
672                                *p, message->name, message->signature);
673                         errno = EINVAL;
674                         goto err;
675                 }
676
677                 switch (arg.type) {
678                 case 'u':
679                         closure->types[i] = &ffi_type_uint32;
680                         closure->args[i] = p++;
681                         break;
682                 case 'i':
683                         closure->types[i] = &ffi_type_sint32;
684                         closure->args[i] = p++;
685                         break;
686                 case 'f':
687                         closure->types[i] = &ffi_type_sint32;
688                         closure->args[i] = p++;
689                         break;
690                 case 's':
691                         closure->types[i] = &ffi_type_pointer;
692                         length = *p++;
693
694                         next = p + DIV_ROUNDUP(length, sizeof *p);
695                         if (next > end) {
696                                 printf("message too short, "
697                                        "object (%d), message %s(%s)\n",
698                                        *p, message->name, message->signature);
699                                 errno = EINVAL;
700                                 goto err;
701                         }
702
703                         s = (char **) extra;
704                         extra += sizeof *s;
705                         closure->args[i] = s;
706
707                         if (length == 0) {
708                                 *s = NULL;
709                         } else {
710                                 *s = (char *) p;
711                         }
712
713                         if (length > 0 && (*s)[length - 1] != '\0') {
714                                 printf("string not nul-terminated, "
715                                        "message %s(%s)\n",
716                                        message->name, message->signature);
717                                 errno = EINVAL;
718                                 goto err;
719                         }
720                         p = next;
721                         break;
722                 case 'o':
723                         closure->types[i] = &ffi_type_pointer;
724                         object = (struct wl_object **) extra;
725                         extra += sizeof *object;
726                         closure->args[i] = object;
727
728                         if (*p == 0 && !arg.nullable) {
729                                 printf("NULL new ID received on non-nullable "
730                                        "type, message %s(%s)\n", message->name,
731                                        message->signature);
732                                 *object = NULL;
733                                 errno = EINVAL;
734                                 goto err;
735                         }
736
737                         *object = wl_map_lookup(objects, *p);
738                         if (*object == WL_ZOMBIE_OBJECT) {
739                                 /* references object we've already
740                                  * destroyed client side */
741                                 *object = NULL;
742                         } else if (*object == NULL && *p != 0) {
743                                 printf("unknown object (%u), message %s(%s)\n",
744                                        *p, message->name, message->signature);
745                                 *object = NULL;
746                                 errno = EINVAL;
747                                 goto err;
748                         }
749
750                         if (*object != NULL && message->types[i-2] != NULL &&
751                             (*object)->interface != message->types[i-2]) {
752                                 printf("invalid object (%u), type (%s), "
753                                         "message %s(%s)\n",
754                                        *p, (*object)->interface->name,
755                                        message->name, message->signature);
756                                 errno = EINVAL;
757                                 goto err;
758                         }
759
760                         p++;
761                         break;
762                 case 'n':
763                         closure->types[i] = &ffi_type_pointer;
764                         id = (uint32_t **) extra;
765                         extra += sizeof *id;
766                         closure->args[i] = id;
767                         *id = p;
768
769                         if (*id == 0 && !arg.nullable) {
770                                 printf("NULL new ID received on non-nullable "
771                                        "type, message %s(%s)\n", message->name,
772                                        message->signature);
773                                 errno = EINVAL;
774                                 goto err;
775                         }
776
777                         if (wl_map_reserve_new(objects, *p) < 0) {
778                                 printf("not a valid new object id (%d), "
779                                        "message %s(%s)\n",
780                                        *p, message->name, message->signature);
781                                 errno = EINVAL;
782                                 goto err;
783                         }
784
785                         p++;
786                         break;
787                 case 'a':
788                         closure->types[i] = &ffi_type_pointer;
789                         length = *p++;
790
791                         next = p + DIV_ROUNDUP(length, sizeof *p);
792                         if (next > end) {
793                                 printf("message too short, "
794                                        "object (%d), message %s(%s)\n",
795                                        *p, message->name, message->signature);
796                                 errno = EINVAL;
797                                 goto err;
798                         }
799
800                         array = (struct wl_array **) extra;
801                         extra += sizeof *array;
802                         closure->args[i] = array;
803
804                         *array = (struct wl_array *) extra;
805                         extra += sizeof **array;
806
807                         (*array)->size = length;
808                         (*array)->alloc = 0;
809                         (*array)->data = p;
810                         p = next;
811                         break;
812                 case 'h':
813                         closure->types[i] = &ffi_type_sint;
814
815                         fd = (int *) extra;
816                         extra += sizeof *fd;
817                         closure->args[i] = fd;
818
819                         wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
820                         connection->fds_in.tail += sizeof *fd;
821                         break;
822                 default:
823                         printf("unknown type\n");
824                         assert(0);
825                         break;
826                 }
827         }
828
829         closure->count = i;
830
831         ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
832                      closure->count, &ffi_type_void, closure->types);
833
834         wl_connection_consume(connection, size);
835
836         return closure;
837
838  err:
839         closure->count = i;
840         wl_closure_destroy(closure);
841         wl_connection_consume(connection, size);
842
843         return NULL;
844 }
845
846 void
847 wl_closure_invoke(struct wl_closure *closure,
848                   struct wl_object *target, void (*func)(void), void *data)
849 {
850         int result;
851
852         closure->args[0] = &data;
853         closure->args[1] = &target;
854
855         ffi_call(&closure->cif, func, &result, closure->args);
856 }
857
858 static int
859 copy_fds_to_connection(struct wl_closure *closure,
860                        struct wl_connection *connection)
861 {
862         const struct wl_message *message = closure->message;
863         uint32_t i, count;
864         struct argument_details arg;
865         const char *signature = message->signature;
866         int *fd;
867
868         count = arg_count_for_signature(signature) + 2;
869         for (i = 2; i < count; i++) {
870                 signature = get_next_argument(signature, &arg);
871                 if (arg.type != 'h')
872                         continue;
873
874                 fd = closure->args[i];
875                 if (wl_connection_put_fd(connection, *fd)) {
876                         fprintf(stderr, "request could not be marshaled: "
877                                 "can't send file descriptor");
878                         return -1;
879                 }
880         }
881
882         return 0;
883 }
884
885 int
886 wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
887 {
888         uint32_t size;
889
890         if (copy_fds_to_connection(closure, connection))
891                 return -1;
892
893         size = closure->start[1] >> 16;
894
895         return wl_connection_write(connection, closure->start, size);
896 }
897
898 int
899 wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
900 {
901         uint32_t size;
902
903         if (copy_fds_to_connection(closure, connection))
904                 return -1;
905
906         size = closure->start[1] >> 16;
907
908         return wl_connection_queue(connection, closure->start, size);
909 }
910
911 void
912 wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
913 {
914         union wl_value *value;
915         int32_t si;
916         int i;
917         struct argument_details arg;
918         const char *signature = closure->message->signature;
919         struct timespec tp;
920         unsigned int time;
921
922         clock_gettime(CLOCK_REALTIME, &tp);
923         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
924
925         fprintf(stderr, "[%10.3f] %s%s@%u.%s(",
926                 time / 1000.0,
927                 send ? " -> " : "",
928                 target->interface->name, target->id,
929                 closure->message->name);
930
931         for (i = 2; i < closure->count; i++) {
932                 signature = get_next_argument(signature, &arg);
933                 if (i > 2)
934                         fprintf(stderr, ", ");
935
936                 value = closure->args[i];
937                 switch (arg.type) {
938                 case 'u':
939                         fprintf(stderr, "%u", value->uint32);
940                         break;
941                 case 'i':
942                         si = (int32_t) value->uint32;
943                         fprintf(stderr, "%d", si);
944                         break;
945                 case 'f':
946                         si = (int32_t) value->uint32;
947                         fprintf(stderr, "%f", wl_fixed_to_double(si));
948                         break;
949                 case 's':
950                         fprintf(stderr, "\"%s\"", value->string);
951                         break;
952                 case 'o':
953                         if (value->object)
954                                 fprintf(stderr, "%s@%u",
955                                         value->object->interface->name,
956                                         value->object->id);
957                         else
958                                 fprintf(stderr, "nil");
959                         break;
960                 case 'n':
961                         fprintf(stderr, "new id %s@",
962                                 (closure->message->types[i - 2]) ?
963                                  closure->message->types[i - 2]->name :
964                                   "[unknown]");
965                         if (send && value->new_id != 0)
966                                 fprintf(stderr, "%u", value->new_id);
967                         else if (!send && value->object != NULL)
968                                 fprintf(stderr, "%u",
969                                         *((uint32_t *)value->object));
970                         else
971                                 fprintf(stderr, "nil");
972                         break;
973                 case 'a':
974                         fprintf(stderr, "array");
975                         break;
976                 case 'h':
977                         fprintf(stderr, "fd %d", value->uint32);
978                         break;
979                 }
980         }
981
982         fprintf(stderr, ")\n");
983 }
984
985 void
986 wl_closure_destroy(struct wl_closure *closure)
987 {
988         free(closure);
989 }