X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-hreq.c;h=9984cbcbe9d63fff1f803594f05394c19e2bc403;hb=fcef933b69ccc363ad10d9f7308f02c5dc474ff6;hp=953c80a15372af2df1ad043695f36a978fd12889;hpb=83ce3b29a598141f8f28afde655beb07ec78c312;p=src%2Fapp-framework-binder.git diff --git a/src/afb-hreq.c b/src/afb-hreq.c index 953c80a1..9984cbcb 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -51,6 +51,8 @@ static const char token_header[] = "x-afb-token"; static const char token_arg[] = "token"; static const char token_cookie[] = "token"; +static char *cookie_name = NULL; +static char *cookie_setter = NULL; struct hreq_data { struct hreq_data *next; @@ -60,19 +62,23 @@ struct hreq_data { char *path; }; +static struct json_object *req_json(struct afb_hreq *hreq); static struct afb_arg req_get(struct afb_hreq *hreq, const char *name); -static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure); static void req_fail(struct afb_hreq *hreq, const char *status, const char *info); static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info); +static const char *req_raw(struct afb_hreq *hreq, size_t *size); +static void req_send(struct afb_hreq *hreq, char *buffer, size_t size); static int req_session_create(struct afb_hreq *hreq); static int req_session_check(struct afb_hreq *hreq, int refresh); static void req_session_close(struct afb_hreq *hreq); static const struct afb_req_itf afb_hreq_itf = { + .json = (void*)req_json, .get = (void*)req_get, - .iterate = (void*)req_iterate, - .fail = (void*)req_fail, .success = (void*)req_success, + .fail = (void*)req_fail, + .raw = (void*)req_raw, + .send = (void*)req_send, .session_create = (void*)req_session_create, .session_check = (void*)req_session_check, .session_close = (void*)req_session_close @@ -81,8 +87,6 @@ static const struct afb_req_itf afb_hreq_itf = { static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create) { struct hreq_data *data = hreq->data; - if (key == NULL) - key = empty_string; while (data != NULL) { if (!strcasecmp(data->key, key)) return data; @@ -147,6 +151,64 @@ static int validsubpath(const char *subpath) #define MAGIC_DB "/usr/share/misc/magic.mgc" #endif +static void afb_hreq_reply_v(struct afb_hreq *hreq, unsigned status, struct MHD_Response *response, va_list args) +{ + char *cookie; + const char *k, *v; + k = va_arg(args, const char *); + while (k != NULL) { + v = va_arg(args, const char *); + MHD_add_response_header(response, k, v); + k = va_arg(args, const char *); + } + if (hreq->context != NULL && asprintf(&cookie, cookie_setter, hreq->context->uuid)) { + MHD_add_response_header(response, MHD_HTTP_HEADER_SET_COOKIE, cookie); + free(cookie); + } + MHD_queue_response(hreq->connection, status, response); + MHD_destroy_response(response); +} + +void afb_hreq_reply(struct afb_hreq *hreq, unsigned status, struct MHD_Response *response, ...) +{ + va_list args; + va_start(args, response); + afb_hreq_reply_v(hreq, status, response, args); + va_end(args); +} + +void afb_hreq_reply_empty(struct afb_hreq *hreq, unsigned status, ...) +{ + va_list args; + va_start(args, status); + afb_hreq_reply_v(hreq, status, MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT), args); + va_end(args); +} + +void afb_hreq_reply_static(struct afb_hreq *hreq, unsigned status, size_t size, char *buffer, ...) +{ + va_list args; + va_start(args, buffer); + afb_hreq_reply_v(hreq, status, MHD_create_response_from_buffer((unsigned)size, buffer, MHD_RESPMEM_PERSISTENT), args); + va_end(args); +} + +void afb_hreq_reply_copy(struct afb_hreq *hreq, unsigned status, size_t size, char *buffer, ...) +{ + va_list args; + va_start(args, buffer); + afb_hreq_reply_v(hreq, status, MHD_create_response_from_buffer((unsigned)size, buffer, MHD_RESPMEM_MUST_COPY), args); + va_end(args); +} + +void afb_hreq_reply_free(struct afb_hreq *hreq, unsigned status, size_t size, char *buffer, ...) +{ + va_list args; + va_start(args, buffer); + afb_hreq_reply_v(hreq, status, MHD_create_response_from_buffer((unsigned)size, buffer, MHD_RESPMEM_MUST_FREE), args); + va_end(args); +} + static magic_t lazy_libmagic() { static int done = 0; @@ -221,11 +283,16 @@ void afb_hreq_free(struct afb_hreq *hreq) MHD_destroy_post_processor(hreq->postform); for (data = hreq->data; data; data = hreq->data) { hreq->data = data->next; + if (data->path) { + unlink(data->path); + free(data->path); + } free(data->key); free(data->value); free(data); } ctxClientPut(hreq->context); + json_object_put(hreq->json); free(hreq); } } @@ -259,20 +326,7 @@ int afb_hreq_valid_tail(struct afb_hreq *hreq) void afb_hreq_reply_error(struct afb_hreq *hreq, unsigned int status) { - char *buffer; - int length; - struct MHD_Response *response; - - length = asprintf(&buffer, "error %u", status); - if (length > 0) - response = MHD_create_response_from_buffer((unsigned)length, buffer, MHD_RESPMEM_MUST_FREE); - else { - buffer = "error"; - response = MHD_create_response_from_buffer(strlen(buffer), buffer, MHD_RESPMEM_PERSISTENT); - } - if (!MHD_queue_response(hreq->connection, status, response)) - fprintf(stderr, "Failed to reply error code %u", status); - MHD_destroy_response(response); + afb_hreq_reply_empty(hreq, status, NULL); } int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *filename) @@ -380,10 +434,10 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f } /* fills the value and send */ - MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, hreq->cacheTimeout); - MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etag); - MHD_queue_response(hreq->connection, status, response); - MHD_destroy_response(response); + afb_hreq_reply(hreq, status, response, + MHD_HTTP_HEADER_CACHE_CONTROL, hreq->cacheTimeout, + MHD_HTTP_HEADER_ETAG, etag, + NULL); return 1; } @@ -397,12 +451,8 @@ int afb_hreq_reply_file(struct afb_hreq *hreq, int dirfd, const char *filename) int afb_hreq_redirect_to(struct afb_hreq *hreq, const char *url) { - struct MHD_Response *response; - - response = MHD_create_response_from_buffer(0, empty_string, MHD_RESPMEM_PERSISTENT); - MHD_add_response_header(response, MHD_HTTP_HEADER_LOCATION, url); - MHD_queue_response(hreq->connection, MHD_HTTP_MOVED_PERMANENTLY, response); - MHD_destroy_response(response); + afb_hreq_reply_static(hreq, MHD_HTTP_MOVED_PERMANENTLY, 0, NULL, + MHD_HTTP_HEADER_LOCATION, url, NULL); if (verbosity) fprintf(stderr, "redirect from [%s] to [%s]\n", hreq->url, url); return 1; @@ -465,7 +515,6 @@ int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *f ssize_t sz; struct hreq_data *hdat = get_data(hreq, key, 1); -fprintf(stderr, "%s=%s %s=%s %s\n",key,hdat->key,file,hdat->value,hdat->path); if (hdat->value == NULL) { hdat->value = strdup(file); if (hdat->value == NULL) @@ -503,51 +552,61 @@ static struct afb_arg req_get(struct afb_hreq *hreq, const char *name) return (struct afb_arg){ .name = hdat->key, .value = hdat->value, - .size = hdat->length, .path = hdat->path }; return (struct afb_arg){ .name = name, .value = MHD_lookup_connection_value(hreq->connection, MHD_GET_ARGUMENT_KIND, name), - .size = 0, .path = NULL }; } -struct iterdata +static int _iterargs_(struct json_object *obj, enum MHD_ValueKind kind, const char *key, const char *value) { - struct afb_hreq *hreq; - int (*iterator)(void *closure, struct afb_arg arg); - void *closure; -}; + json_object_object_add(obj, key, value ? json_object_new_string(value) : NULL); + return 1; +} -static int _iterargs_(struct iterdata *id, enum MHD_ValueKind kind, const char *key, const char *value) +static struct json_object *req_json(struct afb_hreq *hreq) { - if (get_data(id->hreq, key, 0)) - return 1; - return id->iterator(id->closure, (struct afb_arg){ - .name = key, - .value = value ? : "", - .size = value ? strlen(value) : 0, - .path = NULL - }); + struct hreq_data *hdat; + struct json_object *obj, *val; + + obj = hreq->json; + if (obj == NULL) { + hreq->json = obj = json_object_new_object(); + if (obj == NULL) { + } else { + MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_iterargs_, obj); + for (hdat = hreq->data ; hdat ; hdat = hdat->next) { + if (hdat->path == NULL) + val = hdat->value ? json_object_new_string(hdat->value) : NULL; + else { + val = json_object_new_object(); + if (val == NULL) { + } else { + json_object_object_add(val, "file", json_object_new_string(hdat->value)); + json_object_object_add(val, "path", json_object_new_string(hdat->path)); + } + } + json_object_object_add(obj, hdat->key, val); + } + } + } + return obj; } -static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure) +static const char *req_raw(struct afb_hreq *hreq, size_t *size) { - struct iterdata id = { .hreq = hreq, .iterator = iterator, .closure = closure }; - struct hreq_data *hdat = hreq->data; - while (hdat) { - if (!iterator(closure, (struct afb_arg){ - .name = hdat->key, - .value = hdat->value, - .size = hdat->length, - .path = hdat->path})) - return; - hdat = hdat->next; - } - MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_iterargs_, &id); + const char *result = json_object_get_string(req_json(hreq)); + *size = result ? strlen(result) : 0; + return result; +} + +static void req_send(struct afb_hreq *hreq, char *buffer, size_t size) +{ + afb_hreq_reply_free(hreq, MHD_HTTP_OK, size, buffer, NULL); } static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max) @@ -576,8 +635,7 @@ static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *statu } response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, SIZE_RESPONSE_BUFFER, (void*)send_json_cb, root, (void*)json_object_put); - MHD_queue_response(hreq->connection, retcode, response); - MHD_destroy_response(response); + afb_hreq_reply(hreq, retcode, response, NULL); } static void req_fail(struct afb_hreq *hreq, const char *status, const char *info) @@ -599,7 +657,7 @@ struct AFB_clientCtx *afb_hreq_context(struct afb_hreq *hreq) if (uuid == NULL) uuid = afb_hreq_get_argument(hreq, uuid_arg); if (uuid == NULL) - uuid = afb_hreq_get_cookie(hreq, uuid_cookie); + uuid = afb_hreq_get_cookie(hreq, cookie_name); hreq->context = ctxClientGetForUuid(uuid); } return hreq->context; @@ -649,5 +707,24 @@ static void req_session_close(struct afb_hreq *hreq) ctxClientClose(context); } +int afb_hreq_init_cookie(int port, const char *path, int maxage) +{ + int rc; + + free(cookie_name); + free(cookie_setter); + cookie_name = NULL; + cookie_setter = NULL; + + path = path ? : "/"; + rc = asprintf(&cookie_name, "x-afb-uuid-%d", port); + if (rc < 0) + return 0; + rc = asprintf(&cookie_setter, "%s=%%s; Path=%s; Max-Age=%d; HttpOnly", + cookie_name, path, maxage); + if (rc < 0) + return 0; + return 1; +}