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
32 #include "wayland-util.h"
33 #include "connection.h"
35 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
42 struct wl_connection {
43 struct wl_buffer in, out;
46 wl_connection_update_func_t update;
49 struct wl_connection *
50 wl_connection_create(int fd,
51 wl_connection_update_func_t update,
54 struct wl_connection *connection;
56 connection = malloc(sizeof *connection);
57 memset(connection, 0, sizeof *connection);
59 connection->update = update;
60 connection->data = data;
62 connection->update(connection,
63 WL_CONNECTION_READABLE,
70 wl_connection_destroy(struct wl_connection *connection)
76 wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
83 if (tail + size <= ARRAY_LENGTH(b->data)) {
84 memcpy(data, b->data + tail, size);
86 rest = ARRAY_LENGTH(b->data) - tail;
87 memcpy(data, b->data + tail, rest);
88 memcpy(data + rest, b->data, size - rest);
93 wl_connection_consume(struct wl_connection *connection, size_t size)
100 if (tail + size <= ARRAY_LENGTH(b->data)) {
103 rest = ARRAY_LENGTH(b->data) - tail;
104 b->tail = size - rest;
108 int wl_connection_data(struct wl_connection *connection, uint32_t mask)
112 int len, head, tail, count, size, available;
114 if (mask & WL_CONNECTION_READABLE) {
116 head = connection->in.head;
117 if (head < b->tail) {
118 iov[0].iov_base = b->data + head;
119 iov[0].iov_len = b->tail - head;
122 size = ARRAY_LENGTH(b->data) - head;
123 iov[0].iov_base = b->data + head;
124 iov[0].iov_len = size;
125 iov[1].iov_base = b->data;
126 iov[1].iov_len = b->tail;
130 len = readv(connection->fd, iov, count);
131 } while (len < 0 && errno == EINTR);
134 "read error from connection %p: %m (%d)\n",
137 } else if (len == 0) {
138 /* FIXME: Handle this better? */
140 } else if (head + len <= ARRAY_LENGTH(b->data)) {
143 b->head = head + len - ARRAY_LENGTH(b->data);
146 /* We know we have data in the buffer at this point,
147 * so if head equals tail, it means the buffer is
150 available = b->head - b->tail;
152 available = sizeof b->data;
153 else if (available < 0)
154 available += ARRAY_LENGTH(b->data);
159 if (mask & WL_CONNECTION_WRITABLE) {
160 b = &connection->out;
162 if (tail < b->head) {
163 iov[0].iov_base = b->data + tail;
164 iov[0].iov_len = b->head - tail;
167 size = ARRAY_LENGTH(b->data) - tail;
168 iov[0].iov_base = b->data + tail;
169 iov[0].iov_len = size;
170 iov[1].iov_base = b->data;
171 iov[1].iov_len = b->head;
175 len = writev(connection->fd, iov, count);
176 } while (len < 0 && errno == EINTR);
178 fprintf(stderr, "write error for connection %p: %m\n", connection);
180 } else if (tail + len <= ARRAY_LENGTH(b->data)) {
183 b->tail = tail + len - ARRAY_LENGTH(b->data);
186 /* We just took data out of the buffer, so at this
187 * point if head equals tail, the buffer is empty. */
189 if (b->tail == b->head)
190 connection->update(connection,
191 WL_CONNECTION_READABLE,
199 wl_connection_write(struct wl_connection *connection, const void *data, size_t count)
205 b = &connection->out;
207 if (head + count <= ARRAY_LENGTH(b->data)) {
208 memcpy(b->data + head, data, count);
211 size = ARRAY_LENGTH(b->data) - head;
212 memcpy(b->data + head, data, size);
213 memcpy(b->data, data + size, count - size);
214 b->head = count - size;
218 connection->update(connection,
219 WL_CONNECTION_READABLE |
220 WL_CONNECTION_WRITABLE,
225 wl_connection_vmarshal(struct wl_connection *connection,
226 struct wl_object *sender,
227 uint32_t opcode, va_list ap,
228 const struct wl_message *message)
230 struct wl_object *object;
231 uint32_t args[32], length, *p, size;
235 count = strlen(message->signature);
236 assert(count <= ARRAY_LENGTH(args));
239 for (i = 0; i < count; i++) {
240 switch (message->signature[i]) {
243 *p++ = va_arg(ap, uint32_t);
246 s = va_arg(ap, const char *);
249 memcpy(p, s, length);
250 p += DIV_ROUNDUP(length, sizeof(*p));
254 object = va_arg(ap, struct wl_object *);
263 size = (p - args) * sizeof *p;
264 args[0] = sender->id;
265 args[1] = opcode | (size << 16);
266 wl_connection_write(connection, args, size);
270 wl_connection_demarshal(struct wl_connection *connection,
272 struct wl_hash *objects,
274 void *data, struct wl_object *target,
275 const struct wl_message *message)
279 uint32_t *p, result, length;
288 struct wl_object *object;
291 count = strlen(message->signature) + 2;
292 if (count > ARRAY_LENGTH(types)) {
293 printf("too many args (%d)\n", count);
297 if (sizeof buffer < size) {
298 printf("request too big, should malloc tmp buffer here\n");
302 types[0] = &ffi_type_pointer;
303 values[0].object = data;
304 args[0] = &values[0];
306 types[1] = &ffi_type_pointer;
307 values[1].object = target;
308 args[1] = &values[1];
310 wl_connection_copy(connection, buffer, size);
312 for (i = 2; i < count; i++) {
313 switch (message->signature[i - 2]) {
316 types[i] = &ffi_type_uint32;
317 values[i].uint32 = *p++;
320 types[i] = &ffi_type_pointer;
322 values[i].string = malloc(length + 1);
323 if (values[i].string == NULL) {
324 /* FIXME: Send NO_MEMORY */
327 memcpy(values[i].string, p, length);
328 values[i].string[length] = '\0';
329 p += DIV_ROUNDUP(length, sizeof *p);
332 types[i] = &ffi_type_pointer;
333 object = wl_hash_lookup(objects, *p);
335 printf("unknown object (%d)\n", *p);
336 values[i].object = object;
340 types[i] = &ffi_type_uint32;
341 values[i].new_id = *p;
342 object = wl_hash_lookup(objects, *p);
344 printf("object already exists (%d)\n", *p);
348 printf("unknown type\n");
351 args[i] = &values[i];
354 ffi_prep_cif(&cif, FFI_DEFAULT_ABI, count, &ffi_type_uint32, types);
355 ffi_call(&cif, func, &result, args);
357 for (i = 2; i < count; i++) {
358 switch (message->signature[i - 2]) {
360 free(values[i].string);