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
33 #include <sys/types.h>
34 #include <sys/socket.h>
36 #include "wayland-util.h"
37 #include "connection.h"
39 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
46 #define MASK(i) ((i) & 4095)
50 const struct wl_message *message;
58 struct wl_connection {
59 struct wl_buffer in, out;
60 struct wl_buffer fds_in, fds_out;
63 wl_connection_update_func_t update;
64 struct wl_closure closure;
70 struct wl_object *object;
72 struct wl_array *array;
76 wl_buffer_put(struct wl_buffer *b, const void *data, size_t count)
81 if (head + count <= sizeof b->data) {
82 memcpy(b->data + head, data, count);
84 size = sizeof b->data - head;
85 memcpy(b->data + head, data, size);
86 memcpy(b->data, (const char *) data + size, count - size);
93 wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count)
100 iov[0].iov_base = b->data + head;
101 iov[0].iov_len = tail - head;
103 } else if (tail == 0) {
104 iov[0].iov_base = b->data + head;
105 iov[0].iov_len = sizeof b->data - head;
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;
117 wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count)
121 head = MASK(b->head);
122 tail = MASK(b->tail);
124 iov[0].iov_base = b->data + tail;
125 iov[0].iov_len = head - tail;
127 } else if (head == 0) {
128 iov[0].iov_base = b->data + tail;
129 iov[0].iov_len = sizeof b->data - tail;
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;
141 wl_buffer_copy(struct wl_buffer *b, void *data, size_t count)
145 tail = MASK(b->tail);
146 if (tail + count <= sizeof b->data) {
147 memcpy(data, b->data + tail, count);
149 size = sizeof b->data - tail;
150 memcpy(data, b->data + tail, size);
151 memcpy((char *) data + size, b->data, count - size);
155 struct wl_connection *
156 wl_connection_create(int fd,
157 wl_connection_update_func_t update,
160 struct wl_connection *connection;
162 connection = malloc(sizeof *connection);
163 memset(connection, 0, sizeof *connection);
165 connection->update = update;
166 connection->data = data;
168 connection->update(connection,
169 WL_CONNECTION_READABLE,
176 wl_connection_destroy(struct wl_connection *connection)
178 close(connection->fd);
183 wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
185 wl_buffer_copy(&connection->in, data, size);
189 wl_connection_consume(struct wl_connection *connection, size_t size)
191 connection->in.tail += size;
195 build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
197 struct cmsghdr *cmsg;
200 size = buffer->head - buffer->tail;
202 cmsg = (struct cmsghdr *) data;
203 cmsg->cmsg_level = SOL_SOCKET;
204 cmsg->cmsg_type = SCM_RIGHTS;
205 cmsg->cmsg_len = CMSG_LEN(size);
206 wl_buffer_copy(buffer, CMSG_DATA(cmsg), size);
207 *clen = cmsg->cmsg_len;
214 close_fds(struct wl_buffer *buffer)
216 int fds[32], i, count;
219 size = buffer->head - buffer->tail;
223 wl_buffer_copy(buffer, fds, size);
224 count = size / sizeof fds[0];
225 for (i = 0; i < count; i++)
227 buffer->tail += size;
231 decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
233 struct cmsghdr *cmsg;
236 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
237 cmsg = CMSG_NXTHDR(msg, cmsg)) {
238 if (cmsg->cmsg_level == SOL_SOCKET &&
239 cmsg->cmsg_type == SCM_RIGHTS) {
240 size = cmsg->cmsg_len - CMSG_LEN(0);
241 wl_buffer_put(buffer, CMSG_DATA(cmsg), size);
247 wl_connection_data(struct wl_connection *connection, uint32_t mask)
252 int len, count, clen;
254 if (mask & WL_CONNECTION_WRITABLE) {
255 wl_buffer_get_iov(&connection->out, iov, &count);
257 build_cmsg(&connection->fds_out, cmsg, &clen);
262 msg.msg_iovlen = count;
263 msg.msg_control = cmsg;
264 msg.msg_controllen = clen;
268 len = sendmsg(connection->fd, &msg, 0);
269 } while (len < 0 && errno == EINTR);
273 "write error for connection %p, fd %d: %m\n",
274 connection, connection->fd);
278 close_fds(&connection->fds_out);
280 connection->out.tail += len;
281 if (connection->out.tail == connection->out.head)
282 connection->update(connection,
283 WL_CONNECTION_READABLE,
287 if (mask & WL_CONNECTION_READABLE) {
288 wl_buffer_put_iov(&connection->in, iov, &count);
293 msg.msg_iovlen = count;
294 msg.msg_control = cmsg;
295 msg.msg_controllen = sizeof cmsg;
299 len = recvmsg(connection->fd, &msg, 0);
300 } while (len < 0 && errno == EINTR);
304 "read error from connection %p: %m (%d)\n",
307 } else if (len == 0) {
308 /* FIXME: Handle this better? */
312 decode_cmsg(&connection->fds_in, &msg);
314 connection->in.head += len;
317 return connection->in.head - connection->in.tail;
321 wl_connection_write(struct wl_connection *connection,
322 const void *data, size_t count)
324 wl_buffer_put(&connection->out, data, count);
326 if (connection->out.head - connection->out.tail == count)
327 connection->update(connection,
328 WL_CONNECTION_READABLE |
329 WL_CONNECTION_WRITABLE,
334 wl_message_size_extra(const struct wl_message *message)
338 for (i = 0, extra = 0; message->signature[i]; i++) {
340 switch (message->signature[i]) {
343 extra += sizeof (void *);
346 extra += sizeof (void *) + sizeof (struct wl_array);
349 extra += sizeof (uint32_t);
360 wl_connection_vmarshal(struct wl_connection *connection,
361 struct wl_object *sender,
362 uint32_t opcode, va_list ap,
363 const struct wl_message *message)
365 struct wl_closure *closure = &connection->closure;
366 struct wl_object **objectp, *object;
367 uint32_t length, *p, *start, size;
369 struct wl_array **arrayp, *array;
372 int i, count, fd, extra_size;
374 extra_size = wl_message_size_extra(message);
375 count = strlen(message->signature) + 2;
376 extra = (char *) closure->buffer;
377 start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
379 for (i = 2; i < count; i++) {
380 switch (message->signature[i - 2]) {
382 closure->types[i] = &ffi_type_uint32;
383 closure->args[i] = p;
384 *p++ = va_arg(ap, uint32_t);
387 closure->types[i] = &ffi_type_sint32;
388 closure->args[i] = p;
389 *p++ = va_arg(ap, int32_t);
392 closure->types[i] = &ffi_type_pointer;
393 closure->args[i] = extra;
394 sp = (const char **) extra;
397 s = va_arg(ap, const char *);
398 length = s ? strlen(s) + 1: 0;
402 *sp = (const char *) p;
406 memcpy(p, s, length);
407 p += DIV_ROUNDUP(length, sizeof *p);
410 closure->types[i] = &ffi_type_pointer;
411 closure->args[i] = extra;
412 objectp = (struct wl_object **) extra;
413 extra += sizeof *objectp;
415 object = va_arg(ap, struct wl_object *);
417 *p++ = object ? object->id : 0;
421 closure->types[i] = &ffi_type_uint32;
422 closure->args[i] = p;
423 object = va_arg(ap, struct wl_object *);
428 closure->types[i] = &ffi_type_pointer;
429 closure->args[i] = extra;
430 arrayp = (struct wl_array **) extra;
431 extra += sizeof *arrayp;
433 *arrayp = (struct wl_array *) extra;
434 extra += sizeof **arrayp;
436 array = va_arg(ap, struct wl_array *);
437 if (array == NULL || array->size == 0) {
442 memcpy(p, array->data, array->size);
444 (*arrayp)->size = array->size;
445 (*arrayp)->alloc = array->alloc;
448 p += DIV_ROUNDUP(array->size, sizeof *p);
452 fd = va_arg(ap, int);
455 fprintf(stderr, "dup failed: %m");
458 wl_buffer_put(&connection->fds_out,
459 &dup_fd, sizeof dup_fd);
467 size = (p - start) * sizeof *p;
468 start[0] = sender->id;
469 start[1] = opcode | (size << 16);
471 closure->start = start;
472 closure->message = message;
473 closure->count = count;
479 wl_connection_demarshal(struct wl_connection *connection,
481 struct wl_hash_table *objects,
482 const struct wl_message *message)
484 uint32_t *p, *next, *end, length;
487 int i, count, extra_space;
488 struct wl_object **object;
489 struct wl_array **array;
490 struct wl_closure *closure = &connection->closure;
492 count = strlen(message->signature) + 2;
493 if (count > ARRAY_LENGTH(closure->types)) {
494 printf("too many args (%d)\n", count);
498 extra_space = wl_message_size_extra(message);
499 if (sizeof closure->buffer < size + extra_space) {
500 printf("request too big, should malloc tmp buffer here\n");
504 closure->message = message;
505 closure->types[0] = &ffi_type_pointer;
506 closure->types[1] = &ffi_type_pointer;
508 wl_connection_copy(connection, closure->buffer, size);
509 p = &closure->buffer[2];
510 end = (uint32_t *) ((char *) (p + size));
511 extra = (char *) end;
512 for (i = 2; i < count; i++) {
514 printf("message too short, "
515 "object (%d), message %s(%s)\n",
516 *p, message->name, message->signature);
521 switch (message->signature[i - 2]) {
523 closure->types[i] = &ffi_type_uint32;
524 closure->args[i] = p++;
527 closure->types[i] = &ffi_type_sint32;
528 closure->args[i] = p++;
531 closure->types[i] = &ffi_type_pointer;
534 next = p + DIV_ROUNDUP(length, sizeof *p);
536 printf("message too short, "
537 "object (%d), message %s(%s)\n",
538 *p, message->name, message->signature);
545 closure->args[i] = s;
553 if (length > 0 && (*s)[length - 1] != '\0') {
554 printf("string not nul-terminated, "
556 message->name, message->signature);
563 closure->types[i] = &ffi_type_pointer;
564 object = (struct wl_object **) extra;
565 extra += sizeof *object;
566 closure->args[i] = object;
568 *object = wl_hash_table_lookup(objects, *p);
569 if (*object == NULL && *p != 0) {
570 printf("unknown object (%d), message %s(%s)\n",
571 *p, message->name, message->signature);
579 closure->types[i] = &ffi_type_uint32;
580 closure->args[i] = p;
581 object = wl_hash_table_lookup(objects, *p);
582 if (object != NULL) {
583 printf("not a new object (%d), "
585 *p, message->name, message->signature);
592 closure->types[i] = &ffi_type_pointer;
595 next = p + DIV_ROUNDUP(length, sizeof *p);
597 printf("message too short, "
598 "object (%d), message %s(%s)\n",
599 *p, message->name, message->signature);
604 array = (struct wl_array **) extra;
605 extra += sizeof *array;
606 closure->args[i] = array;
608 *array = (struct wl_array *) extra;
609 extra += sizeof **array;
611 (*array)->size = length;
617 closure->types[i] = &ffi_type_sint;
621 closure->args[i] = fd;
623 wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
624 connection->fds_in.tail += sizeof *fd;
627 printf("unknown type\n");
634 ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
635 closure->count, &ffi_type_uint32, closure->types);
637 wl_connection_consume(connection, size);
643 wl_closure_destroy(closure);
649 wl_closure_invoke(struct wl_closure *closure,
650 struct wl_object *target, void (*func)(void), void *data)
654 closure->args[0] = &data;
655 closure->args[1] = ⌖
657 ffi_call(&closure->cif, func, &result, closure->args);
661 wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
665 size = closure->start[1] >> 16;
666 wl_connection_write(connection, closure->start, size);
670 wl_closure_print(struct wl_closure *closure, struct wl_object *target)
672 union wl_value *value;
675 fprintf(stderr, "%s@%d.%s(",
676 target->interface->name, target->id,
677 closure->message->name);
679 for (i = 2; i < closure->count; i++) {
681 fprintf(stderr, ", ");
683 value = closure->args[i];
684 switch (closure->message->signature[i - 2]) {
686 fprintf(stderr, "%u", value->uint32);
689 fprintf(stderr, "%d", value->uint32);
692 fprintf(stderr, "\"%s\"", value->string);
695 fprintf(stderr, "object %u",
696 value->object ? value->object->id : 0);
699 fprintf(stderr, "new id %u", value->uint32);
702 fprintf(stderr, "array");
705 fprintf(stderr, "fd %d", value->uint32);
710 fprintf(stderr, ")\n");
714 wl_closure_destroy(struct wl_closure *closure)