-/* callback for subcall reply */
-static void client_subcall_reply_cb(void *closure, int iserror, json_object *object)
-{
- client_send_subcall_reply(closure, iserror, object);
- free(closure);
-}
-
-/* received a subcall request */
-static void client_subcall(struct afb_stub_ws *stubws, struct readbuf *rb)
-{
- struct client_subcall *subcall;
- struct client_call *call;
- const char *api, *verb;
- uint32_t subcallid;
- struct json_object *object;
-
- subcall = malloc(sizeof *subcall);
- if (!subcall)
- return;
-
- /* retrieve the message data */
- if (!client_msg_call_get(stubws, rb, &call))
- return;
-
- if (readbuf_uint32(rb, &subcallid)
- && readbuf_string(rb, &api, NULL)
- && readbuf_string(rb, &verb, NULL)
- && readbuf_object(rb, &object)) {
- subcall->stubws = stubws;
- subcall->subcallid = subcallid;
- afb_xreq_subcall(call->xreq, api, verb, object, client_subcall_reply_cb, subcall);
- }
-}
-
-/* pushs an event */
-static void client_on_description(struct afb_stub_ws *stubws, struct readbuf *rb)
-{
- uint32_t descid;
- struct client_describe *desc;
- struct json_object *object;
-
- if (!readbuf_uint32(rb, &descid))
- ERROR("unreadable description");
- else {
- desc = stubws->describes;
- while (desc && desc->descid != descid)
- desc = desc->next;
- if (desc == NULL)
- ERROR("unexpected description");
- else {
- if (readbuf_object(rb, &object))
- desc->result = object;
- else
- ERROR("bad description");
- jobs_leave(desc->jobloop);
- }
- }
-}
-
-/* callback when receiving binary data */
-static void client_on_binary(void *closure, char *data, size_t size)
-{
- if (size > 0) {
- struct afb_stub_ws *stubws = closure;
- struct readbuf rb = { .head = data, .end = data + size };
-
- pthread_mutex_lock(&stubws->mutex);
- switch (*rb.head++) {
- case CHAR_FOR_ANSWER_SUCCESS: /* success */
- client_reply_success(stubws, &rb);
- break;
- case CHAR_FOR_ANSWER_FAIL: /* fail */
- client_reply_fail(stubws, &rb);
- break;
- case CHAR_FOR_EVT_BROADCAST: /* broadcast */
- client_event_broadcast(stubws, &rb);
- break;
- case CHAR_FOR_EVT_ADD: /* creates the event */
- client_event_create(stubws, &rb);
- break;
- case CHAR_FOR_EVT_DEL: /* drops the event */
- client_event_drop(stubws, &rb);
- break;
- case CHAR_FOR_EVT_PUSH: /* pushs the event */
- client_event_push(stubws, &rb);
- break;
- case CHAR_FOR_EVT_SUBSCRIBE: /* subscribe event for a request */
- client_event_subscribe(stubws, &rb);
- break;
- case CHAR_FOR_EVT_UNSUBSCRIBE: /* unsubscribe event for a request */
- client_event_unsubscribe(stubws, &rb);
- break;
- case CHAR_FOR_SUBCALL_CALL: /* subcall */
- client_subcall(stubws, &rb);
- break;
- case CHAR_FOR_DESCRIPTION: /* description */
- client_on_description(stubws, &rb);
- break;
- default: /* unexpected message */
- /* TODO: close the connection */
- break;
- }
- pthread_mutex_unlock(&stubws->mutex);
- }
- free(data);
-}
-
-/* on call, propagate it to the ws service */
-static void client_call_cb(void * closure, struct afb_xreq *xreq)
-{
- int rc;
- struct client_call *call;
- struct writebuf wb = { .count = 0 };
- const char *raw;
- size_t szraw;
- struct afb_stub_ws *stubws = closure;
-
- pthread_mutex_lock(&stubws->mutex);
-
- /* create the recording data */
- call = client_call_make(stubws, xreq);
- if (call == NULL) {
- afb_xreq_fail_f(xreq, "error", "out of memory");
- goto end;
- }
-
- /* creates the call message */
- raw = afb_xreq_raw(xreq, &szraw);
- if (raw == NULL)
- goto internal_error;
- if (!writebuf_char(&wb, CHAR_FOR_CALL)
- || !writebuf_uint32(&wb, call->msgid)
- || !writebuf_uint32(&wb, (uint32_t)xreq->context.flags)
- || !writebuf_string(&wb, xreq->verb)
- || !writebuf_string(&wb, afb_session_uuid(xreq->context.session))
- || !writebuf_string_length(&wb, raw, szraw))
- goto overflow;
-
- /* send */
- rc = afb_ws_binary_v(stubws->ws, wb.iovec, wb.count);
- if (rc >= 0)
- goto end;
-
- afb_xreq_fail(xreq, "error", "websocket sending error");
- goto clean_call;
-
-internal_error:
- afb_xreq_fail(xreq, "error", "internal: raw is NULL!");
- goto clean_call;
-
-overflow:
- afb_xreq_fail(xreq, "error", "overflow: size doesn't match 32 bits!");
-
-clean_call:
- client_call_destroy(call);
-end:
- pthread_mutex_unlock(&stubws->mutex);
-}
-
-static void client_send_describe_cb(int signum, void *closure, struct jobloop *jobloop)
-{
- struct client_describe *desc = closure;
- struct writebuf wb = { .count = 0 };
-
- if (!signum) {
- /* record the jobloop */
- desc->jobloop = jobloop;
-
- /* send */
- if (writebuf_char(&wb, CHAR_FOR_DESCRIBE)
- && writebuf_uint32(&wb, desc->descid)
- && afb_ws_binary_v(desc->stubws->ws, wb.iovec, wb.count) >= 0)
- return;
- }
- jobs_leave(jobloop);
-}