Esempio n. 1
0
void
wl_connection_sync(struct wl_connection *connection)
{
	uint32_t p[2];
	struct wl_buffer *b;
	int size, avail, head;

	b = &connection->in;
	size = sizeof p;
	do {
		head = connection->in.head;
		if (head < b->tail)
			avail = ARRAY_LENGTH(b->data) - (b->tail - head);
		else
			avail = head - b->tail;

		if (avail < size)
			wl_connection_data(connection, WL_CONNECTION_READABLE);
		else if (size == sizeof p) {
			/* If the header is available, get the full size.  */
			wl_connection_copy(connection, p, sizeof p);
			size = p[1] >> 16;
		}
	} while (avail < size);
}
Esempio n. 2
0
WL_EXPORT void
wl_display_iterate(struct wl_display *display, uint32_t mask)
{
    uint32_t p[2], opcode, size;
    int len;

    len = wl_connection_data(display->connection, mask);
    while (len > 0) {
        if (len < sizeof p)
            break;

        wl_connection_copy(display->connection, p, sizeof p);
        opcode = p[1] & 0xffff;
        size = p[1] >> 16;
        if (len < size)
            break;

        handle_event(display, p[0], opcode, size);
        len -= size;
    }

    if (len < 0) {
        fprintf(stderr, "read error: %m\n");
        exit(EXIT_FAILURE);
    }
}
Esempio n. 3
0
static int
queue_event(struct wl_display *display, int len)
{
	uint32_t p[2], id;
	int opcode, size;
	struct wl_proxy *proxy;
	struct wl_closure *closure;
	const struct wl_message *message;
	struct wl_event_queue *queue;

	wl_connection_copy(display->connection, p, sizeof p);
	id = p[0];
	opcode = p[1] & 0xffff;
	size = p[1] >> 16;
	if (len < size)
		return 0;

	proxy = wl_map_lookup(&display->objects, id);
	if (proxy == WL_ZOMBIE_OBJECT) {
		wl_connection_consume(display->connection, size);
		return size;
	} else if (proxy == NULL) {
		wl_connection_consume(display->connection, size);
		return size;
	}

	message = &proxy->object.interface->events[opcode];
	closure = wl_connection_demarshal(display->connection, size,
					  &display->objects, message);
	if (!closure)
		return -1;

	if (create_proxies(proxy, closure) < 0) {
		wl_closure_destroy(closure);
		return -1;
	}

	if (wl_closure_lookup_objects(closure, &display->objects) != 0) {
		wl_closure_destroy(closure);
		return -1;
	}

	increase_closure_args_refcount(closure);
	proxy->refcount++;
	closure->proxy = proxy;

	if (proxy == &display->proxy)
		queue = &display->display_queue;
	else
		queue = proxy->queue;

	if (wl_list_empty(&queue->event_list))
		pthread_cond_signal(&queue->cond);
	wl_list_insert(queue->event_list.prev, &closure->link);

	return size;
}
Esempio n. 4
0
static void
handle_event(struct wl_display *display, uint32_t id, uint32_t opcode,
             uint32_t size)
{
    if (size < 4096) {
        uint32_t *p = alloca (size);

        wl_connection_copy(display->connection, p, size);
        if (display->event_handler != NULL)
            display->event_handler(display, id, opcode, p[2], p[3],
                                   display->event_handler_data);
    }

    wl_connection_consume(display->connection, size);
}
Esempio n. 5
0
struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection,
			uint32_t size,
			struct wl_map *objects,
			const struct wl_message *message)
{
	uint32_t *p, *next, *end, length, id;
	int fd;
	char *s;
	unsigned int i, count, num_arrays;
	const char *signature;
	struct argument_details arg;
	struct wl_closure *closure;
	struct wl_array *array, *array_extra;

	count = arg_count_for_signature(message->signature);
	if (count > WL_CLOSURE_MAX_ARGS) {
		wl_log("too many args (%d)\n", count);
		errno = EINVAL;
		wl_connection_consume(connection, size);
		return NULL;
	}

	num_arrays = wl_message_count_arrays(message);
	closure = malloc(sizeof *closure + size + num_arrays * sizeof *array);
	if (closure == NULL) {
		errno = ENOMEM;
		wl_connection_consume(connection, size);
		return NULL;
	}

	array_extra = closure->extra;
	p = (uint32_t *)(closure->extra + num_arrays);
	end = p + size / sizeof *p;

	wl_connection_copy(connection, p, size);
	closure->sender_id = *p++;
	closure->opcode = *p++ & 0x0000ffff;

	signature = message->signature;
	for (i = 0; i < count; i++) {
		signature = get_next_argument(signature, &arg);

		if (arg.type != 'h' && p + 1 > end) {
			wl_log("message too short, "
			       "object (%d), message %s(%s)\n",
			       *p, message->name, message->signature);
			errno = EINVAL;
			goto err;
		}

		switch (arg.type) {
		case 'u':
			closure->args[i].u = *p++;
			break;
		case 'i':
			closure->args[i].i = *p++;
			break;
		case 'f':
			closure->args[i].f = *p++;
			break;
		case 's':
			length = *p++;

			if (length == 0) {
				closure->args[i].s = NULL;
				break;
			}

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				wl_log("message too short, "
				       "object (%d), message %s(%s)\n",
				       closure->sender_id, message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			s = (char *) p;

			if (length > 0 && s[length - 1] != '\0') {
				wl_log("string not nul-terminated, "
				       "message %s(%s)\n",
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			closure->args[i].s = s;
			p = next;
			break;
		case 'o':
			id = *p++;
			closure->args[i].n = id;

			if (id == 0 && !arg.nullable) {
				wl_log("NULL object received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}
			break;
		case 'n':
			id = *p++;
			closure->args[i].n = id;

			if (id == 0 && !arg.nullable) {
				wl_log("NULL new ID received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			if (wl_map_reserve_new(objects, id) < 0) {
				wl_log("not a valid new object id (%u), "
				       "message %s(%s)\n",
				       id, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			break;
		case 'a':
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				wl_log("message too short, "
				       "object (%d), message %s(%s)\n",
				       closure->sender_id, message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			array_extra->size = length;
			array_extra->alloc = 0;
			array_extra->data = p;

			closure->args[i].a = array_extra++;
			p = next;
			break;
		case 'h':
			if (connection->fds_in.tail == connection->fds_in.head) {
				wl_log("file descriptor expected, "
				       "object (%d), message %s(%s)\n",
				       closure->sender_id, message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			wl_buffer_copy(&connection->fds_in, &fd, sizeof fd);
			connection->fds_in.tail += sizeof fd;
			closure->args[i].h = fd;
			break;
		default:
			wl_abort("unknown type\n");
			break;
		}
	}

	closure->count = count;
	closure->message = message;

	wl_connection_consume(connection, size);

	return closure;

 err:
	wl_closure_destroy(closure);
	wl_connection_consume(connection, size);

	return NULL;
}
Esempio n. 6
0
struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection,
			uint32_t size,
			struct wl_map *objects,
			const struct wl_message *message)
{
	uint32_t *p, *next, *end, length, **id;
	int *fd;
	char *extra, **s;
	unsigned int i, count, extra_space;
	const char *signature = message->signature;
	struct argument_details arg;
	struct wl_object **object;
	struct wl_array **array;
	struct wl_closure *closure;

	count = arg_count_for_signature(signature) + 2;
	if (count > ARRAY_LENGTH(closure->types)) {
		printf("too many args (%d)\n", count);
		errno = EINVAL;
		wl_connection_consume(connection, size);
		return NULL;
	}

	extra_space = wl_message_size_extra(message);
	closure = malloc(sizeof *closure + 8 + size + extra_space);
	if (closure == NULL)
		return NULL;

	closure->message = message;
	closure->types[0] = &ffi_type_pointer;
	closure->types[1] = &ffi_type_pointer;
	closure->start = closure->buffer;

	wl_connection_copy(connection, closure->buffer, size);
	p = &closure->buffer[2];
	end = (uint32_t *) ((char *) p + size);
	extra = (char *) end;
	for (i = 2; i < count; i++) {
		signature = get_next_argument(signature, &arg);

		if (p + 1 > end) {
			printf("message too short, "
			       "object (%d), message %s(%s)\n",
			       *p, message->name, message->signature);
			errno = EINVAL;
			goto err;
		}

		switch (arg.type) {
		case 'u':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p++;
			break;
		case 'i':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p++;
			break;
		case 'f':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p++;
			break;
		case 's':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			s = (char **) extra;
			extra += sizeof *s;
			closure->args[i] = s;

			if (length == 0) {
				*s = NULL;
			} else {
				*s = (char *) p;
			}

			if (length > 0 && (*s)[length - 1] != '\0') {
				printf("string not nul-terminated, "
				       "message %s(%s)\n",
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}
			p = next;
			break;
		case 'o':
			closure->types[i] = &ffi_type_pointer;
			object = (struct wl_object **) extra;
			extra += sizeof *object;
			closure->args[i] = object;

			if (*p == 0 && !arg.nullable) {
				printf("NULL new ID received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				*object = NULL;
				errno = EINVAL;
				goto err;
			}

			*object = wl_map_lookup(objects, *p);
			if (*object == WL_ZOMBIE_OBJECT) {
				/* references object we've already
				 * destroyed client side */
				*object = NULL;
			} else if (*object == NULL && *p != 0) {
				printf("unknown object (%u), message %s(%s)\n",
				       *p, message->name, message->signature);
				*object = NULL;
				errno = EINVAL;
				goto err;
			}

			if (*object != NULL && message->types[i-2] != NULL &&
			    (*object)->interface != message->types[i-2]) {
				printf("invalid object (%u), type (%s), "
					"message %s(%s)\n",
				       *p, (*object)->interface->name,
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			p++;
			break;
		case 'n':
			closure->types[i] = &ffi_type_pointer;
			id = (uint32_t **) extra;
			extra += sizeof *id;
			closure->args[i] = id;
			*id = p;

			if (*id == 0 && !arg.nullable) {
				printf("NULL new ID received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			if (wl_map_reserve_new(objects, *p) < 0) {
				printf("not a valid new object id (%d), "
				       "message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			p++;
			break;
		case 'a':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			array = (struct wl_array **) extra;
			extra += sizeof *array;
			closure->args[i] = array;

			*array = (struct wl_array *) extra;
			extra += sizeof **array;

			(*array)->size = length;
			(*array)->alloc = 0;
			(*array)->data = p;
			p = next;
			break;
		case 'h':
			closure->types[i] = &ffi_type_sint;

			fd = (int *) extra;
			extra += sizeof *fd;
			closure->args[i] = fd;

			wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
			connection->fds_in.tail += sizeof *fd;
			break;
		default:
			printf("unknown type\n");
			assert(0);
			break;
		}
	}

	closure->count = i;

	ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
		     closure->count, &ffi_type_void, closure->types);

	wl_connection_consume(connection, size);

	return closure;

 err:
	closure->count = i;
	wl_closure_destroy(closure);
	wl_connection_consume(connection, size);

	return NULL;
}
Esempio n. 7
0
int
wl_connection_demarshal_mem(struct wl_connection *connection,
			    struct wl_hash *objects, void *dest, size_t dsize,
			    const char *types, ...)
{
	uint32_t id;
	int size;
	size_t field_ofs, field_size, field_align;
	const char *c;
	union wl_element value;
	struct wl_object *object;
	uint32_t data[64], *p;
	va_list va;

#define alignof(type) offsetof (struct { char c; type i; }, i)

	va_start (va, types);
	for (field_ofs = 0, c = types; *c && *c != '|'; ) {
		switch (*c) {
		case 'i':
			value.uint32 = va_arg (va, int);
			c++;
			field_size = sizeof (int);
			field_align = alignof (int);
			break;
		case 'p':
			value.object = va_arg (va, void *);
			c++;
			field_size = sizeof (void *);
			field_align = alignof (void *);
			break;
		case 's':
			value.object = va_arg (va, char *);
			value.object = strdup (value.object);
			c++;
			field_size = sizeof (char *);
			field_align = alignof (char *);
			break;
		case 'o':
			id = va_arg (va, int);
			object = wl_hash_lookup(objects, id);
			if (object == NULL)
				printf("unknown object (%d)\n", id);
			c++;
			value.object = object;
			field_size = sizeof (void *);
			field_align = alignof (void *);
			break;
#if 0
		case '{':
			id = va_arg (va, int);
			object = wl_hash_lookup(objects, id);
			if (object == NULL)
				printf("unknown object (%d)\n", id);
			c++;
			if (!strchrcmp (&c, '}', object->interface->name))
				printf("wrong object type\n");
			value.object = object;
			field_size = sizeof (void *);
			field_align = alignof (void *);
			break;
#endif
		case 'O':
			value.new_id = id = va_arg (va, int);
			if (objects != NULL) {
				object = wl_hash_lookup(objects, id);
				if (object != NULL)
					printf("object already exists (%d)\n", id);
			}
			c++;
			field_size = sizeof (int);
			field_align = alignof (int);
			break;
		default:
			printf("unknown type %c\n", *c++);
			continue;
		}

		field_ofs = (field_ofs + field_align - 1) & -field_align;
		if (field_ofs > dsize) {
			printf("not enough memory");
			return -1;
		}
		memcpy ((char *)dest + field_ofs, &value, field_size);
		field_ofs += field_size;
	}

	if (*c == '|')
		c++;

	if (connection) {
		wl_connection_copy(connection, data, 2 * sizeof (data[0]));
		id = data[0];
		size = data[1] >> 16;

		if (sizeof data < size) {
			printf("request too big, should malloc tmp buffer here\n");
			return -1;
		}
		wl_connection_copy(connection, data, size);
		wl_connection_consume(connection, size);
	} else
Esempio n. 8
0
struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection,
			uint32_t size,
			struct wl_hash_table *objects,
			const struct wl_message *message)
{
	uint32_t *p, *next, *end, length;
	int *fd;
	char *extra, **s;
	int i, count, extra_space;
	struct wl_object **object;
	struct wl_array **array;
	struct wl_closure *closure = &connection->receive_closure;

	count = strlen(message->signature) + 2;
	if (count > ARRAY_LENGTH(closure->types)) {
		printf("too many args (%d)\n", count);
		assert(0);
	}

	extra_space = wl_message_size_extra(message);
	if (sizeof closure->buffer < size + extra_space) {
		printf("request too big, should malloc tmp buffer here\n");
		assert(0);
	}

	closure->message = message;
	closure->types[0] = &ffi_type_pointer;
	closure->types[1] = &ffi_type_pointer;

	wl_connection_copy(connection, closure->buffer, size);
	p = &closure->buffer[2];
	end = (uint32_t *) ((char *) (p + size));
	extra = (char *) end;
	for (i = 2; i < count; i++) {
		if (p + 1 > end) {
			printf("message too short, "
			       "object (%d), message %s(%s)\n",
			       *p, message->name, message->signature);
			errno = EINVAL;
			goto err;
		}

		switch (message->signature[i - 2]) {
		case 'u':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p++;
			break;
		case 'i':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p++;
			break;
		case 's':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			s = (char **) extra;
			extra += sizeof *s;
			closure->args[i] = s;

			if (length == 0) {
				*s = NULL;
			} else {
				*s = (char *) p;
			}

			if (length > 0 && (*s)[length - 1] != '\0') {
				printf("string not nul-terminated, "
				       "message %s(%s)\n",
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}
			p = next;
			break;
		case 'o':
			closure->types[i] = &ffi_type_pointer;
			object = (struct wl_object **) extra;
			extra += sizeof *object;
			closure->args[i] = object;

			*object = wl_hash_table_lookup(objects, *p);
			if (*object == NULL && *p != 0) {
				printf("unknown object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			p++;
			break;
		case 'n':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p;
			object = wl_hash_table_lookup(objects, *p);
			if (object != NULL) {
				printf("not a new object (%d), "
				       "message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}
			p++;
			break;
		case 'a':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			array = (struct wl_array **) extra;
			extra += sizeof *array;
			closure->args[i] = array;

			*array = (struct wl_array *) extra;
			extra += sizeof **array;

			(*array)->size = length;
			(*array)->alloc = 0;
			(*array)->data = p;
			p = next;
			break;
		case 'h':
			closure->types[i] = &ffi_type_sint;

			fd = (int *) extra;
			extra += sizeof *fd;
			closure->args[i] = fd;

			wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
			connection->fds_in.tail += sizeof *fd;
			break;
		default:
			printf("unknown type\n");
			assert(0);
			break;
		}
	}

	closure->count = i;
	ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
		     closure->count, &ffi_type_uint32, closure->types);

	wl_connection_consume(connection, size);

	return closure;

 err:
	closure->count = i;
	wl_closure_destroy(closure);

	return NULL;
}