Demarshal all arguments from protocol buffer

dev
Kristian Høgsberg 15 years ago
parent 6c7c7a909a
commit f821f5ad93
  1. 143
      connection.c

@ -50,13 +50,6 @@ struct wl_closure {
const struct wl_message *message; const struct wl_message *message;
ffi_type *types[20]; ffi_type *types[20];
ffi_cif cif; ffi_cif cif;
union {
uint32_t uint32;
char *string;
void *object;
uint32_t new_id;
struct wl_array *array;
} values[20];
void *args[20]; void *args[20];
uint32_t buffer[64]; uint32_t buffer[64];
}; };
@ -71,6 +64,14 @@ struct wl_connection {
struct wl_closure closure; 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 static void
wl_buffer_put(struct wl_buffer *b, const void *data, size_t count) 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); 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 * struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection, wl_connection_demarshal(struct wl_connection *connection,
uint32_t size, uint32_t size,
struct wl_hash_table *objects, struct wl_hash_table *objects,
const struct wl_message *message) const struct wl_message *message)
{ {
uint32_t *p, *next, *end, length; uint32_t *p, *next, *end, length, *uint;
char *extra; char *extra, **s;
int i, count; int i, count, extra_space;
struct wl_object *object; struct wl_object **object;
struct wl_array **array;
struct wl_closure *closure = &connection->closure; struct wl_closure *closure = &connection->closure;
count = strlen(message->signature) + 2; count = strlen(message->signature) + 2;
@ -414,17 +441,15 @@ wl_connection_demarshal(struct wl_connection *connection,
assert(0); 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"); printf("request too big, should malloc tmp buffer here\n");
assert(0); assert(0);
} }
closure->message = message; closure->message = message;
closure->types[0] = &ffi_type_pointer; closure->types[0] = &ffi_type_pointer;
closure->args[0] = &closure->values[0];
closure->types[1] = &ffi_type_pointer; closure->types[1] = &ffi_type_pointer;
closure->args[1] = &closure->values[1];
wl_connection_copy(connection, closure->buffer, size); wl_connection_copy(connection, closure->buffer, size);
p = &closure->buffer[2]; p = &closure->buffer[2];
@ -443,7 +468,7 @@ wl_connection_demarshal(struct wl_connection *connection,
case 'u': case 'u':
case 'i': case 'i':
closure->types[i] = &ffi_type_uint32; closure->types[i] = &ffi_type_uint32;
closure->values[i].uint32 = *p++; closure->args[i] = p++;
break; break;
case 's': case 's':
closure->types[i] = &ffi_type_pointer; closure->types[i] = &ffi_type_pointer;
@ -458,36 +483,44 @@ wl_connection_demarshal(struct wl_connection *connection,
goto err; goto err;
} }
s = (char **) extra;
extra += sizeof *s;
closure->args[i] = s;
if (length == 0) { if (length == 0) {
closure->values[i].string = NULL; *s = NULL;
} else { } else {
closure->values[i].string = (char *) p; *s = (char *) p;
if (closure->values[i].string[length - 1] != '\0') { }
printf("string not nul-terminated, "
"message %s(%s)\n", if (length > 0 && (*s)[length - 1] != '\0') {
message->name, printf("string not nul-terminated, "
message->signature); "message %s(%s)\n",
errno = EINVAL; message->name, message->signature);
goto err; errno = EINVAL;
} goto err;
} }
p = next; p = next;
break; break;
case 'o': case 'o':
closure->types[i] = &ffi_type_pointer; closure->types[i] = &ffi_type_pointer;
object = wl_hash_table_lookup(objects, *p); object = (struct wl_object **) extra;
if (object == NULL && *p != 0) { 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", printf("unknown object (%d), message %s(%s)\n",
*p, message->name, message->signature); *p, message->name, message->signature);
errno = EINVAL; errno = EINVAL;
goto err; goto err;
} }
closure->values[i].object = object;
p++; p++;
break; break;
case 'n': case 'n':
closure->types[i] = &ffi_type_uint32; closure->types[i] = &ffi_type_uint32;
closure->values[i].new_id = *p; closure->args[i] = p;
object = wl_hash_table_lookup(objects, *p); object = wl_hash_table_lookup(objects, *p);
if (object != NULL) { if (object != NULL) {
printf("not a new object (%d), " printf("not a new object (%d), "
@ -511,27 +544,34 @@ wl_connection_demarshal(struct wl_connection *connection,
goto err; goto err;
} }
closure->values[i].array = (struct wl_array *) extra; array = (struct wl_array **) extra;
extra += sizeof *closure->values[i].array; extra += sizeof *array;
closure->values[i].array->size = length; closure->args[i] = array;
closure->values[i].array->alloc = 0;
closure->values[i].array->data = p; *array = (struct wl_array *) extra;
extra += sizeof **array;
(*array)->size = length;
(*array)->alloc = 0;
(*array)->data = p;
p = next; p = next;
break; break;
case 'h': case 'h':
closure->types[i] = &ffi_type_uint32; closure->types[i] = &ffi_type_uint32;
uint = (uint32_t *) extra;
extra += sizeof *uint;
closure->args[i] = uint;
wl_buffer_copy(&connection->fds_in, wl_buffer_copy(&connection->fds_in,
&closure->values[i].uint32, uint, sizeof *uint);
sizeof closure->values[i].uint32); connection->fds_in.tail += sizeof *uint;
connection->fds_in.tail +=
sizeof closure->values[i].uint32;
break; break;
default: default:
printf("unknown type\n"); printf("unknown type\n");
assert(0); assert(0);
break; break;
} }
closure->args[i] = &closure->values[i];
} }
closure->count = i; closure->count = i;
@ -555,8 +595,8 @@ wl_closure_invoke(struct wl_closure *closure,
{ {
int result; int result;
closure->values[0].object = data; closure->args[0] = &data;
closure->values[1].object = target; closure->args[1] = &target;
ffi_call(&closure->cif, func, &result, closure->args); ffi_call(&closure->cif, func, &result, closure->args);
} }
@ -564,7 +604,7 @@ wl_closure_invoke(struct wl_closure *closure,
void void
wl_closure_print(struct wl_closure *closure, struct wl_object *target) wl_closure_print(struct wl_closure *closure, struct wl_object *target)
{ {
struct wl_object *object; union wl_value *value;
int i; int i;
fprintf(stderr, "%s(%d).%s(", 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++) { for (i = 2; i < closure->count; i++) {
if (i > 2) if (i > 2)
fprintf(stderr, ", "); fprintf(stderr, ", ");
value = closure->args[i];
switch (closure->message->signature[i - 2]) { switch (closure->message->signature[i - 2]) {
case 'u': case 'u':
fprintf(stderr, "%u", closure->values[i].uint32); fprintf(stderr, "%u", value->uint32);
break; break;
case 'i': case 'i':
fprintf(stderr, "%d", closure->values[i].uint32); fprintf(stderr, "%d", value->uint32);
break; break;
case 's': case 's':
fprintf(stderr, "\"%s\"", closure->values[i].string); fprintf(stderr, "\"%s\"", value->string);
break; break;
case 'o': case 'o':
object = closure->values[i].object; fprintf(stderr, "object %u",
fprintf(stderr, "object %u", object ? object->id : 0); value->object ? value->object->id : 0);
break; break;
case 'n': case 'n':
fprintf(stderr, "new id %u", fprintf(stderr, "new id %u", value->uint32);
closure->values[i].uint32);
break; break;
case 'a': case 'a':
fprintf(stderr, "array"); fprintf(stderr, "array");
break; break;
case 'h': case 'h':
fprintf(stderr, "fd %d", closure->values[i].uint32); fprintf(stderr, "fd %d", value->uint32);
break; break;
} }
} }

Loading…
Cancel
Save