2 * Copyright © 2008 Kristian Høgsberg
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.
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
35 #include <sys/types.h>
36 #include <sys/socket.h>
39 #include "wayland-util.h"
40 #include "connection.h"
42 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
49 #define MASK(i) ((i) & 4095)
53 const struct wl_message *message;
61 struct wl_connection {
62 struct wl_buffer in, out;
63 struct wl_buffer fds_in, fds_out;
66 wl_connection_update_func_t update;
67 struct wl_closure receive_closure, send_closure;
73 struct wl_object *object;
75 struct wl_array *array;
79 wl_buffer_put(struct wl_buffer *b, const void *data, size_t count)
84 if (head + count <= sizeof b->data) {
85 memcpy(b->data + head, data, count);
87 size = sizeof b->data - head;
88 memcpy(b->data + head, data, size);
89 memcpy(b->data, (const char *) data + size, count - size);
96 wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count)
100 head = MASK(b->head);
101 tail = MASK(b->tail);
103 iov[0].iov_base = b->data + head;
104 iov[0].iov_len = tail - head;
106 } else if (tail == 0) {
107 iov[0].iov_base = b->data + head;
108 iov[0].iov_len = sizeof b->data - head;
111 iov[0].iov_base = b->data + head;
112 iov[0].iov_len = sizeof b->data - head;
113 iov[1].iov_base = b->data;
114 iov[1].iov_len = tail;
120 wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count)
124 head = MASK(b->head);
125 tail = MASK(b->tail);
127 iov[0].iov_base = b->data + tail;
128 iov[0].iov_len = head - tail;
130 } else if (head == 0) {
131 iov[0].iov_base = b->data + tail;
132 iov[0].iov_len = sizeof b->data - tail;
135 iov[0].iov_base = b->data + tail;
136 iov[0].iov_len = sizeof b->data - tail;
137 iov[1].iov_base = b->data;
138 iov[1].iov_len = head;
144 wl_buffer_copy(struct wl_buffer *b, void *data, size_t count)
148 tail = MASK(b->tail);
149 if (tail + count <= sizeof b->data) {
150 memcpy(data, b->data + tail, count);
152 size = sizeof b->data - tail;
153 memcpy(data, b->data + tail, size);
154 memcpy((char *) data + size, b->data, count - size);
158 struct wl_connection *
159 wl_connection_create(int fd,
160 wl_connection_update_func_t update,
163 struct wl_connection *connection;
165 connection = malloc(sizeof *connection);
166 if (connection == NULL)
168 memset(connection, 0, sizeof *connection);
170 connection->update = update;
171 connection->data = data;
173 connection->update(connection,
174 WL_CONNECTION_READABLE,
181 wl_connection_destroy(struct wl_connection *connection)
183 close(connection->fd);
188 wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
190 wl_buffer_copy(&connection->in, data, size);
194 wl_connection_consume(struct wl_connection *connection, size_t size)
196 connection->in.tail += size;
200 build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
202 struct cmsghdr *cmsg;
205 size = buffer->head - buffer->tail;
207 cmsg = (struct cmsghdr *) data;
208 cmsg->cmsg_level = SOL_SOCKET;
209 cmsg->cmsg_type = SCM_RIGHTS;
210 cmsg->cmsg_len = CMSG_LEN(size);
211 wl_buffer_copy(buffer, CMSG_DATA(cmsg), size);
212 *clen = cmsg->cmsg_len;
219 close_fds(struct wl_buffer *buffer)
221 int fds[32], i, count;
224 size = buffer->head - buffer->tail;
228 wl_buffer_copy(buffer, fds, size);
229 count = size / sizeof fds[0];
230 for (i = 0; i < count; i++)
232 buffer->tail += size;
236 decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
238 struct cmsghdr *cmsg;
241 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
242 cmsg = CMSG_NXTHDR(msg, cmsg)) {
243 if (cmsg->cmsg_level == SOL_SOCKET &&
244 cmsg->cmsg_type == SCM_RIGHTS) {
245 size = cmsg->cmsg_len - CMSG_LEN(0);
246 wl_buffer_put(buffer, CMSG_DATA(cmsg), size);
252 wl_connection_data(struct wl_connection *connection, uint32_t mask)
257 int len, count, clen;
259 if (mask & WL_CONNECTION_WRITABLE) {
260 wl_buffer_get_iov(&connection->out, iov, &count);
262 build_cmsg(&connection->fds_out, cmsg, &clen);
267 msg.msg_iovlen = count;
268 msg.msg_control = cmsg;
269 msg.msg_controllen = clen;
273 len = sendmsg(connection->fd, &msg, MSG_NOSIGNAL);
274 } while (len < 0 && errno == EINTR);
276 if (len == -1 && errno == EPIPE) {
278 } else if (len < 0) {
280 "write error for connection %p, fd %d: %m\n",
281 connection, connection->fd);
285 close_fds(&connection->fds_out);
287 connection->out.tail += len;
288 if (connection->out.tail == connection->out.head)
289 connection->update(connection,
290 WL_CONNECTION_READABLE,
294 if (mask & WL_CONNECTION_READABLE) {
295 wl_buffer_put_iov(&connection->in, iov, &count);
300 msg.msg_iovlen = count;
301 msg.msg_control = cmsg;
302 msg.msg_controllen = sizeof cmsg;
306 len = recvmsg(connection->fd, &msg, MSG_CMSG_CLOEXEC);
307 } while (len < 0 && errno == EINTR);
311 "read error from connection %p: %m (%d)\n",
314 } else if (len == 0) {
315 /* FIXME: Handle this better? */
319 decode_cmsg(&connection->fds_in, &msg);
321 connection->in.head += len;
324 return connection->in.head - connection->in.tail;
328 wl_connection_write(struct wl_connection *connection,
329 const void *data, size_t count)
331 if (connection->out.head - connection->out.tail +
332 count > ARRAY_LENGTH(connection->out.data))
333 wl_connection_data(connection, WL_CONNECTION_WRITABLE);
335 wl_buffer_put(&connection->out, data, count);
337 if (connection->out.head - connection->out.tail == count)
338 connection->update(connection,
339 WL_CONNECTION_READABLE |
340 WL_CONNECTION_WRITABLE,
345 wl_message_size_extra(const struct wl_message *message)
349 for (i = 0, extra = 0; message->signature[i]; i++) {
351 switch (message->signature[i]) {
354 extra += sizeof (void *);
357 extra += sizeof (void *) + sizeof (struct wl_array);
360 extra += sizeof (int);
371 wl_connection_vmarshal(struct wl_connection *connection,
372 struct wl_object *sender,
373 uint32_t opcode, va_list ap,
374 const struct wl_message *message)
376 struct wl_closure *closure = &connection->send_closure;
377 struct wl_object **objectp, *object;
378 uint32_t length, *p, *start, size;
380 struct wl_array **arrayp, *array;
383 int i, count, fd, extra_size, *fd_ptr;
385 extra_size = wl_message_size_extra(message);
386 count = strlen(message->signature) + 2;
387 extra = (char *) closure->buffer;
388 start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
390 for (i = 2; i < count; i++) {
391 switch (message->signature[i - 2]) {
393 closure->types[i] = &ffi_type_uint32;
394 closure->args[i] = p;
395 *p++ = va_arg(ap, uint32_t);
398 closure->types[i] = &ffi_type_sint32;
399 closure->args[i] = p;
400 *p++ = va_arg(ap, int32_t);
403 closure->types[i] = &ffi_type_pointer;
404 closure->args[i] = extra;
405 sp = (const char **) extra;
408 s = va_arg(ap, const char *);
409 length = s ? strlen(s) + 1: 0;
413 *sp = (const char *) p;
417 memcpy(p, s, length);
418 p += DIV_ROUNDUP(length, sizeof *p);
421 closure->types[i] = &ffi_type_pointer;
422 closure->args[i] = extra;
423 objectp = (struct wl_object **) extra;
424 extra += sizeof *objectp;
426 object = va_arg(ap, struct wl_object *);
428 *p++ = object ? object->id : 0;
432 closure->types[i] = &ffi_type_uint32;
433 closure->args[i] = p;
434 object = va_arg(ap, struct wl_object *);
439 closure->types[i] = &ffi_type_pointer;
440 closure->args[i] = extra;
441 arrayp = (struct wl_array **) extra;
442 extra += sizeof *arrayp;
444 *arrayp = (struct wl_array *) extra;
445 extra += sizeof **arrayp;
447 array = va_arg(ap, struct wl_array *);
448 if (array == NULL || array->size == 0) {
453 memcpy(p, array->data, array->size);
455 (*arrayp)->size = array->size;
456 (*arrayp)->alloc = array->alloc;
459 p += DIV_ROUNDUP(array->size, sizeof *p);
463 closure->types[i] = &ffi_type_sint;
464 closure->args[i] = extra;
465 fd_ptr = (int *) extra;
466 extra += sizeof *fd_ptr;
468 fd = va_arg(ap, int);
469 dup_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
471 fprintf(stderr, "dup failed: %m");
475 wl_buffer_put(&connection->fds_out,
476 &dup_fd, sizeof dup_fd);
484 size = (p - start) * sizeof *p;
485 start[0] = sender->id;
486 start[1] = opcode | (size << 16);
488 closure->start = start;
489 closure->message = message;
490 closure->count = count;
496 wl_connection_demarshal(struct wl_connection *connection,
498 struct wl_hash_table *objects,
499 const struct wl_message *message)
501 uint32_t *p, *next, *end, length;
504 int i, count, extra_space;
505 struct wl_object **object;
506 struct wl_array **array;
507 struct wl_closure *closure = &connection->receive_closure;
509 count = strlen(message->signature) + 2;
510 if (count > ARRAY_LENGTH(closure->types)) {
511 printf("too many args (%d)\n", count);
513 wl_connection_consume(connection, size);
517 extra_space = wl_message_size_extra(message);
518 if (sizeof closure->buffer < size + extra_space) {
519 printf("request too big, should malloc tmp buffer here\n");
521 wl_connection_consume(connection, size);
525 closure->message = message;
526 closure->types[0] = &ffi_type_pointer;
527 closure->types[1] = &ffi_type_pointer;
529 wl_connection_copy(connection, closure->buffer, size);
530 p = &closure->buffer[2];
531 end = (uint32_t *) ((char *) p + size);
532 extra = (char *) end;
533 for (i = 2; i < count; i++) {
535 printf("message too short, "
536 "object (%d), message %s(%s)\n",
537 *p, message->name, message->signature);
542 switch (message->signature[i - 2]) {
544 closure->types[i] = &ffi_type_uint32;
545 closure->args[i] = p++;
548 closure->types[i] = &ffi_type_sint32;
549 closure->args[i] = p++;
552 closure->types[i] = &ffi_type_pointer;
555 next = p + DIV_ROUNDUP(length, sizeof *p);
557 printf("message too short, "
558 "object (%d), message %s(%s)\n",
559 *p, message->name, message->signature);
566 closure->args[i] = s;
574 if (length > 0 && (*s)[length - 1] != '\0') {
575 printf("string not nul-terminated, "
577 message->name, message->signature);
584 closure->types[i] = &ffi_type_pointer;
585 object = (struct wl_object **) extra;
586 extra += sizeof *object;
587 closure->args[i] = object;
589 *object = wl_hash_table_lookup(objects, *p);
590 if (*object == NULL && *p != 0) {
591 printf("unknown object (%d), message %s(%s)\n",
592 *p, message->name, message->signature);
600 closure->types[i] = &ffi_type_uint32;
601 closure->args[i] = p;
602 object = wl_hash_table_lookup(objects, *p);
603 if (object != NULL) {
604 printf("not a new object (%d), "
606 *p, message->name, message->signature);
613 closure->types[i] = &ffi_type_pointer;
616 next = p + DIV_ROUNDUP(length, sizeof *p);
618 printf("message too short, "
619 "object (%d), message %s(%s)\n",
620 *p, message->name, message->signature);
625 array = (struct wl_array **) extra;
626 extra += sizeof *array;
627 closure->args[i] = array;
629 *array = (struct wl_array *) extra;
630 extra += sizeof **array;
632 (*array)->size = length;
638 closure->types[i] = &ffi_type_sint;
642 closure->args[i] = fd;
644 wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
645 connection->fds_in.tail += sizeof *fd;
648 printf("unknown type\n");
655 ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
656 closure->count, &ffi_type_uint32, closure->types);
658 wl_connection_consume(connection, size);
664 wl_closure_destroy(closure);
665 wl_connection_consume(connection, size);
671 wl_closure_invoke(struct wl_closure *closure,
672 struct wl_object *target, void (*func)(void), void *data)
676 closure->args[0] = &data;
677 closure->args[1] = ⌖
679 ffi_call(&closure->cif, func, &result, closure->args);
683 wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
687 size = closure->start[1] >> 16;
688 wl_connection_write(connection, closure->start, size);
692 wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
694 union wl_value *value;
699 clock_gettime(CLOCK_REALTIME, &tp);
700 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
702 fprintf(stderr, "[%10.3f] %s%s@%d.%s(",
705 target->interface->name, target->id,
706 closure->message->name);
708 for (i = 2; i < closure->count; i++) {
710 fprintf(stderr, ", ");
712 value = closure->args[i];
713 switch (closure->message->signature[i - 2]) {
715 fprintf(stderr, "%u", value->uint32);
718 fprintf(stderr, "%d", value->uint32);
721 fprintf(stderr, "\"%s\"", value->string);
725 fprintf(stderr, "%s@%u",
726 value->object->interface->name,
729 fprintf(stderr, "nil");
732 fprintf(stderr, "new id %u", value->uint32);
735 fprintf(stderr, "array");
738 fprintf(stderr, "fd %d", value->uint32);
743 fprintf(stderr, ")\n");
747 wl_closure_destroy(struct wl_closure *closure)