851a7d1d326f6dbac860f6f7f172a37b25c94e54
[profile/ivi/wayland.git] / 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 #include <stdlib.h>
24 #include <stdint.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <sys/uio.h>
29 #include <ffi.h>
30 #include <assert.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35
36 #include "wayland-util.h"
37 #include "connection.h"
38
39 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
40
41 struct wl_buffer {
42         char data[4096];
43         int head, tail;
44 };
45
46 #define MASK(i) ((i) & 4095)
47
48 struct wl_closure {
49         int count;
50         const struct wl_message *message;
51         ffi_type *types[20];
52         ffi_cif cif;
53         void *args[20];
54         uint32_t buffer[64];
55 };
56
57 struct wl_connection {
58         struct wl_buffer in, out;
59         struct wl_buffer fds_in, fds_out;
60         int fds_in_tail;
61         int fd;
62         void *data;
63         wl_connection_update_func_t update;
64         struct wl_closure closure;
65 };
66
67 union wl_value {
68         uint32_t uint32;
69         char *string;
70         struct wl_object *object;
71         uint32_t new_id;
72         struct wl_array *array;
73 };
74
75 static void
76 wl_buffer_put(struct wl_buffer *b, const void *data, size_t count)
77 {
78         int head, size;
79
80         head = MASK(b->head);
81         if (head + count <= sizeof b->data) {
82                 memcpy(b->data + head, data, count);
83         } else {
84                 size = sizeof b->data - head;
85                 memcpy(b->data + head, data, size);
86                 memcpy(b->data, (const char *) data + size, count - size);
87         }
88
89         b->head += count;
90 }
91
92 static void
93 wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count)
94 {
95         int head, tail;
96
97         head = MASK(b->head);
98         tail = MASK(b->tail);
99         if (head < tail) {
100                 iov[0].iov_base = b->data + head;
101                 iov[0].iov_len = tail - head;
102                 *count = 1;
103         } else if (tail == 0) {
104                 iov[0].iov_base = b->data + head;
105                 iov[0].iov_len = sizeof b->data - head;
106                 *count = 1;
107         } else {
108                 iov[0].iov_base = b->data + head;
109                 iov[0].iov_len = sizeof b->data - head;
110                 iov[1].iov_base = b->data;
111                 iov[1].iov_len = tail;
112                 *count = 2;
113         }
114 }
115
116 static void
117 wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count)
118 {
119         int head, tail;
120
121         head = MASK(b->head);
122         tail = MASK(b->tail);
123         if (tail < head) {
124                 iov[0].iov_base = b->data + tail;
125                 iov[0].iov_len = head - tail;
126                 *count = 1;
127         } else if (head == 0) {
128                 iov[0].iov_base = b->data + tail;
129                 iov[0].iov_len = sizeof b->data - tail;
130                 *count = 1;
131         } else {
132                 iov[0].iov_base = b->data + tail;
133                 iov[0].iov_len = sizeof b->data - tail;
134                 iov[1].iov_base = b->data;
135                 iov[1].iov_len = head;
136                 *count = 2;
137         }
138 }
139
140 static void
141 wl_buffer_copy(struct wl_buffer *b, void *data, size_t count)
142 {
143         int tail, size;
144
145         tail = MASK(b->tail);
146         if (tail + count <= sizeof b->data) {
147                 memcpy(data, b->data + tail, count);
148         } else {
149                 size = sizeof b->data - tail;
150                 memcpy(data, b->data + tail, size);
151                 memcpy((char *) data + size, b->data, count - size);
152         }
153 }
154
155 struct wl_connection *
156 wl_connection_create(int fd,
157                      wl_connection_update_func_t update,
158                      void *data)
159 {
160         struct wl_connection *connection;
161
162         connection = malloc(sizeof *connection);
163         memset(connection, 0, sizeof *connection);
164         connection->fd = fd;
165         connection->update = update;
166         connection->data = data;
167
168         connection->update(connection,
169                            WL_CONNECTION_READABLE,
170                            connection->data);
171
172         return connection;
173 }
174
175 void
176 wl_connection_destroy(struct wl_connection *connection)
177 {
178         close(connection->fd);
179         free(connection);
180 }
181
182 void
183 wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
184 {
185         wl_buffer_copy(&connection->in, data, size);
186 }
187
188 void
189 wl_connection_consume(struct wl_connection *connection, size_t size)
190 {
191         connection->in.tail += size;
192         connection->fds_in.tail = connection->fds_in_tail;
193 }
194
195 static void
196 build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
197 {
198         struct cmsghdr *cmsg;
199         size_t size;
200
201         size = buffer->head - buffer->tail;
202         if (size > 0) {
203                 cmsg = (struct cmsghdr *) data;
204                 cmsg->cmsg_level = SOL_SOCKET;
205                 cmsg->cmsg_type = SCM_RIGHTS;
206                 cmsg->cmsg_len = CMSG_LEN(size);
207                 wl_buffer_copy(buffer, CMSG_DATA(cmsg), size);
208                 *clen = cmsg->cmsg_len;
209         } else {
210                 *clen = 0;
211         }
212 }
213
214 static void
215 close_fds(struct wl_buffer *buffer)
216 {
217         int fds[32], i, count;
218         size_t size;
219
220         size = buffer->head - buffer->tail;
221         if (size == 0)
222                 return;
223
224         wl_buffer_copy(buffer, fds, size);
225         count = size / sizeof fds[0];
226         for (i = 0; i < count; i++)
227                 close(fds[i]);
228         buffer->tail += size;
229 }
230
231 static void
232 decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
233 {
234         struct cmsghdr *cmsg;
235         size_t size;
236
237         for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
238              cmsg = CMSG_NXTHDR(msg, cmsg)) {
239                 if (cmsg->cmsg_level == SOL_SOCKET &&
240                     cmsg->cmsg_type == SCM_RIGHTS) {
241                         size = cmsg->cmsg_len - CMSG_LEN(0);
242                         wl_buffer_put(buffer, CMSG_DATA(cmsg), size);
243                 }
244         }
245 }
246
247 int
248 wl_connection_data(struct wl_connection *connection, uint32_t mask)
249 {
250         struct iovec iov[2];
251         struct msghdr msg;
252         char cmsg[128];
253         int len, count, clen;
254
255         if (mask & WL_CONNECTION_READABLE) {
256                 wl_buffer_put_iov(&connection->in, iov, &count);
257
258                 msg.msg_name = NULL;
259                 msg.msg_namelen = 0;
260                 msg.msg_iov = iov;
261                 msg.msg_iovlen = count;
262                 msg.msg_control = cmsg;
263                 msg.msg_controllen = sizeof cmsg;
264                 msg.msg_flags = 0;
265
266                 do {
267                         len = recvmsg(connection->fd, &msg, 0);
268                 } while (len < 0 && errno == EINTR);
269
270                 if (len < 0) {
271                         fprintf(stderr,
272                                 "read error from connection %p: %m (%d)\n",
273                                 connection, errno);
274                         return -1;
275                 } else if (len == 0) {
276                         /* FIXME: Handle this better? */
277                         return -1;
278                 }
279
280                 decode_cmsg(&connection->fds_in, &msg);
281
282                 connection->in.head += len;
283         }       
284
285         if (mask & WL_CONNECTION_WRITABLE) {
286                 wl_buffer_get_iov(&connection->out, iov, &count);
287
288                 build_cmsg(&connection->fds_out, cmsg, &clen);
289
290                 msg.msg_name = NULL;
291                 msg.msg_namelen = 0;
292                 msg.msg_iov = iov;
293                 msg.msg_iovlen = count;
294                 msg.msg_control = cmsg;
295                 msg.msg_controllen = clen;
296                 msg.msg_flags = 0;
297
298                 do {
299                         len = sendmsg(connection->fd, &msg, 0);
300                 } while (len < 0 && errno == EINTR);
301
302                 if (len < 0) {
303                         fprintf(stderr,
304                                 "write error for connection %p, fd %d: %m\n",
305                                 connection, connection->fd);
306                         return -1;
307                 }
308
309                 close_fds(&connection->fds_out);
310
311                 connection->out.tail += len;
312                 if (connection->out.tail == connection->out.head)
313                         connection->update(connection,
314                                            WL_CONNECTION_READABLE,
315                                            connection->data);
316         }
317
318         return connection->in.head - connection->in.tail;
319 }
320
321 void
322 wl_connection_write(struct wl_connection *connection,
323                     const void *data, size_t count)
324 {
325         wl_buffer_put(&connection->out, data, count);
326
327         if (connection->out.head - connection->out.tail == count)
328                 connection->update(connection,
329                                    WL_CONNECTION_READABLE |
330                                    WL_CONNECTION_WRITABLE,
331                                    connection->data);
332 }
333
334 void
335 wl_connection_vmarshal(struct wl_connection *connection,
336                        struct wl_object *sender,
337                        uint32_t opcode, va_list ap,
338                        const struct wl_message *message)
339 {
340         struct wl_closure *closure = &connection->closure;
341         struct wl_object *object;
342         uint32_t length, *p, size;
343         int dup_fd;
344         struct wl_array *array;
345         const char *s;
346         int i, count, fd;
347
348         count = strlen(message->signature);
349         p = &closure->buffer[2];
350         for (i = 0; i < count; i++) {
351                 switch (message->signature[i]) {
352                 case 'u':
353                         *p++ = va_arg(ap, uint32_t);
354                         break;
355                 case 'i':
356                         *p++ = va_arg(ap, int32_t);
357                         break;
358                 case 's':
359                         s = va_arg(ap, const char *);
360                         length = s ? strlen(s) + 1: 0;
361                         *p++ = length;
362                         memcpy(p, s, length);
363                         p += DIV_ROUNDUP(length, sizeof(*p));
364                         break;
365                 case 'o':
366                 case 'n':
367                         object = va_arg(ap, struct wl_object *);
368                         *p++ = object ? object->id : 0;
369                         break;
370                 case 'a':
371                         array = va_arg(ap, struct wl_array *);
372                         if (array == NULL || array->size == 0) {
373                                 *p++ = 0;
374                                 break;
375                         }
376                         *p++ = array->size;
377                         memcpy(p, array->data, array->size);
378                         p = (void *) p + array->size;
379                         break;
380                 case 'h':
381                         fd = va_arg(ap, int);
382                         dup_fd = dup(fd);
383                         if (dup_fd < 0) {
384                                 fprintf(stderr, "dup failed: %m");
385                                 abort();
386                         }
387                         wl_buffer_put(&connection->fds_out,
388                                       &dup_fd, sizeof dup_fd);
389                         break;
390                 default:
391                         assert(0);
392                         break;
393                 }
394         }
395
396         size = (p - closure->buffer) * sizeof *p;
397         closure->buffer[0] = sender->id;
398         closure->buffer[1] = opcode | (size << 16);
399         wl_connection_write(connection, closure->buffer, size);
400 }
401
402 static int
403 wl_message_size_extra(const struct wl_message *message)
404 {
405         int i, extra;
406
407         for (i = 0, extra = 0; message->signature[i]; i++) {
408
409                 switch (message->signature[i - 2]) {
410                 case 's':
411                 case 'o':
412                         extra += sizeof (void *);
413                         break;
414                 case 'a':
415                         extra += sizeof (void *) + sizeof (struct wl_array);
416                         break;
417                 case 'h':
418                         extra += sizeof (uint32_t);
419                 default:
420                         break;
421                 }
422         }
423
424         return extra;
425 }
426
427 struct wl_closure *
428 wl_connection_demarshal(struct wl_connection *connection,
429                         uint32_t size,
430                         struct wl_hash_table *objects,
431                         const struct wl_message *message)
432 {
433         uint32_t *p, *next, *end, length;
434         int *fd;
435         char *extra, **s;
436         int i, count, extra_space;
437         struct wl_object **object;
438         struct wl_array **array;
439         struct wl_closure *closure = &connection->closure;
440
441         count = strlen(message->signature) + 2;
442         if (count > ARRAY_LENGTH(closure->types)) {
443                 printf("too many args (%d)\n", count);
444                 assert(0);
445         }
446
447         extra_space = wl_message_size_extra(message);
448         if (sizeof closure->buffer < size + extra_space) {
449                 printf("request too big, should malloc tmp buffer here\n");
450                 assert(0);
451         }
452
453         closure->message = message;
454         closure->types[0] = &ffi_type_pointer;
455         closure->types[1] = &ffi_type_pointer;
456
457         wl_connection_copy(connection, closure->buffer, size);
458         p = &closure->buffer[2];
459         end = (uint32_t *) ((char *) (p + size));
460         extra = (char *) end;
461         for (i = 2; i < count; i++) {
462                 if (p + 1 > end) {
463                         printf("message too short, "
464                                "object (%d), message %s(%s)\n",
465                                *p, message->name, message->signature);
466                         errno = EINVAL;
467                         goto err;
468                 }
469
470                 switch (message->signature[i - 2]) {
471                 case 'u':
472                         closure->types[i] = &ffi_type_uint32;
473                         closure->args[i] = p++;
474                         break;
475                 case 'i':
476                         closure->types[i] = &ffi_type_sint32;
477                         closure->args[i] = p++;
478                         break;
479                 case 's':
480                         closure->types[i] = &ffi_type_pointer;
481                         length = *p++;
482
483                         next = p + DIV_ROUNDUP(length, sizeof *p);
484                         if (next > end) {
485                                 printf("message too short, "
486                                        "object (%d), message %s(%s)\n",
487                                        *p, message->name, message->signature);
488                                 errno = EINVAL;
489                                 goto err;
490                         }
491
492                         s = (char **) extra;
493                         extra += sizeof *s;
494                         closure->args[i] = s;
495
496                         if (length == 0) {
497                                 *s = NULL;
498                         } else {
499                                 *s = (char *) p;
500                         }
501
502                         if (length > 0 && (*s)[length - 1] != '\0') {
503                                 printf("string not nul-terminated, "
504                                        "message %s(%s)\n",
505                                        message->name, message->signature);
506                                 errno = EINVAL;
507                                 goto err;
508                         }
509                         p = next;
510                         break;
511                 case 'o':
512                         closure->types[i] = &ffi_type_pointer;
513                         object = (struct wl_object **) extra;
514                         extra += sizeof *object;
515                         closure->args[i] = object;
516
517                         *object = wl_hash_table_lookup(objects, *p);
518                         if (*object == NULL && *p != 0) {
519                                 printf("unknown object (%d), message %s(%s)\n",
520                                        *p, message->name, message->signature);
521                                 errno = EINVAL;
522                                 goto err;
523                         }
524
525                         p++;
526                         break;
527                 case 'n':
528                         closure->types[i] = &ffi_type_uint32;
529                         closure->args[i] = p;
530                         object = wl_hash_table_lookup(objects, *p);
531                         if (object != NULL) {
532                                 printf("not a new object (%d), "
533                                        "message %s(%s)\n",
534                                        *p, message->name, message->signature);
535                                 errno = EINVAL;
536                                 goto err;
537                         }
538                         p++;
539                         break;
540                 case 'a':
541                         closure->types[i] = &ffi_type_pointer;
542                         length = *p++;
543
544                         next = p + DIV_ROUNDUP(length, sizeof *p);
545                         if (next > end) {
546                                 printf("message too short, "
547                                        "object (%d), message %s(%s)\n",
548                                        *p, message->name, message->signature);
549                                 errno = EINVAL;
550                                 goto err;
551                         }
552
553                         array = (struct wl_array **) extra;
554                         extra += sizeof *array;
555                         closure->args[i] = array;
556
557                         *array = (struct wl_array *) extra;
558                         extra += sizeof **array;
559
560                         (*array)->size = length;
561                         (*array)->alloc = 0;
562                         (*array)->data = p;
563                         p = next;
564                         break;
565                 case 'h':
566                         closure->types[i] = &ffi_type_sint;
567
568                         fd = (int *) extra;
569                         extra += sizeof *fd;
570                         closure->args[i] = fd;
571
572                         wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
573                         connection->fds_in.tail += sizeof *fd;
574                         break;
575                 default:
576                         printf("unknown type\n");
577                         assert(0);
578                         break;
579                 }
580         }
581
582         closure->count = i;
583         ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
584                      closure->count, &ffi_type_uint32, closure->types);
585
586         wl_connection_consume(connection, size);
587
588         return closure;
589
590  err:
591         closure->count = i;
592         wl_closure_destroy(closure);
593
594         return NULL;
595 }
596
597 void
598 wl_closure_invoke(struct wl_closure *closure,
599                   struct wl_object *target, void (*func)(void), void *data)
600 {
601         int result;
602
603         closure->args[0] = &data;
604         closure->args[1] = &target;
605
606         ffi_call(&closure->cif, func, &result, closure->args);
607 }
608
609 void
610 wl_closure_print(struct wl_closure *closure, struct wl_object *target)
611 {
612         union wl_value *value;
613         int i;
614
615         fprintf(stderr, "%s(%d).%s(",
616                 target->interface->name, target->id,
617                 closure->message->name);
618
619         for (i = 2; i < closure->count; i++) {
620                 if (i > 2)
621                         fprintf(stderr, ", ");
622
623                 value = closure->args[i];
624                 switch (closure->message->signature[i - 2]) {
625                 case 'u':
626                         fprintf(stderr, "%u", value->uint32);
627                         break;
628                 case 'i':
629                         fprintf(stderr, "%d", value->uint32);
630                         break;
631                 case 's':
632                         fprintf(stderr, "\"%s\"", value->string);
633                         break;
634                 case 'o':
635                         fprintf(stderr, "object %u",
636                                 value->object ? value->object->id : 0);
637                         break;
638                 case 'n':
639                         fprintf(stderr, "new id %u", value->uint32);
640                         break;
641                 case 'a':
642                         fprintf(stderr, "array");
643                         break;
644                 case 'h':
645                         fprintf(stderr, "fd %d", value->uint32);
646                         break;
647                 }
648         }
649
650         fprintf(stderr, ")\n");
651 }
652
653 void
654 wl_closure_destroy(struct wl_closure *closure)
655 {
656 }