From f821f5ad935015ab05ad9f509a950c56103aa83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 7 Sep 2010 17:00:34 -0400 Subject: [PATCH] Demarshal all arguments from protocol buffer --- connection.c | 143 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 51 deletions(-) diff --git a/connection.c b/connection.c index c09bc134..e9440f0a 100644 --- a/connection.c +++ b/connection.c @@ -50,13 +50,6 @@ struct wl_closure { const struct wl_message *message; ffi_type *types[20]; ffi_cif cif; - union { - uint32_t uint32; - char *string; - void *object; - uint32_t new_id; - struct wl_array *array; - } values[20]; void *args[20]; uint32_t buffer[64]; }; @@ -71,6 +64,14 @@ struct wl_connection { struct wl_closure closure; }; +union wl_value { + uint32_t uint32; + char *string; + struct wl_object *object; + uint32_t new_id; + struct wl_array *array; +}; + static void wl_buffer_put(struct wl_buffer *b, const void *data, size_t count) { @@ -396,16 +397,42 @@ wl_connection_vmarshal(struct wl_connection *connection, wl_connection_write(connection, closure->buffer, size); } +static int +wl_message_size_extra(const struct wl_message *message) +{ + int i, extra; + + for (i = 0, extra = 0; message->signature[i]; i++) { + + switch (message->signature[i - 2]) { + case 's': + case 'o': + extra += sizeof (void *); + break; + case 'a': + extra += sizeof (void *) + sizeof (struct wl_array); + break; + case 'h': + extra += sizeof (uint32_t); + default: + break; + } + } + + return extra; +} + 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; - char *extra; - int i, count; - struct wl_object *object; + uint32_t *p, *next, *end, length, *uint; + char *extra, **s; + int i, count, extra_space; + struct wl_object **object; + struct wl_array **array; struct wl_closure *closure = &connection->closure; count = strlen(message->signature) + 2; @@ -414,17 +441,15 @@ wl_connection_demarshal(struct wl_connection *connection, assert(0); } - if (sizeof closure->buffer < size) { + 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->args[0] = &closure->values[0]; - closure->types[1] = &ffi_type_pointer; - closure->args[1] = &closure->values[1]; wl_connection_copy(connection, closure->buffer, size); p = &closure->buffer[2]; @@ -443,7 +468,7 @@ wl_connection_demarshal(struct wl_connection *connection, case 'u': case 'i': closure->types[i] = &ffi_type_uint32; - closure->values[i].uint32 = *p++; + closure->args[i] = p++; break; case 's': closure->types[i] = &ffi_type_pointer; @@ -458,36 +483,44 @@ wl_connection_demarshal(struct wl_connection *connection, goto err; } + s = (char **) extra; + extra += sizeof *s; + closure->args[i] = s; + if (length == 0) { - closure->values[i].string = NULL; + *s = NULL; } else { - closure->values[i].string = (char *) p; - if (closure->values[i].string[length - 1] != '\0') { - printf("string not nul-terminated, " - "message %s(%s)\n", - message->name, - message->signature); - errno = EINVAL; - goto err; - } + *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 = wl_hash_table_lookup(objects, *p); - if (object == NULL && *p != 0) { + 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; } - closure->values[i].object = object; + p++; break; case 'n': closure->types[i] = &ffi_type_uint32; - closure->values[i].new_id = *p; + closure->args[i] = p; object = wl_hash_table_lookup(objects, *p); if (object != NULL) { printf("not a new object (%d), " @@ -511,27 +544,34 @@ wl_connection_demarshal(struct wl_connection *connection, goto err; } - closure->values[i].array = (struct wl_array *) extra; - extra += sizeof *closure->values[i].array; - closure->values[i].array->size = length; - closure->values[i].array->alloc = 0; - closure->values[i].array->data = p; + 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_uint32; + + uint = (uint32_t *) extra; + extra += sizeof *uint; + closure->args[i] = uint; + wl_buffer_copy(&connection->fds_in, - &closure->values[i].uint32, - sizeof closure->values[i].uint32); - connection->fds_in.tail += - sizeof closure->values[i].uint32; + uint, sizeof *uint); + connection->fds_in.tail += sizeof *uint; break; default: printf("unknown type\n"); assert(0); break; } - closure->args[i] = &closure->values[i]; } closure->count = i; @@ -555,8 +595,8 @@ wl_closure_invoke(struct wl_closure *closure, { int result; - closure->values[0].object = data; - closure->values[1].object = target; + closure->args[0] = &data; + closure->args[1] = ⌖ ffi_call(&closure->cif, func, &result, closure->args); } @@ -564,7 +604,7 @@ wl_closure_invoke(struct wl_closure *closure, void wl_closure_print(struct wl_closure *closure, struct wl_object *target) { - struct wl_object *object; + union wl_value *value; int i; fprintf(stderr, "%s(%d).%s(", @@ -574,29 +614,30 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target) for (i = 2; i < closure->count; i++) { if (i > 2) fprintf(stderr, ", "); + + value = closure->args[i]; switch (closure->message->signature[i - 2]) { case 'u': - fprintf(stderr, "%u", closure->values[i].uint32); + fprintf(stderr, "%u", value->uint32); break; case 'i': - fprintf(stderr, "%d", closure->values[i].uint32); + fprintf(stderr, "%d", value->uint32); break; case 's': - fprintf(stderr, "\"%s\"", closure->values[i].string); + fprintf(stderr, "\"%s\"", value->string); break; case 'o': - object = closure->values[i].object; - fprintf(stderr, "object %u", object ? object->id : 0); + fprintf(stderr, "object %u", + value->object ? value->object->id : 0); break; case 'n': - fprintf(stderr, "new id %u", - closure->values[i].uint32); + fprintf(stderr, "new id %u", value->uint32); break; case 'a': fprintf(stderr, "array"); break; case 'h': - fprintf(stderr, "fd %d", closure->values[i].uint32); + fprintf(stderr, "fd %d", value->uint32); break; } }