a888940d5ea9c9afc70d7af103c7401dc55778f5
[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                         extra += sizeof (void *);
379                         break;
380                 case 'a':
381                         extra += sizeof (void *) + sizeof (struct wl_array);
382                         break;
383                 case 'h':
384                         extra += sizeof (int);
385                         break;
386                 default:
387                         break;
388                 }
389         }
390
391         return extra;
392 }
393
394 static int
395 wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
396 {
397         if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd)
398                 if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
399                         return -1;
400
401         wl_buffer_put(&connection->fds_out, &fd, sizeof fd);
402
403         return 0;
404 }
405
406 int
407 wl_closure_vmarshal(struct wl_closure *closure,
408                     struct wl_object *sender,
409                     uint32_t opcode, va_list ap,
410                     const struct wl_message *message)
411 {
412         struct wl_object **objectp, *object;
413         uint32_t length, *p, *start, size, *end;
414         int dup_fd;
415         struct wl_array **arrayp, *array;
416         const char **sp, *s;
417         char *extra;
418         int i, count, fd, extra_size, *fd_ptr;
419
420         extra_size = wl_message_size_extra(message);
421         count = strlen(message->signature) + 2;
422         extra = (char *) closure->buffer;
423         start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
424         end = &closure->buffer[ARRAY_LENGTH(closure->buffer)];
425         p = &start[2];
426
427         closure->types[0] = &ffi_type_pointer;
428         closure->types[1] = &ffi_type_pointer;
429
430         for (i = 2; i < count; i++) {
431                 switch (message->signature[i - 2]) {
432                 case 'f':
433                         closure->types[i] = &ffi_type_sint32;
434                         closure->args[i] = p;
435                         if (end - p < 1)
436                                 goto err;
437                         *p++ = va_arg(ap, wl_fixed_t);
438                         break;
439                 case 'u':
440                         closure->types[i] = &ffi_type_uint32;
441                         closure->args[i] = p;
442                         if (end - p < 1)
443                                 goto err;
444                         *p++ = va_arg(ap, uint32_t);
445                         break;
446                 case 'i':
447                         closure->types[i] = &ffi_type_sint32;
448                         closure->args[i] = p;
449                         if (end - p < 1)
450                                 goto err;
451                         *p++ = va_arg(ap, int32_t);
452                         break;
453                 case 's':
454                         closure->types[i] = &ffi_type_pointer;
455                         closure->args[i] = extra;
456                         sp = (const char **) extra;
457                         extra += sizeof *sp;
458
459                         s = va_arg(ap, const char *);
460                         length = s ? strlen(s) + 1: 0;
461                         if (p + DIV_ROUNDUP(length, sizeof *p) + 1 > end)
462                                 goto err;
463                         *p++ = length;
464
465                         if (length > 0)
466                                 *sp = (const char *) p;
467                         else
468                                 *sp = NULL;
469
470                         memcpy(p, s, length);
471                         p += DIV_ROUNDUP(length, sizeof *p);
472                         break;
473                 case 'o':
474                         closure->types[i] = &ffi_type_pointer;
475                         closure->args[i] = extra;
476                         objectp = (struct wl_object **) extra;
477                         extra += sizeof *objectp;
478
479                         object = va_arg(ap, struct wl_object *);
480                         *objectp = object;
481                         if (end - p < 1)
482                                 goto err;
483                         *p++ = object ? object->id : 0;
484                         break;
485
486                 case 'n':
487                         closure->types[i] = &ffi_type_uint32;
488                         closure->args[i] = p;
489                         object = va_arg(ap, struct wl_object *);
490                         if (end - p < 1)
491                                 goto err;
492                         *p++ = object ? object->id : 0;
493                         break;
494
495                 case 'a':
496                         closure->types[i] = &ffi_type_pointer;
497                         closure->args[i] = extra;
498                         arrayp = (struct wl_array **) extra;
499                         extra += sizeof *arrayp;
500
501                         *arrayp = (struct wl_array *) extra;
502                         extra += sizeof **arrayp;
503
504                         array = va_arg(ap, struct wl_array *);
505                         if (array == NULL || array->size == 0) {
506                                 if (end - p < 1)
507                                         goto err;
508                                 *p++ = 0;
509                                 break;
510                         }
511                         if (p + DIV_ROUNDUP(array->size, sizeof *p) + 1 > end)
512                                 goto err;
513                         *p++ = array->size;
514                         memcpy(p, array->data, array->size);
515
516                         (*arrayp)->size = array->size;
517                         (*arrayp)->alloc = array->alloc;
518                         (*arrayp)->data = p;
519
520                         p += DIV_ROUNDUP(array->size, sizeof *p);
521                         break;
522
523                 case 'h':
524                         closure->types[i] = &ffi_type_sint;
525                         closure->args[i] = extra;
526                         fd_ptr = (int *) extra;
527                         extra += sizeof *fd_ptr;
528
529                         fd = va_arg(ap, int);
530                         dup_fd = wl_os_dupfd_cloexec(fd, 0);
531                         if (dup_fd < 0) {
532                                 fprintf(stderr, "dup failed: %m");
533                                 abort();
534                         }
535                         *fd_ptr = dup_fd;
536                         break;
537                 default:
538                         fprintf(stderr, "unhandled format code: '%c'\n",
539                                 message->signature[i - 2]);
540                         assert(0);
541                         break;
542                 }
543         }
544
545         size = (p - start) * sizeof *p;
546         start[0] = sender->id;
547         start[1] = opcode | (size << 16);
548
549         closure->start = start;
550         closure->message = message;
551         closure->count = count;
552
553         ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
554                      closure->count, &ffi_type_void, closure->types);
555
556         return 0;
557
558 err:
559         printf("request too big to marshal, maximum size is %zu\n",
560                sizeof closure->buffer);
561         errno = ENOMEM;
562         return -1;
563 }
564
565 int
566 wl_connection_demarshal(struct wl_connection *connection,
567                         struct wl_closure *closure,
568                         uint32_t size,
569                         struct wl_map *objects,
570                         const struct wl_message *message)
571 {
572         uint32_t *p, *next, *end, length;
573         int *fd;
574         char *extra, **s;
575         unsigned int i, count, extra_space;
576         struct wl_object **object;
577         struct wl_array **array;
578
579         count = strlen(message->signature) + 2;
580         if (count > ARRAY_LENGTH(closure->types)) {
581                 printf("too many args (%d)\n", count);
582                 errno = EINVAL;
583                 wl_connection_consume(connection, size);
584                 return -1;
585         }
586
587         extra_space = wl_message_size_extra(message);
588         if (sizeof closure->buffer < size + extra_space) {
589                 printf("request too big to demarshal, maximum %zu actual %d\n",
590                        sizeof closure->buffer, size + extra_space);
591                 errno = ENOMEM;
592                 wl_connection_consume(connection, size);
593                 return -1;
594         }
595
596         closure->message = message;
597         closure->types[0] = &ffi_type_pointer;
598         closure->types[1] = &ffi_type_pointer;
599
600         wl_connection_copy(connection, closure->buffer, size);
601         p = &closure->buffer[2];
602         end = (uint32_t *) ((char *) p + size);
603         extra = (char *) end;
604         for (i = 2; i < count; i++) {
605                 if (p + 1 > end) {
606                         printf("message too short, "
607                                "object (%d), message %s(%s)\n",
608                                *p, message->name, message->signature);
609                         errno = EINVAL;
610                         goto err;
611                 }
612
613                 switch (message->signature[i - 2]) {
614                 case 'u':
615                         closure->types[i] = &ffi_type_uint32;
616                         closure->args[i] = p++;
617                         break;
618                 case 'i':
619                         closure->types[i] = &ffi_type_sint32;
620                         closure->args[i] = p++;
621                         break;
622                 case 'f':
623                         closure->types[i] = &ffi_type_sint32;
624                         closure->args[i] = p++;
625                         break;
626                 case 's':
627                         closure->types[i] = &ffi_type_pointer;
628                         length = *p++;
629
630                         next = p + DIV_ROUNDUP(length, sizeof *p);
631                         if (next > end) {
632                                 printf("message too short, "
633                                        "object (%d), message %s(%s)\n",
634                                        *p, message->name, message->signature);
635                                 errno = EINVAL;
636                                 goto err;
637                         }
638
639                         s = (char **) extra;
640                         extra += sizeof *s;
641                         closure->args[i] = s;
642
643                         if (length == 0) {
644                                 *s = NULL;
645                         } else {
646                                 *s = (char *) p;
647                         }
648
649                         if (length > 0 && (*s)[length - 1] != '\0') {
650                                 printf("string not nul-terminated, "
651                                        "message %s(%s)\n",
652                                        message->name, message->signature);
653                                 errno = EINVAL;
654                                 goto err;
655                         }
656                         p = next;
657                         break;
658                 case 'o':
659                         closure->types[i] = &ffi_type_pointer;
660                         object = (struct wl_object **) extra;
661                         extra += sizeof *object;
662                         closure->args[i] = object;
663
664                         *object = wl_map_lookup(objects, *p);
665                         if (*object == WL_ZOMBIE_OBJECT) {
666                                 /* references object we've already
667                                  * destroyed client side */
668                                 *object = NULL;
669                         } else if (*object == NULL && *p != 0) {
670                                 printf("unknown object (%d), message %s(%s)\n",
671                                        *p, message->name, message->signature);
672                                 *object = NULL;
673                                 errno = EINVAL;
674                                 goto err;
675                         }
676
677                         if (*object != NULL && message->types[i-2] != NULL &&
678                             (*object)->interface != message->types[i-2]) {
679                                 printf("invalid object (%d), type (%s), "
680                                         "message %s(%s)\n",
681                                        *p, (*object)->interface->name,
682                                        message->name, message->signature);
683                                 errno = EINVAL;
684                                 goto err;
685                         }
686
687                         p++;
688                         break;
689                 case 'n':
690                         closure->types[i] = &ffi_type_uint32;
691                         closure->args[i] = p;
692                         object = wl_map_lookup(objects, *p);
693                         if (object != NULL) {
694                                 printf("not a new object (%d), "
695                                        "message %s(%s)\n",
696                                        *p, message->name, message->signature);
697                                 errno = EINVAL;
698                                 goto err;
699                         }
700                         p++;
701                         break;
702                 case 'a':
703                         closure->types[i] = &ffi_type_pointer;
704                         length = *p++;
705
706                         next = p + DIV_ROUNDUP(length, sizeof *p);
707                         if (next > end) {
708                                 printf("message too short, "
709                                        "object (%d), message %s(%s)\n",
710                                        *p, message->name, message->signature);
711                                 errno = EINVAL;
712                                 goto err;
713                         }
714
715                         array = (struct wl_array **) extra;
716                         extra += sizeof *array;
717                         closure->args[i] = array;
718
719                         *array = (struct wl_array *) extra;
720                         extra += sizeof **array;
721
722                         (*array)->size = length;
723                         (*array)->alloc = 0;
724                         (*array)->data = p;
725                         p = next;
726                         break;
727                 case 'h':
728                         closure->types[i] = &ffi_type_sint;
729
730                         fd = (int *) extra;
731                         extra += sizeof *fd;
732                         closure->args[i] = fd;
733
734                         wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
735                         connection->fds_in.tail += sizeof *fd;
736                         break;
737                 default:
738                         printf("unknown type\n");
739                         assert(0);
740                         break;
741                 }
742         }
743
744         closure->count = i;
745
746         ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
747                      closure->count, &ffi_type_void, closure->types);
748
749         wl_connection_consume(connection, size);
750
751         return 0;
752
753  err:
754         closure->count = i;
755         wl_closure_destroy(closure);
756         wl_connection_consume(connection, size);
757
758         return -1;
759 }
760
761 void
762 wl_closure_invoke(struct wl_closure *closure,
763                   struct wl_object *target, void (*func)(void), void *data)
764 {
765         int result;
766
767         closure->args[0] = &data;
768         closure->args[1] = &target;
769
770         ffi_call(&closure->cif, func, &result, closure->args);
771 }
772
773 static int
774 copy_fds_to_connection(struct wl_closure *closure,
775                        struct wl_connection *connection)
776 {
777         const struct wl_message *message = closure->message;
778         uint32_t i, count;
779         int *fd;
780
781         count = strlen(message->signature) + 2;
782         for (i = 2; i < count; i++) {
783                 if (message->signature[i - 2] != 'h')
784                         continue;
785
786                 fd = closure->args[i];
787                 if (wl_connection_put_fd(connection, *fd)) {
788                         fprintf(stderr, "request could not be marshaled: "
789                                 "can't send file descriptor");
790                         return -1;
791                 }
792         }
793
794         return 0;
795 }
796
797 int
798 wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
799 {
800         uint32_t size;
801
802         if (copy_fds_to_connection(closure, connection))
803                 return -1;
804
805         size = closure->start[1] >> 16;
806
807         return wl_connection_write(connection, closure->start, size);
808 }
809
810 int
811 wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
812 {
813         uint32_t size;
814
815         if (copy_fds_to_connection(closure, connection))
816                 return -1;
817
818         size = closure->start[1] >> 16;
819
820         return wl_connection_queue(connection, closure->start, size);
821 }
822
823 void
824 wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
825 {
826         union wl_value *value;
827         int32_t si;
828         int i;
829         struct timespec tp;
830         unsigned int time;
831
832         clock_gettime(CLOCK_REALTIME, &tp);
833         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
834
835         fprintf(stderr, "[%10.3f] %s%s@%u.%s(",
836                 time / 1000.0,
837                 send ? " -> " : "",
838                 target->interface->name, target->id,
839                 closure->message->name);
840
841         for (i = 2; i < closure->count; i++) {
842                 if (i > 2)
843                         fprintf(stderr, ", ");
844
845                 value = closure->args[i];
846                 switch (closure->message->signature[i - 2]) {
847                 case 'u':
848                         fprintf(stderr, "%u", value->uint32);
849                         break;
850                 case 'i':
851                         si = (int32_t) value->uint32;
852                         fprintf(stderr, "%d", si);
853                         break;
854                 case 'f':
855                         si = (int32_t) value->uint32;
856                         fprintf(stderr, "%f", (double) si / 256.0);
857                         break;
858                 case 's':
859                         fprintf(stderr, "\"%s\"", value->string);
860                         break;
861                 case 'o':
862                         if (value->object)
863                                 fprintf(stderr, "%s@%u",
864                                         value->object->interface->name,
865                                         value->object->id);
866                         else
867                                 fprintf(stderr, "nil");
868                         break;
869                 case 'n':
870                         fprintf(stderr, "new id %u", value->uint32);
871                         break;
872                 case 'a':
873                         fprintf(stderr, "array");
874                         break;
875                 case 'h':
876                         fprintf(stderr, "fd %d", value->uint32);
877                         break;
878                 }
879         }
880
881         fprintf(stderr, ")\n");
882 }
883
884 void
885 wl_closure_destroy(struct wl_closure *closure)
886 {
887 }