X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fafb-hreq.c;h=16c235abca0fc059711f69505973442e7be38070;hb=11d36a9f7e16aa9992835f8ce06f0e1e5297b131;hp=16114675a08001310630b132e0086bdf0b48261d;hpb=1205c90cccd3144bab24b4b5fd8dcbf0d0e6b570;p=src%2Fapp-framework-binder.git diff --git a/src/afb-hreq.c b/src/afb-hreq.c index 16114675..16c235ab 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -16,18 +16,36 @@ */ #define _GNU_SOURCE -#include + +#include +#include +#include #include -#include +#include +#include #include -#include "../include/local-def.h" +#include + +#include "local-def.h" #include "afb-method.h" #include "afb-req-itf.h" #include "afb-hreq.h" +#include "session.h" + +#define SIZE_RESPONSE_BUFFER 8000 static char empty_string[] = ""; +static const char uuid_header[] = "x-afb-uuid"; +static const char uuid_arg[] = "uuid"; +static const char uuid_cookie[] = "uuid"; + +static const char token_header[] = "x-afb-token"; +static const char token_arg[] = "token"; +static const char token_cookie[] = "token"; + + struct hreq_data { struct hreq_data *next; char *key; @@ -36,10 +54,22 @@ struct hreq_data { char *value; }; +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 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 = { - .argument = (void*)afb_hreq_get_argument, - .is_argument_file = (void*)afb_hreq_is_argument_a_file, - .iterate_arguments = (void*)afb_hreq_iterate_arguments + .get = (void*)req_get, + .iterate = (void*)req_iterate, + .fail = (void*)req_fail, + .success = (void*)req_success, + .session_create = (void*)req_session_create, + .session_check = (void*)req_session_check, + .session_close = (void*)req_session_close }; static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create) @@ -105,8 +135,25 @@ static int validsubpath(const char *subpath) return 1; } +void afb_hreq_free(struct afb_hreq *hreq) +{ + struct hreq_data *data; + if (hreq != NULL) { + if (hreq->postform != NULL) + MHD_destroy_post_processor(hreq->postform); + for (data = hreq->data; data; data = hreq->data) { + hreq->data = data->next; + free(data->key); + free(data->value); + free(data); + } + ctxClientPut(hreq->context); + free(hreq); + } +} + /* - * Removes the 'prefix' of 'length' frome the tail of 'hreq' + * Removes the 'prefix' of 'length' from the tail of 'hreq' * if and only if the prefix exists and is terminated by a leading * slash */ @@ -161,12 +208,20 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f struct MHD_Response *response; /* Opens the file or directory */ - fd = openat(dirfd, filename, O_RDONLY); - if (fd < 0) { - if (errno == ENOENT) - return 0; - afb_hreq_reply_error(hreq, MHD_HTTP_FORBIDDEN); - return 1; + if (filename[0]) { + fd = openat(dirfd, filename, O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + return 0; + afb_hreq_reply_error(hreq, MHD_HTTP_FORBIDDEN); + return 1; + } + } else { + fd = dup(dirfd); + if (fd < 0) { + afb_hreq_reply_error(hreq, MHD_HTTP_INTERNAL_SERVER_ERROR); + return 1; + } } /* Retrieves file's status */ @@ -352,41 +407,158 @@ struct afb_req afb_hreq_to_req(struct afb_hreq *hreq) return (struct afb_req){ .itf = &afb_hreq_itf, .data = hreq }; } -struct iterator_data +static struct afb_arg req_get(struct afb_hreq *hreq, const char *name) +{ + struct hreq_data *hdat = get_data(hreq, name, 0); + if (hdat) + return (struct afb_arg){ + .name = hdat->key, + .value = hdat->value, + .size = hdat->length, + .is_file = (hdat->file != 0) + }; + + return (struct afb_arg){ + .name = name, + .value = MHD_lookup_connection_value(hreq->connection, MHD_GET_ARGUMENT_KIND, name), + .size = 0, + .is_file = 0 + }; +} + +struct iterdata { struct afb_hreq *hreq; - int (*iterator)(void *closure, const char *key, const char *value, int isfile); + int (*iterator)(void *closure, struct afb_arg arg); void *closure; }; -static int itargs(struct iterator_data *id, enum MHD_ValueKind kind, const char *key, const char *value) +static int _iterargs_(struct iterdata *id, enum MHD_ValueKind kind, const char *key, const char *value) { if (get_data(id->hreq, key, 0)) return 1; - return id->iterator(id->closure, key, value, 0); + return id->iterator(id->closure, (struct afb_arg){ + .name = key, + .value = value, + .size = 0, + .is_file = 0 + }); } -void afb_hreq_iterate_arguments(struct afb_hreq *hreq, int (*iterator)(void *closure, const char *key, const char *value, int isfile), void *closure) +static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure) { - struct iterator_data id = { .hreq = hreq, .iterator = iterator, .closure = closure }; - struct hreq_data *data = hreq->data; - while (data) { - if (!iterator(closure, data->key, data->value, !!data->file)) + 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, + .is_file = (hdat->file != 0)})) return; - data = data->next; + hdat = hdat->next; } - MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)itargs, &id); + MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_iterargs_, &id); } -void afb_hreq_drop_data(struct afb_hreq *hreq) +static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max) { - struct hreq_data *data = hreq->data; - while (data) { - hreq->data = data->next; - free(data->key); - free(data->value); - free(data); - data = hreq->data; + ssize_t len = stpncpy(buf, json_object_to_json_string(obj)+pos, max) - buf; + return len ? : -1; +} + +static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *status, const char *info, json_object *resp) +{ + json_object *root, *request; + struct MHD_Response *response; + + root = json_object_new_object(); + json_object_object_add(root, "jtype", json_object_new_string("afb-reply")); + request = json_object_new_object(); + json_object_object_add(root, "request", request); + json_object_object_add(request, "status", json_object_new_string(status)); + if (info) + json_object_object_add(request, "info", json_object_new_string(info)); + if (resp) + json_object_object_add(root, "response", resp); + if (hreq->context) { + json_object_object_add(request, uuid_arg, json_object_new_string(hreq->context->uuid)); + json_object_object_add(request, token_arg, json_object_new_string(hreq->context->token)); + } + + 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); +} + +static void req_fail(struct afb_hreq *hreq, const char *status, const char *info) +{ + req_reply(hreq, MHD_HTTP_OK, status, info, NULL); +} + +static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info) +{ + req_reply(hreq, MHD_HTTP_OK, "success", info, obj); +} + +struct AFB_clientCtx *afb_hreq_context(struct afb_hreq *hreq) +{ + const char *uuid; + + if (hreq->context == NULL) { + uuid = afb_hreq_get_header(hreq, uuid_header); + if (uuid == NULL) + uuid = afb_hreq_get_argument(hreq, uuid_arg); + if (uuid == NULL) + uuid = afb_hreq_get_cookie(hreq, uuid_cookie); + hreq->context = ctxClientGet(uuid); } + return hreq->context; } +static int req_session_create(struct afb_hreq *hreq) +{ + struct AFB_clientCtx *context = afb_hreq_context(hreq); + if (context == NULL) + return 0; + if (context->created) + return 0; + return req_session_check(hreq, 1); +} + +static int req_session_check(struct afb_hreq *hreq, int refresh) +{ + const char *token; + + struct AFB_clientCtx *context = afb_hreq_context(hreq); + + if (context == NULL) + return 0; + + token = afb_hreq_get_header(hreq, token_header); + if (token == NULL) + token = afb_hreq_get_argument(hreq, token_arg); + if (token == NULL) + token = afb_hreq_get_cookie(hreq, token_cookie); + if (token == NULL) + return 0; + + if (!ctxTokenCheck (context, token)) + return 0; + + if (refresh) { + ctxTokenNew (context); + } + + return 1; +} + +static void req_session_close(struct afb_hreq *hreq) +{ + struct AFB_clientCtx *context = afb_hreq_context(hreq); + if (context != NULL) + ctxClientClose(context); +} + + +