X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-api-ws.c;h=89b83bc55b5f74634c855aa2b02e9023a25e1b5f;hb=8d322ebdd04d6de2d5649626bbc23aae0d0ed556;hp=663170eee6119986b30e954bc23084bc1e15e1dc;hpb=09f78b70e5debb683e455f6c2de3a5ea0fd93d44;p=src%2Fapp-framework-binder.git diff --git a/src/afb-api-ws.c b/src/afb-api-ws.c index 663170ee..89b83bc5 100644 --- a/src/afb-api-ws.c +++ b/src/afb-api-ws.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016 "IoT.bzh" + * Copyright (C) 2015, 2016, 2017 "IoT.bzh" * Author José Bollo * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +37,7 @@ #include "afb-common.h" -#include "session.h" +#include "afb-session.h" #include "afb-ws.h" #include "afb-msg-json.h" #include "afb-apis.h" @@ -46,6 +46,7 @@ #include "afb-evt.h" #include "afb-subcall.h" #include "verbose.h" +#include "sd-fds.h" struct api_ws_memo; struct api_ws_event; @@ -157,33 +158,36 @@ struct api_ws_server_req { }; static struct json_object *api_ws_server_req_json(struct api_ws_server_req *wreq); -static struct afb_arg api_ws_server_req_get(struct api_ws_server_req *wreq, const char *name); -static void api_ws_server_req_success(struct api_ws_server_req *wreq, struct json_object *obj, const char *info); -static void api_ws_server_req_fail(struct api_ws_server_req *wreq, const char *status, const char *info); -static const char *api_ws_server_req_raw(struct api_ws_server_req *wreq, size_t *size); -static void api_ws_server_req_send(struct api_ws_server_req *wreq, const char *buffer, size_t size); -static void api_ws_server_req_addref(struct api_ws_server_req *wreq); static void api_ws_server_req_unref(struct api_ws_server_req *wreq); -static int api_ws_server_req_subscribe(struct api_ws_server_req *wreq, struct afb_event event); -static int api_ws_server_req_unsubscribe(struct api_ws_server_req *wreq, struct afb_event event); -static void api_ws_server_req_subcall(struct api_ws_server_req *wreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure); + +static struct json_object *api_ws_server_req_json_cb(void *closure); +static struct afb_arg api_ws_server_req_get_cb(void *closure, const char *name); +static void api_ws_server_req_success_cb(void *closure, struct json_object *obj, const char *info); +static void api_ws_server_req_fail_cb(void *closure, const char *status, const char *info); +static const char *api_ws_server_req_raw_cb(void *closure, size_t *size); +static void api_ws_server_req_send_cb(void *closure, const char *buffer, size_t size); +static void api_ws_server_req_addref_cb(void *closure); +static void api_ws_server_req_unref_cb(void *closure); +static int api_ws_server_req_subscribe_cb(void *closure, struct afb_event event); +static int api_ws_server_req_unsubscribe_cb(void *closure, struct afb_event event); +static void api_ws_server_req_subcall_cb(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure); const struct afb_req_itf afb_api_ws_req_itf = { - .json = (void*)api_ws_server_req_json, - .get = (void*)api_ws_server_req_get, - .success = (void*)api_ws_server_req_success, - .fail = (void*)api_ws_server_req_fail, - .raw = (void*)api_ws_server_req_raw, - .send = (void*)api_ws_server_req_send, + .json = api_ws_server_req_json_cb, + .get = api_ws_server_req_get_cb, + .success = api_ws_server_req_success_cb, + .fail = api_ws_server_req_fail_cb, + .raw = api_ws_server_req_raw_cb, + .send = api_ws_server_req_send_cb, .context_get = (void*)afb_context_get, .context_set = (void*)afb_context_set, - .addref = (void*)api_ws_server_req_addref, - .unref = (void*)api_ws_server_req_unref, + .addref = api_ws_server_req_addref_cb, + .unref = api_ws_server_req_unref_cb, .session_close = (void*)afb_context_close, .session_set_LOA = (void*)afb_context_change_loa, - .subscribe = (void*)api_ws_server_req_subscribe, - .unsubscribe = (void*)api_ws_server_req_unsubscribe, - .subcall = (void*)api_ws_server_req_subcall + .subscribe = api_ws_server_req_subscribe_cb, + .unsubscribe = api_ws_server_req_unsubscribe_cb, + .subcall = api_ws_server_req_subcall_cb }; /******************* common part **********************************/ @@ -205,11 +209,13 @@ static struct api_ws *api_ws_make(const char *path) } /* path is copied after the struct */ - api->path = (void*)(api+1); + api->path = (char*)(api+1); memcpy(api->path, path, length + 1); /* api name is at the end of the path */ - api->api = strrchr(api->path, '/'); + while (length && path[length - 1] != '/' && path[length - 1] != ':') + length = length - 1; + api->api = &api->path[length]; if (api->api == NULL || !afb_apis_is_valid_api_name(++api->api)) { errno = EINVAL; goto error2; @@ -281,7 +287,7 @@ static int api_ws_socket_inet(const char *path, int server) rc = getaddrinfo(host, service, &hint, &rai); if (rc != 0) { errno = EINVAL; - return NULL; + return -1; } /* get the socket */ @@ -311,21 +317,29 @@ static int api_ws_socket(const char *path, int server) { int fd, rc; - /* check for unix socket */ - if (0 == strncmp(path, "unix:", 5)) - fd = api_ws_socket_unix(path + 5, server); - else - fd = api_ws_socket_inet(path, server); - - if (fd >= 0) { - fcntl(fd, F_SETFD, FD_CLOEXEC); - fcntl(fd, F_SETFL, O_NONBLOCK); - if (server) { + /* check for systemd socket */ + if (0 == strncmp(path, "sd:", 3)) + fd = sd_fds_for(path + 3); + else { + /* check for unix socket */ + if (0 == strncmp(path, "unix:", 5)) + /* unix socket */ + fd = api_ws_socket_unix(path + 5, server); + else + /* inet socket */ + fd = api_ws_socket_inet(path, server); + + if (fd >= 0 && server) { rc = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof rc); rc = listen(fd, 5); } } + /* configure the socket */ + if (fd >= 0) { + fcntl(fd, F_SETFD, FD_CLOEXEC); + fcntl(fd, F_SETFL, O_NONBLOCK); + } return fd; } @@ -417,12 +431,6 @@ static int api_ws_write_uint32(struct writebuf *wb, uint32_t value) return 1; } -static int api_ws_write_string_nz(struct writebuf *wb, const char *value, size_t length) -{ - uint32_t len = (uint32_t)length; - return (size_t)len == length && ++len && api_ws_write_uint32(wb, len) && api_ws_write_put(wb, value, length) && api_ws_write_char(wb, '\0'); -} - static int api_ws_write_string_length(struct writebuf *wb, const char *value, size_t length) { uint32_t len = (uint32_t)++length; @@ -797,16 +805,18 @@ static void api_ws_client_on_binary(void *closure, char *data, size_t size) break; } } + free(data); } /* on call, propagate it to the ws service */ -static void api_ws_client_call(struct api_ws *api, struct afb_req req, struct afb_context *context, const char *verb, size_t lenverb) +static void api_ws_client_call_cb(void * closure, struct afb_req req, struct afb_context *context, const char *verb) { int rc; struct api_ws_memo *memo; struct writebuf wb = { .count = 0 }; const char *raw; size_t szraw; + struct api_ws *api = closure; /* create the recording data */ memo = api_ws_client_memo_make(api, req, context); @@ -821,8 +831,8 @@ static void api_ws_client_call(struct api_ws *api, struct afb_req req, struct af goto internal_error; if (!api_ws_write_uint32(&wb, memo->msgid) || !api_ws_write_uint32(&wb, (uint32_t)context->flags) - || !api_ws_write_string_nz(&wb, verb, lenverb) - || !api_ws_write_string(&wb, ctxClientGetUuid(context->session)) + || !api_ws_write_string(&wb, verb) + || !api_ws_write_string(&wb, afb_session_uuid(context->session)) || !api_ws_write_string_length(&wb, raw, szraw)) goto overflow; @@ -847,8 +857,10 @@ clean_memo: api_ws_client_memo_destroy(memo); } -static int api_ws_service_start(struct api_ws *api, int share_session, int onneed) +static int api_ws_service_start_cb(void *closure, int share_session, int onneed) { + struct api_ws *api = closure; + /* not an error when onneed */ if (onneed != 0) return 0; @@ -909,8 +921,8 @@ int afb_api_ws_add_client(const char *path) /* record it as an API */ afb_api.closure = api; - afb_api.call = (void*)api_ws_client_call; - afb_api.service_start = (void*)api_ws_service_start; + afb_api.call = api_ws_client_call_cb; + afb_api.service_start = api_ws_service_start_cb; if (afb_apis_add(api->api, afb_api) < 0) goto error3; @@ -970,7 +982,7 @@ static void api_ws_server_called(struct api_ws_client *client, struct readbuf *r /* makes the call */ areq.itf = &afb_api_ws_req_itf; areq.closure = wreq; - afb_apis_call_(areq, &wreq->context, client->api, verb); + afb_apis_call(areq, &wreq->context, client->api, verb); api_ws_server_req_unref(wreq); return; @@ -1016,6 +1028,8 @@ static void api_ws_server_accept(struct api_ws *api) lenaddr = (socklen_t)sizeof addr; client->fd = accept(api->fd, &addr, &lenaddr); if (client->fd >= 0) { + fcntl(client->fd, F_SETFD, FD_CLOEXEC); + fcntl(client->fd, F_SETFL, O_NONBLOCK); client->ws = afb_ws_create(afb_common_get_event_loop(), client->fd, &api_ws_server_ws_itf, client); if (client->ws != NULL) { client->api = api->api; @@ -1084,12 +1098,18 @@ static void api_ws_server_event_broadcast(void *closure, const char *event, int /******************* ws request part for server *****************/ /* increment the reference count of the request */ -static void api_ws_server_req_addref(struct api_ws_server_req *wreq) +static void api_ws_server_req_addref_cb(void *closure) { + struct api_ws_server_req *wreq = closure; wreq->refcount++; } /* decrement the reference count of the request and free/release it on falling to null */ +static void api_ws_server_req_unref_cb(void *closure) +{ + api_ws_server_req_unref(closure); +} + static void api_ws_server_req_unref(struct api_ws_server_req *wreq) { if (wreq == NULL || --wreq->refcount) @@ -1103,6 +1123,11 @@ static void api_ws_server_req_unref(struct api_ws_server_req *wreq) } /* get the object of the request */ +static struct json_object *api_ws_server_req_json_cb(void *closure) +{ + return api_ws_server_req_json(closure); +} + static struct json_object *api_ws_server_req_json(struct api_ws_server_req *wreq) { if (wreq->json == NULL) { @@ -1116,15 +1141,17 @@ static struct json_object *api_ws_server_req_json(struct api_ws_server_req *wreq } /* get the argument of the request of 'name' */ -static struct afb_arg api_ws_server_req_get(struct api_ws_server_req *wreq, const char *name) +static struct afb_arg api_ws_server_req_get_cb(void *closure, const char *name) { + struct api_ws_server_req *wreq = closure; return afb_msg_json_get_arg(api_ws_server_req_json(wreq), name); } -static void api_ws_server_req_success(struct api_ws_server_req *wreq, struct json_object *obj, const char *info) +static void api_ws_server_req_success_cb(void *closure, struct json_object *obj, const char *info) { int rc; struct writebuf wb = { .count = 0 }; + struct api_ws_server_req *wreq = closure; if (api_ws_write_char(&wb, 'T') && api_ws_write_uint32(&wb, wreq->msgid) @@ -1140,10 +1167,11 @@ success: json_object_put(obj); } -static void api_ws_server_req_fail(struct api_ws_server_req *wreq, const char *status, const char *info) +static void api_ws_server_req_fail_cb(void *closure, const char *status, const char *info) { int rc; struct writebuf wb = { .count = 0 }; + struct api_ws_server_req *wreq = closure; if (api_ws_write_char(&wb, 'F') && api_ws_write_uint32(&wb, wreq->msgid) @@ -1157,18 +1185,20 @@ static void api_ws_server_req_fail(struct api_ws_server_req *wreq, const char *s ERROR("error while sending fail"); } -static const char *api_ws_server_req_raw(struct api_ws_server_req *wreq, size_t *size) +static const char *api_ws_server_req_raw_cb(void *closure, size_t *size) { + struct api_ws_server_req *wreq = closure; if (size != NULL) *size = wreq->lenreq; return wreq->request; } -static void api_ws_server_req_send(struct api_ws_server_req *wreq, const char *buffer, size_t size) +static void api_ws_server_req_send_cb(void *closure, const char *buffer, size_t size) { /* TODO: how to put sized buffer as strings? things aren't clear here!!! */ int rc; struct writebuf wb = { .count = 0 }; + struct api_ws_server_req *wreq = closure; if (api_ws_write_char(&wb, 'X') && api_ws_write_uint32(&wb, wreq->msgid) @@ -1181,10 +1211,11 @@ static void api_ws_server_req_send(struct api_ws_server_req *wreq, const char *b ERROR("error while sending raw"); } -static int api_ws_server_req_subscribe(struct api_ws_server_req *wreq, struct afb_event event) +static int api_ws_server_req_subscribe_cb(void *closure, struct afb_event event) { int rc, rc2; struct writebuf wb = { .count = 0 }; + struct api_ws_server_req *wreq = closure; rc = afb_evt_add_watch(wreq->client->listener, event); if (rc < 0) @@ -1203,10 +1234,11 @@ success: return rc; } -static int api_ws_server_req_unsubscribe(struct api_ws_server_req *wreq, struct afb_event event) +static int api_ws_server_req_unsubscribe_cb(void *closure, struct afb_event event) { int rc, rc2; struct writebuf wb = { .count = 0 }; + struct api_ws_server_req *wreq = closure; if (api_ws_write_char(&wb, 'U') && api_ws_write_uint32(&wb, wreq->msgid) @@ -1222,9 +1254,10 @@ success: return rc; } -static void api_ws_server_req_subcall(struct api_ws_server_req *wreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure) +static void api_ws_server_req_subcall_cb(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure) { - afb_subcall(&wreq->context, api, verb, args, callback, closure, (struct afb_req){ .itf = &afb_api_ws_req_itf, .closure = wreq }); + struct api_ws_server_req *wreq = closure; + afb_subcall(&wreq->context, api, verb, args, callback, cb_closure, (struct afb_req){ .itf = &afb_api_ws_req_itf, .closure = wreq }); } /******************* server part **********************************/