From 56f9ef4581d567248b6f83a3b15f39a0aca42895 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Fri, 8 Apr 2016 15:14:59 +0200 Subject: [PATCH] refactoring req interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: I6fc9246099c34f62c82e060cf014a63b0e8f63d8 Signed-off-by: José Bollo --- include/afb-req-itf.h | 27 ++- plugins/afm-main-plugin/afm-main-plugin.c | 8 +- plugins/samples/HelloWorld.c | 18 +- plugins/samples/SamplePost.c | 25 +-- src/TODO | 4 + src/afb-hreq.c | 83 ++++---- src/afb-hreq.h | 2 + src/afb-hsrv.c | 2 +- src/afb-ws-json.c | 315 ++++++++++++++++++++---------- src/session.c | 21 +- src/session.h | 1 + 11 files changed, 304 insertions(+), 202 deletions(-) create mode 100644 src/TODO diff --git a/include/afb-req-itf.h b/include/afb-req-itf.h index 9ced7630..7f7472f1 100644 --- a/include/afb-req-itf.h +++ b/include/afb-req-itf.h @@ -21,14 +21,15 @@ struct afb_arg { const char *name; const char *value; const char *path; - size_t size; }; struct afb_req_itf { + struct json_object *(*json)(void *data); struct afb_arg (*get)(void *data, const char *name); - void (*iterate)(void *data, int (*iterator)(void *closure, struct afb_arg arg), void *closure); - void (*fail)(void *data, const char *status, const char *info); void (*success)(void *data, struct json_object *obj, const char *info); + void (*fail)(void *data, const char *status, const char *info); + const char *(*raw)(void *data, size_t *size); + void (*send)(void *data, char *buffer, size_t size); int (*session_create)(void *data); int (*session_check)(void *data, int refresh); void (*session_close)(void *data); @@ -45,7 +46,7 @@ static inline struct afb_arg afb_req_get(struct afb_req req, const char *name) return req.itf->get(req.data, name); } -static inline const char *afb_req_argument(struct afb_req req, const char *name) +static inline const char *afb_req_value(struct afb_req req, const char *name) { return afb_req_get(req, name).value; } @@ -55,9 +56,14 @@ static inline const char *afb_req_path(struct afb_req req, const char *name) return afb_req_get(req, name).path; } -static inline void afb_req_iterate(struct afb_req req, int (*iterator)(void *closure, struct afb_arg arg), void *closure) +static inline struct json_object *afb_req_json(struct afb_req req) +{ + return req.itf->json(req.data); +} + +static inline void afb_req_success(struct afb_req req, struct json_object *obj, const char *info) { - req.itf->iterate(req.data, iterator, closure); + req.itf->success(req.data, obj, info); } static inline void afb_req_fail(struct afb_req req, const char *status, const char *info) @@ -65,9 +71,14 @@ static inline void afb_req_fail(struct afb_req req, const char *status, const ch req.itf->fail(req.data, status, info); } -static inline void afb_req_success(struct afb_req req, struct json_object *obj, const char *info) +static inline const char *afb_req_raw(struct afb_req req, size_t *size) { - req.itf->success(req.data, obj, info); + return req.itf->raw(req.data, size); +} + +static inline void afb_req_send(struct afb_req req, char *buffer, size_t size) +{ + req.itf->send(req.data, buffer, size); } static inline int afb_req_session_create(struct afb_req req) diff --git a/plugins/afm-main-plugin/afm-main-plugin.c b/plugins/afm-main-plugin/afm-main-plugin.c index a23b1971..b026fd80 100644 --- a/plugins/afm-main-plugin/afm-main-plugin.c +++ b/plugins/afm-main-plugin/afm-main-plugin.c @@ -91,7 +91,7 @@ static void call_appid(struct afb_req request, const char *method) { struct json_object *obj; char *sid; - const char *id = afb_req_argument(request, _id_); + const char *id = afb_req_value(request, _id_); if (id == NULL) { afb_req_fail(request, "bad-request", "missing 'id'"); return; @@ -114,7 +114,7 @@ static void call_appid(struct afb_req request, const char *method) static void call_runid(struct afb_req request, const char *method) { struct json_object *obj; - const char *id = afb_req_argument(request, _runid_); + const char *id = afb_req_value(request, _runid_); if (id == NULL) { afb_req_fail(request, "bad-request", "missing 'runid'"); return; @@ -151,13 +151,13 @@ static void start(struct afb_req request) int rc; /* get the id */ - id = afb_req_argument(request, _id_); + id = afb_req_value(request, _id_); if (id == NULL) { afb_req_fail(request, "bad-request", "missing 'id'"); return; } /* get the mode */ - mode = afb_req_argument(request, _mode_); + mode = afb_req_value(request, _mode_); if (mode == NULL || !strcmp(mode, _auto_)) { mode = interface->mode == AFB_MODE_REMOTE ? _remote_ : _local_; } diff --git a/plugins/samples/HelloWorld.c b/plugins/samples/HelloWorld.c index 7d99f6df..946f4b01 100644 --- a/plugins/samples/HelloWorld.c +++ b/plugins/samples/HelloWorld.c @@ -23,27 +23,11 @@ #include "afb-plugin.h" #include "afb-req-itf.h" -static int fillargs(json_object *args, struct afb_arg arg) -{ - json_object *obj; - - obj = json_object_new_object(); - json_object_object_add (obj, "value", json_object_new_string(arg.value)); - if (arg.path != NULL) - json_object_object_add (obj, "path", json_object_new_string(arg.path)); - json_object_object_add (obj, "size", json_object_new_int64((int64_t)arg.size)); - json_object_object_add (args, arg.name && *arg.name ? arg.name : "", obj); - return 1; /* continue to iterate */ -} - // Sample Generic Ping Debug API static void ping(struct afb_req request, json_object *jresp, const char *tag) { static int pingcount = 0; - json_object *query; - - query = json_object_new_object(); - afb_req_iterate(request, (void*)fillargs, query); + json_object *query = afb_req_json(request); afb_req_success_f(request, jresp, "Ping Binder Daemon tag=%s count=%d query=%s", tag, ++pingcount, json_object_to_json_string(query)); } diff --git a/plugins/samples/SamplePost.c b/plugins/samples/SamplePost.c index 8a1b477a..e5a7235f 100644 --- a/plugins/samples/SamplePost.c +++ b/plugins/samples/SamplePost.c @@ -25,27 +25,11 @@ #include "afb-req-itf.h" -static int fillargs(json_object *args, struct afb_arg arg) -{ - json_object *obj; - - obj = json_object_new_object(); - json_object_object_add (obj, "value", json_object_new_string(arg.value)); - if (arg.path != NULL) - json_object_object_add (obj, "path", json_object_new_string(arg.path)); - json_object_object_add (obj, "size", json_object_new_int64((int64_t)arg.size)); - json_object_object_add (args, arg.name && *arg.name ? arg.name : "", obj); - return 1; /* continue to iterate */ -} - // Sample Generic Ping Debug API static void getPingTest(struct afb_req request) { static int pingcount = 0; - json_object *query; - - query = json_object_new_object(); - afb_req_iterate(request, (void*)fillargs, query); + json_object *query = afb_req_json(request); afb_req_success_f(request, query, "Ping Binder Daemon count=%d", ++pingcount); } @@ -53,12 +37,9 @@ static void getPingTest(struct afb_req request) // With content-type=json data are directly avaliable in request->post->data static void GetJsonByPost (struct afb_req request) { - json_object* jresp; - json_object *query; struct afb_arg arg; - - query = json_object_new_object(); - afb_req_iterate(request, (void*)fillargs, query); + json_object* jresp; + json_object *query = afb_req_json(request); arg = afb_req_get(request, ""); jresp = arg.value ? json_tokener_parse(arg.value) : NULL; diff --git a/src/TODO b/src/TODO new file mode 100644 index 00000000..86373d27 --- /dev/null +++ b/src/TODO @@ -0,0 +1,4 @@ +april 8, 2016 +------------- + - finish properly websockets (the structure is currently pending) + - diff --git a/src/afb-hreq.c b/src/afb-hreq.c index 953c80a1..00c27eb1 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -60,19 +60,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 +85,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; @@ -465,7 +467,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 +504,63 @@ 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) +{ + struct MHD_Response *response = MHD_create_response_from_buffer((unsigned)size, buffer, MHD_RESPMEM_MUST_FREE); + MHD_queue_response(hreq->connection, MHD_HTTP_OK, response); + MHD_destroy_response(response); } static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max) diff --git a/src/afb-hreq.h b/src/afb-hreq.h index 37bda99e..41f499d0 100644 --- a/src/afb-hreq.h +++ b/src/afb-hreq.h @@ -17,6 +17,7 @@ struct AFB_session; struct AFB_clientCtx; +struct json_object; struct afb_hreq { const char *cacheTimeout; @@ -30,6 +31,7 @@ struct afb_hreq { struct MHD_PostProcessor *postform; struct AFB_clientCtx *context; struct hreq_data *data; + struct json_object *json; int upgrade; }; diff --git a/src/afb-hsrv.c b/src/afb-hsrv.c index efbb9356..c58295a4 100644 --- a/src/afb-hsrv.c +++ b/src/afb-hsrv.c @@ -162,7 +162,7 @@ static int access_handler( if (!MHD_post_process (hreq->postform, upload_data, *upload_data_size)) goto internal_error; } else { - if (!afb_hreq_post_add(hreq, NULL, upload_data, *upload_data_size)) + if (!afb_hreq_post_add(hreq, "", upload_data, *upload_data_size)) goto internal_error; } *upload_data_size = 0; diff --git a/src/afb-ws-json.c b/src/afb-ws-json.c index 43c70a4f..a1766888 100644 --- a/src/afb-ws-json.c +++ b/src/afb-ws-json.c @@ -93,162 +93,255 @@ error: static void aws_on_close(struct afb_ws_json *ws, uint16_t code, char *text, size_t size) { - /* do nothing */ + /* do nothing but free the text */ free(text); } +#define CALL 2 +#define RETOK 3 +#define RETERR 4 struct afb_wsreq { struct afb_ws_json *aws; struct afb_wsreq *next; - struct json_object *id; - struct json_object *name; - struct json_object *token; - struct json_object *request; + char *text; + size_t size; + int code; + char *id; + size_t idlen; + char *api; + size_t apilen; + char *verb; + size_t verblen; + char *obj; + size_t objlen; + char *tok; + size_t toklen; + struct json_object *root; }; + +static struct json_object *wsreq_json(struct afb_wsreq *wsreq); static struct afb_arg wsreq_get(struct afb_wsreq *wsreq, const char *name); -static void wsreq_iterate(struct afb_wsreq *wsreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure); static void wsreq_fail(struct afb_wsreq *wsreq, const char *status, const char *info); static void wsreq_success(struct afb_wsreq *wsreq, struct json_object *obj, const char *info); +static const char *wsreq_raw(struct afb_wsreq *wsreq, size_t *size); +static void wsreq_send(struct afb_wsreq *wsreq, char *buffer, size_t size); static int wsreq_session_create(struct afb_wsreq *wsreq); static int wsreq_session_check(struct afb_wsreq *wsreq, int refresh); static void wsreq_session_close(struct afb_wsreq *wsreq); + static const struct afb_req_itf wsreq_itf = { + .json = (void*)wsreq_json, .get = (void*)wsreq_get, - .iterate = (void*)wsreq_iterate, - .fail = (void*)wsreq_fail, .success = (void*)wsreq_success, + .fail = (void*)wsreq_fail, + .raw = (void*)wsreq_raw, + .send = (void*)wsreq_send, .session_create = (void*)wsreq_session_create, .session_check = (void*)wsreq_session_check, .session_close = (void*)wsreq_session_close }; -static int aws_handle_json(struct afb_ws_json *aws, struct json_object *obj) +static int aws_wsreq_parse(struct afb_wsreq *r, char *text, size_t size) { - struct afb_req r; - int count, num; - struct json_object *type, *id, *name, *req, *token; - struct afb_wsreq *wsreq; - const char *api, *verb; - size_t lenapi, lenverb; - - /* protocol inspired by http://www.gir.fr/ocppjs/ocpp_srpc_spec.shtml */ + char *pos, *end, c; + int aux; + + /* scan */ + pos = text; + end = text + size; + + /* scans: [ */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + if (*pos++ != '[') goto bad_header; + + /* scans code: 2|3|4 */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + switch (*pos++) { + case '2': r->code = CALL; break; + case '3': r->code = RETOK; break; + case '4': r->code = RETERR; break; + default: goto bad_header; + } - /* the object must be an array of 4 or 5 elements */ - if (!json_object_is_type(obj, json_type_array)) - goto error; - count = json_object_array_length(obj); - if (count < 4 || count > 5) - goto error; + /* scans: , */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + if (*pos++ != ',') goto bad_header; + + /* scans id: "id" */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + if (*pos++ != '"') goto bad_header; + r->id = pos; + while(pos < end && *pos != '"') pos++; + if (pos == end) goto bad_header; + r->idlen = (size_t)(pos++ - r->id); + + /* scans: , */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + if (*pos++ != ',') goto bad_header; + + /* scans the method if needed */ + if (r->code == CALL) { + /* scans: " */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + if (*pos++ != '"') goto bad_header; + + /* scans: api/ */ + r->api = pos; + while(pos < end && *pos != '"' && *pos != '/') pos++; + if (pos == end) goto bad_header; + if (*pos != '/') goto bad_header; + r->apilen = (size_t)(pos++ - r->api); + if (r->apilen && r->api[r->apilen - 1] == '\\') + r->apilen--; + + /* scans: verb" */ + r->verb = pos; + while(pos < end && *pos != '"') pos++; + if (pos == end) goto bad_header; + r->verblen = (size_t)(pos++ - r->verb); + + /* scans: , */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + if (*pos++ != ',') goto bad_header; + } - /* get the 5 elements: type id name request token */ - type = json_object_array_get_idx(obj, 0); - id = json_object_array_get_idx(obj, 1); - name = json_object_array_get_idx(obj, 2); - req = json_object_array_get_idx(obj, 3); - token = json_object_array_get_idx(obj, 4); + /* scan obj */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + aux = 0; + r->obj = pos; + while (pos < end && (aux != 0 || (*pos != ',' && *pos != ']'))) { + if (pos == end) goto bad_header; + switch(*pos) { + case '{': case '[': aux++; break; + case '}': case ']': if (!aux--) goto bad_header; break; + case '"': + do { + pos += 1 + (*pos == '\\'); + } while(pos < end && *pos != '"'); + default: + break; + } + pos++; + } + if (pos > end) goto bad_header; + if (pos == end && aux != 0) goto bad_header; + c = *pos; + r->objlen = (size_t)(pos++ - r->obj); + while (r->objlen && r->obj[r->objlen - 1] == ' ') + r->objlen--; + + /* scan the token (if any) */ + if (c == ',') { + /* scans token: "token" */ + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + if (*pos++ != '"') goto bad_header; + r->tok = pos; + while(pos < end && *pos != '"') pos++; + if (pos == end) goto bad_header; + r->toklen = (size_t)(pos++ - r->tok); + while(pos < end && *pos == ' ') pos++; + if (pos == end) goto bad_header; + c = *pos++; + } - /* check the types: int string string object string */ - if (!json_object_is_type(type, json_type_int)) - goto error; - if (!json_object_is_type(id, json_type_string)) - goto error; - if (!json_object_is_type(name, json_type_string)) - goto error; - if (!json_object_is_type(req, json_type_object)) - goto error; - if (token != NULL && !json_object_is_type(token, json_type_string)) - goto error; + /* scan: ] */ + if (c != ']') goto bad_header; + while(pos < end && *pos == ' ') pos++; + if (pos != end) goto bad_header; + + /* done */ + r->text = text; + r->size = size; +fprintf(stderr, "\n\nONTEXT([%d, %.*s, %.*s/%.*s, %.*s, %.*s])\n\n", + r->code, + (int)r->idlen, r->id, + (int)r->apilen, r->api, + (int)r->verblen, r->verb, + (int)r->objlen, r->obj, + (int)r->toklen, r->tok +); + return 1; - /* the type is only 2 */ - num = json_object_get_int(type); - if (num != 2) - goto error; +bad_header: + return 0; +} - /* checks the api/verb structure of name */ - api = json_object_get_string(name); - for (lenapi = 0 ; api[lenapi] && api[lenapi] != '/' ; lenapi++); - if (!lenapi || !api[lenapi]) - goto error; - verb = &api[lenapi+1]; - for (lenverb = 0 ; verb[lenverb] && verb[lenverb] != '/' ; lenverb++); - if (!lenverb || verb[lenverb]) - goto error; +static void aws_on_text(struct afb_ws_json *ws, char *text, size_t size) +{ + struct afb_req r; + struct afb_wsreq *wsreq; - /* allocates the request data */ - wsreq = malloc(sizeof *wsreq); + /* allocate */ + wsreq = calloc(1, sizeof *wsreq); if (wsreq == NULL) - goto error; + goto alloc_error; + + /* init */ + if (!aws_wsreq_parse(wsreq, text, size)) + goto bad_header; /* fill and record the request */ - wsreq->aws = aws; - wsreq->id = json_object_get(id); - wsreq->name = json_object_get(name); - wsreq->token = json_object_get(token); - wsreq->request = json_object_get(req); - wsreq->next = aws->requests; - aws->requests = wsreq; - json_object_put(obj); + wsreq->aws = ws; + wsreq->next = ws->requests; + ws->requests = wsreq; r.data = wsreq; r.itf = &wsreq_itf; - afb_apis_call(r, aws->context, api, lenapi, verb, lenverb); - return 1; + afb_apis_call(r, ws->context, wsreq->api, wsreq->apilen, wsreq->verb, wsreq->verblen); + return; -error: - json_object_put(obj); - return 0; +bad_header: + free(wsreq); +alloc_error: + free(text); + afb_ws_close(ws->ws, 1008); + return; } -static void aws_on_text(struct afb_ws_json *ws, char *text, size_t size) +static struct json_object *wsreq_json(struct afb_wsreq *wsreq) { - struct json_object *obj; - json_tokener_reset(ws->tokener); - obj = json_tokener_parse_ex(ws->tokener, text, (int)size); - if (obj == NULL) { - afb_ws_close(ws->ws, 1008); - } else if (!aws_handle_json(ws, obj)) { - afb_ws_close(ws->ws, 1008); + struct json_object *root = wsreq->root; + if (root == NULL) { + json_tokener_reset(wsreq->aws->tokener); + root = json_tokener_parse_ex(wsreq->aws->tokener, wsreq->obj, (int)wsreq->objlen); + if (root == NULL) { + /* lazy discovering !!!! not good TODO improve*/ + root = json_object_new_object(); + } + wsreq->root = root; } + return root; } static struct afb_arg wsreq_get(struct afb_wsreq *wsreq, const char *name) { struct afb_arg arg; - struct json_object *value; + struct json_object *value, *root; - if (json_object_object_get_ex(wsreq->request, name, &value)) { + root = wsreq_json(wsreq); + if (json_object_object_get_ex(root, name, &value)) { arg.name = name; arg.value = json_object_get_string(value); - arg.size = strlen(arg.value); } else { arg.name = NULL; arg.value = NULL; - arg.size = 0; } arg.path = NULL; return arg; } -static void wsreq_iterate(struct afb_wsreq *wsreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure) -{ - struct afb_arg arg; - struct json_object_iterator it = json_object_iter_begin(wsreq->request); - struct json_object_iterator end = json_object_iter_end(wsreq->request); - - arg.size = 0; - arg.path = NULL; - while(!json_object_iter_equal(&it, &end)) { - arg.name = json_object_iter_peek_name(&it); - arg.value = json_object_get_string(json_object_iter_peek_value(&it)); - if (!iterator(closure, arg)) - break; - json_object_iter_next(&it); - } -} - static int wsreq_session_create(struct afb_wsreq *wsreq) { struct AFB_clientCtx *context = wsreq->aws->context; @@ -259,17 +352,12 @@ static int wsreq_session_create(struct afb_wsreq *wsreq) static int wsreq_session_check(struct afb_wsreq *wsreq, int refresh) { - const char *token; struct AFB_clientCtx *context = wsreq->aws->context; - if (wsreq->token == NULL) - return 0; - - token = json_object_get_string(wsreq->token); - if (token == NULL) + if (wsreq->tok == NULL) return 0; - if (!ctxTokenCheck (context, token)) + if (!ctxTokenCheckLen (context, wsreq->tok, wsreq->toklen)) return 0; if (refresh) { @@ -305,7 +393,7 @@ static void wsreq_reply(struct afb_wsreq *wsreq, int retcode, const char *status /* make the reply */ reply = json_object_new_array(); json_object_array_add(reply, json_object_new_int(retcode)); - json_object_array_add(reply, wsreq->id); + json_object_array_add(reply, json_object_new_string_len(wsreq->id, (int)wsreq->idlen)); json_object_array_add(reply, root); json_object_array_add(reply, json_object_new_string(wsreq->aws->context->token)); @@ -319,11 +407,22 @@ static void wsreq_reply(struct afb_wsreq *wsreq, int retcode, const char *status static void wsreq_fail(struct afb_wsreq *wsreq, const char *status, const char *info) { - wsreq_reply(wsreq, 4, status, info, NULL); + wsreq_reply(wsreq, RETERR, status, info, NULL); } static void wsreq_success(struct afb_wsreq *wsreq, json_object *obj, const char *info) { - wsreq_reply(wsreq, 3, "success", info, obj); + wsreq_reply(wsreq, RETOK, "success", info, obj); +} + +static const char *wsreq_raw(struct afb_wsreq *wsreq, size_t *size) +{ + *size = wsreq->objlen; + return wsreq->obj; +} + +static void wsreq_send(struct afb_wsreq *wsreq, char *buffer, size_t size) +{ + afb_ws_text(wsreq->aws->ws, buffer, size); } diff --git a/src/session.c b/src/session.c index 11f535b3..936bb4df 100644 --- a/src/session.c +++ b/src/session.c @@ -243,7 +243,7 @@ void ctxClientClose (struct AFB_clientCtx *clientCtx) } // Sample Generic Ping Debug API -int ctxTokenCheck (struct AFB_clientCtx *clientCtx, const char *token) +int ctxTokenCheckLen (struct AFB_clientCtx *clientCtx, const char *token, size_t length) { assert(clientCtx != NULL); assert(token != NULL); @@ -252,13 +252,20 @@ int ctxTokenCheck (struct AFB_clientCtx *clientCtx, const char *token) if (ctxStoreTooOld (clientCtx, NOW)) return 0; - if (!clientCtx->token[0] || 0 == strcmp (token, clientCtx->token)) { - clientCtx->created = 1; /* creates by default */ - return 1; - } + if (clientCtx->token[0] && (length >= sizeof(clientCtx->token) || strncmp (token, clientCtx->token, length) || clientCtx->token[length])) + return 0; + + clientCtx->created = 1; /* creates by default */ + return 1; +} + +// Sample Generic Ping Debug API +int ctxTokenCheck (struct AFB_clientCtx *clientCtx, const char *token) +{ + assert(clientCtx != NULL); + assert(token != NULL); - // Token is not valid let move level of assurance to zero and free attached client handle - return 0; + return ctxTokenCheckLen(clientCtx, token, strlen(token)); } // generate a new token and update client context diff --git a/src/session.h b/src/session.h index 4a1c400b..c11921b6 100644 --- a/src/session.h +++ b/src/session.h @@ -33,5 +33,6 @@ extern struct AFB_clientCtx *ctxClientGet(struct AFB_clientCtx *clientCtx); extern void ctxClientPut(struct AFB_clientCtx *clientCtx); extern void ctxClientClose (struct AFB_clientCtx *clientCtx); extern int ctxTokenCheck (struct AFB_clientCtx *clientCtx, const char *token); +extern int ctxTokenCheckLen (struct AFB_clientCtx *clientCtx, const char *token, size_t length); extern void ctxTokenNew (struct AFB_clientCtx *clientCtx); -- 2.16.6