static void marshal_demarshal(struct marshal_data *data, void (*func)(void), int size, const char *format, ...) { struct wl_closure *closure; static const int opcode = 4444; static struct wl_object sender = { NULL, NULL, 1234 }; struct wl_message message = { "test", format, NULL }; struct wl_map objects; struct wl_object object = { NULL, &func, 0 }; va_list ap; uint32_t msg[1] = { 1234 }; va_start(ap, format); closure = wl_closure_vmarshal(&sender, opcode, ap, &message); va_end(ap); assert(closure); assert(wl_closure_send(closure, data->write_connection) == 0); wl_closure_destroy(closure); assert(wl_connection_flush(data->write_connection) == size); assert(wl_connection_read(data->read_connection) == size); wl_map_init(&objects, WL_MAP_SERVER_SIDE); object.id = msg[0]; closure = wl_connection_demarshal(data->read_connection, size, &objects, &message); assert(closure); wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data); wl_closure_destroy(closure); }
/** Prepare a request to be sent to the compositor * * \param proxy The proxy object * \param opcode Opcode of the request to be sent * \param args Extra arguments for the given request * * Translates the request given by opcode and the extra arguments into the * wire format and write it to the connection buffer. This version takes an * array of the union type wl_argument. * * \note This is intended to be used by language bindings and not in * non-generated code. * * \sa wl_proxy_marshal() * * \memberof wl_proxy */ WL_EXPORT void wl_proxy_marshal_array(struct wl_proxy *proxy, uint32_t opcode, union wl_argument *args) { struct wl_closure *closure; pthread_mutex_lock(&proxy->display->mutex); closure = wl_closure_marshal(&proxy->object, opcode, args, &proxy->object.interface->methods[opcode]); if (closure == NULL) { fprintf(stderr, "Error marshalling request\n"); abort(); } if (wl_debug) wl_closure_print(closure, &proxy->object, true); if (wl_closure_send(closure, proxy->display->connection)) { fprintf(stderr, "Error sending request: %m\n"); abort(); } wl_closure_destroy(closure); pthread_mutex_unlock(&proxy->display->mutex); }
static void marshal(struct marshal_data *data, const char *format, int size, ...) { struct wl_closure *closure; static const uint32_t opcode = 4444; static struct wl_object sender = { NULL, NULL, 1234 }; struct wl_message message = { "test", format, NULL }; va_list ap; va_start(ap, size); closure = wl_closure_vmarshal(&sender, opcode, ap, &message); va_end(ap); assert(closure); assert(wl_closure_send(closure, data->write_connection) == 0); wl_closure_destroy(closure); assert(data->write_mask == (WL_CONNECTION_WRITABLE | WL_CONNECTION_READABLE)); assert(wl_connection_data(data->write_connection, WL_CONNECTION_WRITABLE) == 0); assert(data->write_mask == WL_CONNECTION_READABLE); assert(read(data->s[0], data->buffer, sizeof data->buffer) == size); assert(data->buffer[0] == sender.id); assert(data->buffer[1] == (opcode | (size << 16))); }
/** Prepare a request to be sent to the compositor * * \param proxy The proxy object * \param opcode Opcode of the request to be sent * \param args Extra arguments for the given request * \param interface The interface to use for the new proxy * * Translates the request given by opcode and the extra arguments into the * wire format and write it to the connection buffer. This version takes an * array of the union type wl_argument. * * For new-id arguments, this function will allocate a new wl_proxy * and send the ID to the server. The new wl_proxy will be returned * on success or NULL on errror with errno set accordingly. * * \note This is intended to be used by language bindings and not in * non-generated code. * * \sa wl_proxy_marshal() * * \memberof wl_proxy */ WL_EXPORT struct wl_proxy * wl_proxy_marshal_array_constructor(struct wl_proxy *proxy, uint32_t opcode, union wl_argument *args, const struct wl_interface *interface) { struct wl_closure *closure; struct wl_proxy *new_proxy = NULL; const struct wl_message *message; pthread_mutex_lock(&proxy->display->mutex); message = &proxy->object.interface->methods[opcode]; if (interface) { new_proxy = create_outgoing_proxy(proxy, message, args, interface); if (new_proxy == NULL) goto err_unlock; } closure = wl_closure_marshal(&proxy->object, opcode, args, message); if (closure == NULL) { wl_log("Error marshalling request: %m\n"); abort(); } if (debug_client) wl_closure_print(closure, &proxy->object, true); if (wl_closure_send(closure, proxy->display->connection)) { wl_log("Error sending request: %m\n"); abort(); } wl_closure_destroy(closure); err_unlock: pthread_mutex_unlock(&proxy->display->mutex); return new_proxy; }
static void marshal_demarshal(struct marshal_data *data, void (*func)(void), int size, const char *format, ...) { struct wl_closure *closure; static const int opcode = 4444; static struct wl_object sender = { NULL, NULL, 1234 }; struct wl_message message = { "test", format, NULL }; struct wl_map objects; struct wl_object object; va_list ap; uint32_t msg[1] = { 1234 }; va_start(ap, format); closure = wl_closure_vmarshal(&sender, opcode, ap, &message); va_end(ap); assert(closure); assert(wl_closure_send(closure, data->write_connection) == 0); wl_closure_destroy(closure); assert(data->write_mask == (WL_CONNECTION_WRITABLE | WL_CONNECTION_READABLE)); assert(wl_connection_data(data->write_connection, WL_CONNECTION_WRITABLE) == 0); assert(data->write_mask == WL_CONNECTION_READABLE); assert(wl_connection_data(data->read_connection, WL_CONNECTION_READABLE) == size); wl_map_init(&objects); object.id = msg[0]; closure = wl_connection_demarshal(data->read_connection, size, &objects, &message); wl_closure_invoke(closure, &object, func, data); wl_closure_destroy(closure); }
static void expected_fail_marshal(int expected_error, const char *format, ...) { struct wl_closure *closure; static const uint32_t opcode = 4444; static const struct wl_interface test_interface = { .name = "test_object" }; static struct wl_object sender = { 0 }; struct wl_message message = { "test", format, NULL }; sender.interface = &test_interface; sender.id = 1234; va_list ap; va_start(ap, format); closure = wl_closure_vmarshal(&sender, opcode, ap, &message); va_end(ap); assert(closure == NULL); assert(errno == expected_error); } static void expected_fail_marshal_send(struct marshal_data *data, int expected_error, const char *format, ...) { struct wl_closure *closure; static const uint32_t opcode = 4444; static struct wl_object sender = { NULL, NULL, 1234 }; struct wl_message message = { "test", format, NULL }; va_list ap; va_start(ap, format); closure = wl_closure_vmarshal(&sender, opcode, ap, &message); va_end(ap); assert(closure); assert(wl_closure_send(closure, data->write_connection) < 0); assert(errno == expected_error); wl_closure_destroy(closure); } TEST(connection_marshal_nullables) { struct marshal_data data; struct wl_object object; struct wl_array array; const char text[] = "curry"; setup_marshal_data(&data); expected_fail_marshal(EINVAL, "o", NULL); expected_fail_marshal(EINVAL, "s", NULL); expected_fail_marshal(EINVAL, "a", NULL); marshal(&data, "?o", 12, NULL); assert(data.buffer[2] == 0); marshal(&data, "?a", 12, NULL); assert(data.buffer[2] == 0); marshal(&data, "?s", 12, NULL); assert(data.buffer[2] == 0); object.id = 55293; marshal(&data, "?o", 12, &object); assert(data.buffer[2] == object.id); array.data = (void *) text; array.size = sizeof text; marshal(&data, "?a", 20, &array); assert(data.buffer[2] == array.size); assert(memcmp(&data.buffer[3], text, array.size) == 0); marshal(&data, "?s", 20, text); assert(data.buffer[2] == sizeof text); assert(strcmp((char *) &data.buffer[3], text) == 0); release_marshal_data(&data); } static void validate_demarshal_u(struct marshal_data *data, struct wl_object *object, uint32_t u) { assert(data->value.u == u); }