+static void server_send_description(struct afb_stub_ws *stubws, uint32_t descid, struct json_object *descobj)
+{
+ struct writebuf wb = { .count = 0 };
+
+ if (!writebuf_char(&wb, CHAR_FOR_DESCRIPTION)
+ || !writebuf_uint32(&wb, descid)
+ || !writebuf_object(&wb, descobj)
+ || afb_ws_binary_v(stubws->ws, wb.iovec, wb.count) < 0)
+ ERROR("can't send description");
+}
+
+static void server_describe_job(int signum, void *closure)
+{
+ struct afb_api api;
+ struct json_object *obj;
+ struct server_describe *desc = closure;
+
+ /* get the description if possible */
+ obj = NULL;
+ if (!signum
+ && !afb_apiset_get(desc->stubws->apiset, desc->stubws->apiname, &api)
+ && api.itf->describe) {
+ obj = api.itf->describe(api.closure);
+ }
+
+ /* send it */
+ server_send_description(desc->stubws, desc->descid, obj);
+ json_object_put(obj);
+ afb_stub_ws_unref(desc->stubws);
+ free(desc);
+}
+
+/* on describe, propagate it to the ws service */
+static void server_on_describe(struct afb_stub_ws *stubws, struct readbuf *rb)
+{
+
+ uint32_t descid;
+ struct server_describe *desc;
+
+ /* reads the descid */
+ if (readbuf_uint32(rb, &descid)) {
+ /* create asynchronous job */
+ desc = malloc(sizeof *desc);
+ if (desc) {
+ desc->descid = descid;
+ desc->stubws = stubws;
+ afb_stub_ws_addref(stubws);
+ if (jobs_queue(NULL, 0, server_describe_job, desc) < 0)
+ server_describe_job(0, desc);
+ return;
+ }
+ server_send_description(stubws, descid, NULL);
+ }
+ ERROR("can't provide description");
+}
+