Demarshal all arguments from protocol buffer
This commit is contained in:
parent
6c7c7a909a
commit
f821f5ad93
143
connection.c
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] = ⌖
|
||||||
|
|
||||||
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…
Reference in New Issue
Block a user