diff options
-rw-r--r-- | docs/protocol-x-afb-ws-json1.md | 371 | ||||
-rw-r--r-- | src/afb-context.c | 7 | ||||
-rw-r--r-- | src/afb-context.h | 1 | ||||
-rw-r--r-- | src/afb-hook.c | 2 | ||||
-rw-r--r-- | src/afb-monitor.c | 3 | ||||
-rw-r--r-- | src/afb-msg-json.c | 6 | ||||
-rw-r--r-- | src/afb-session.c | 8 | ||||
-rw-r--r-- | src/afb-session.h | 1 | ||||
-rw-r--r-- | src/afb-supervision.c | 4 | ||||
-rw-r--r-- | src/afb-trace.c | 2 | ||||
-rw-r--r-- | src/afb-ws-json1.c | 2 | ||||
-rw-r--r-- | src/tests/session/test-session.c | 3 |
12 files changed, 195 insertions, 215 deletions
diff --git a/docs/protocol-x-afb-ws-json1.md b/docs/protocol-x-afb-ws-json1.md index cc5fe913..3e3064f6 100644 --- a/docs/protocol-x-afb-ws-json1.md +++ b/docs/protocol-x-afb-ws-json1.md @@ -1,5 +1,4 @@ -The websocket protocol x-afb-ws-json1 -===================================== +# The websocket protocol x-afb-ws-json1 The WebSocket protocol *x-afb-ws-json1* is used to communicate between an application and a binder. It allows access to all registered apis @@ -15,39 +14,36 @@ The registration to the IANA is still to be done, see: This document gives a short description of the protocol *x-afb-ws-json1*. A more formal description has to be done. - -Architecture ------------- +## Architecture The protocol is intended to be symmetric. It allows: - - to CALL a remote procedure that returns a result - - to push and receive EVENT - +- to CALL a remote procedure that returns a result +- to push and receive EVENT -Messages --------- +## Messages Valid messages are made of *text* frames that are all valid JSON. Valid messages are: Calls: -``` + +```txt [ 2, ID, PROCN, ARGS ] [ 2, ID, PROCN, ARGS, TOKEN ] ``` Replies (3: OK, 4: ERROR): -``` + +```txt [ 3, ID, RESP ] -[ 3, ID, RESP, TOKEN ] [ 4, ID, RESP ] -[ 4, ID, RESP, TOKEN ] ``` Events: -``` + +```txt [ 5, EVTN, OBJ ] ``` @@ -59,32 +55,41 @@ Where: | PROCN | string | The procedure name to call of the form "api/verb" | ARGS | any | Any argument to pass to the call (see afb_req_json that returns it) | RESP | any | The response to the call -| TOKEN | string | The token in case of refresh +| TOKEN | string | The authorisation token | EVTN | string | Name of the event in the form "api/event" | OBJ | any | The companion object of the event Below, an example of exchange: -``` +```txt C->S: [2,"156","hello/ping",null] S->C: [3,"156",{"response":"Some String","jtype":"afb-reply","request":{"status":"success","info":"Ping Binder Daemon tag=pingSample count=1 query=\"null\"","uuid":"ec30120c-6997-4529-9d63-c0de0cce56c0"}}] ``` +## History + +### 14 November 2019 + +Removal of token returning. The replies + +```txt +[ 3, ID, RESP, TOKEN ] +[ 4, ID, RESP, TOKEN ] +``` + +are removed from the specification. -Future ------- +## Future Here are the planned extensions: - - add binary messages with cbor data - - add calls with unstructured replies +- add binary messages with cbor data +- add calls with unstructured replies This could be implemented by extending the current protocol or by allowing the binder to accept either protocol including the new ones. - -Javascript implementation -------------------------- +## Javascript implementation The file **AFB.js** is a javascript implementation of the protocol. @@ -110,13 +115,13 @@ Here is that code: AFB = function(base, initialtoken){ if (typeof base != "object") - base = { base: base, token: initialtoken }; + base = { base: base, token: initialtoken }; var initial = { - base: base.base || "api", - token: base.token || initialtoken || "HELLO", - host: base.host || window.location.host, - url: base.url || undefined + base: base.base || "api", + token: base.token || initialtoken || "HELLO", + host: base.host || window.location.host, + url: base.url || undefined }; var urlws = initial.url || "ws://"+initial.host+"/"+initial.base; @@ -128,22 +133,22 @@ var urlws = initial.url || "ws://"+initial.host+"/"+initial.base; /*********************************************/ var AFB_context; { - var UUID = undefined; - var TOKEN = initial.token; - - var context = function(token, uuid) { - this.token = token; - this.uuid = uuid; - } - - context.prototype = { - get token() {return TOKEN;}, - set token(tok) {if(tok) TOKEN=tok;}, - get uuid() {return UUID;}, - set uuid(id) {if(id) UUID=id;} - }; - - AFB_context = new context(); + var UUID = undefined; + var TOKEN = initial.token; + + var context = function(token, uuid) { + this.token = token; + this.uuid = uuid; + } + + context.prototype = { + get token() {return TOKEN;}, + set token(tok) {if(tok) TOKEN=tok;}, + get uuid() {return UUID;}, + set uuid(id) {if(id) UUID=id;} + }; + + AFB_context = new context(); } /*********************************************/ /**** ****/ @@ -152,141 +157,141 @@ var AFB_context; /*********************************************/ var AFB_websocket; { - var CALL = 2; - var RETOK = 3; - var RETERR = 4; - var EVENT = 5; - - var PROTO1 = "x-afb-ws-json1"; - - AFB_websocket = function(on_open, on_abort) { - var u = urlws; - if (AFB_context.token) { - u = u + '?x-afb-token=' + AFB_context.token; - if (AFB_context.uuid) - u = u + '&x-afb-uuid=' + AFB_context.uuid; - } - this.ws = new WebSocket(u, [ PROTO1 ]); - this.url = u; - this.pendings = {}; - this.awaitens = {}; - this.counter = 0; - this.ws.onopen = onopen.bind(this); - this.ws.onerror = onerror.bind(this); - this.ws.onclose = onclose.bind(this); - this.ws.onmessage = onmessage.bind(this); - this.onopen = on_open; - this.onabort = on_abort; - } - - function onerror(event) { - var f = this.onabort; - if (f) { - delete this.onopen; - delete this.onabort; - f && f(this); - } - this.onerror && this.onerror(this); - } - - function onopen(event) { - var f = this.onopen; - delete this.onopen; - delete this.onabort; - f && f(this); - } - - function onclose(event) { - for (var id in this.pendings) { - try { this.pendings[id][1](); } catch (x) {/*TODO?*/} - } - this.pendings = {}; - this.onclose && this.onclose(); - } - - function fire(awaitens, name, data) { - var a = awaitens[name]; - if (a) - a.forEach(function(handler){handler(data);}); - var i = name.indexOf("/"); - if (i >= 0) { - a = awaitens[name.substring(0,i)]; - if (a) - a.forEach(function(handler){handler(data);}); - } - a = awaitens["*"]; - if (a) - a.forEach(function(handler){handler(data);}); - } - - function reply(pendings, id, ans, offset) { - if (id in pendings) { - var p = pendings[id]; - delete pendings[id]; - try { p[offset](ans); } catch (x) {/*TODO?*/} - } - } - - function onmessage(event) { - var obj = JSON.parse(event.data); - var code = obj[0]; - var id = obj[1]; - var ans = obj[2]; - AFB_context.token = obj[3]; - switch (code) { - case RETOK: - reply(this.pendings, id, ans, 0); - break; - case RETERR: - reply(this.pendings, id, ans, 1); - break; - case EVENT: - default: - fire(this.awaitens, id, ans); - break; - } - } - - function close() { - this.ws.close(); - this.ws.onopen = - this.ws.onerror = - this.ws.onclose = - this.ws.onmessage = - this.onopen = - this.onabort = function(){}; - } - - function call(method, request, callid) { - return new Promise((function(resolve, reject){ - var id, arr; - if (callid) { - id = String(callid); - if (id in this.pendings) - throw new Error("pending callid("+id+") exists"); - } else { - do { - id = String(this.counter = 4095 & (this.counter + 1)); - } while (id in this.pendings); - } - this.pendings[id] = [ resolve, reject ]; - arr = [CALL, id, method, request ]; - if (AFB_context.token) arr.push(AFB_context.token); - this.ws.send(JSON.stringify(arr)); - }).bind(this)); - } - - function onevent(name, handler) { - var id = name; - var list = this.awaitens[id] || (this.awaitens[id] = []); - list.push(handler); - } - - AFB_websocket.prototype = { - close: close, - call: call, - onevent: onevent - }; + var CALL = 2; + var RETOK = 3; + var RETERR = 4; + var EVENT = 5; + + var PROTO1 = "x-afb-ws-json1"; + + AFB_websocket = function(on_open, on_abort) { + var u = urlws; + if (AFB_context.token) { + u = u + '?x-afb-token=' + AFB_context.token; + if (AFB_context.uuid) + u = u + '&x-afb-uuid=' + AFB_context.uuid; + } + this.ws = new WebSocket(u, [ PROTO1 ]); + this.url = u; + this.pendings = {}; + this.awaitens = {}; + this.counter = 0; + this.ws.onopen = onopen.bind(this); + this.ws.onerror = onerror.bind(this); + this.ws.onclose = onclose.bind(this); + this.ws.onmessage = onmessage.bind(this); + this.onopen = on_open; + this.onabort = on_abort; + } + + function onerror(event) { + var f = this.onabort; + if (f) { + delete this.onopen; + delete this.onabort; + f && f(this); + } + this.onerror && this.onerror(this); + } + + function onopen(event) { + var f = this.onopen; + delete this.onopen; + delete this.onabort; + f && f(this); + } + + function onclose(event) { + for (var id in this.pendings) { + try { this.pendings[id][1](); } catch (x) {/*TODO?*/} + } + this.pendings = {}; + this.onclose && this.onclose(); + } + + function fire(awaitens, name, data) { + var a = awaitens[name]; + if (a) + a.forEach(function(handler){handler(data);}); + var i = name.indexOf("/"); + if (i >= 0) { + a = awaitens[name.substring(0,i)]; + if (a) + a.forEach(function(handler){handler(data);}); + } + a = awaitens["*"]; + if (a) + a.forEach(function(handler){handler(data);}); + } + + function reply(pendings, id, ans, offset) { + if (id in pendings) { + var p = pendings[id]; + delete pendings[id]; + try { p[offset](ans); } catch (x) {/*TODO?*/} + } + } + + function onmessage(event) { + var obj = JSON.parse(event.data); + var code = obj[0]; + var id = obj[1]; + var ans = obj[2]; + AFB_context.token = obj[3]; + switch (code) { + case RETOK: + reply(this.pendings, id, ans, 0); + break; + case RETERR: + reply(this.pendings, id, ans, 1); + break; + case EVENT: + default: + fire(this.awaitens, id, ans); + break; + } + } + + function close() { + this.ws.close(); + this.ws.onopen = + this.ws.onerror = + this.ws.onclose = + this.ws.onmessage = + this.onopen = + this.onabort = function(){}; + } + + function call(method, request, callid) { + return new Promise((function(resolve, reject){ + var id, arr; + if (callid) { + id = String(callid); + if (id in this.pendings) + throw new Error("pending callid("+id+") exists"); + } else { + do { + id = String(this.counter = 4095 & (this.counter + 1)); + } while (id in this.pendings); + } + this.pendings[id] = [ resolve, reject ]; + arr = [CALL, id, method, request ]; + if (AFB_context.token) arr.push(AFB_context.token); + this.ws.send(JSON.stringify(arr)); + }).bind(this)); + } + + function onevent(name, handler) { + var id = name; + var list = this.awaitens[id] || (this.awaitens[id] = []); + list.push(handler); + } + + AFB_websocket.prototype = { + close: close, + call: call, + onevent: onevent + }; } /*********************************************/ /**** ****/ @@ -294,8 +299,8 @@ var AFB_websocket; /**** ****/ /*********************************************/ return { - context: AFB_context, - ws: AFB_websocket + context: AFB_context, + ws: AFB_websocket }; }; -```
\ No newline at end of file +``` diff --git a/src/afb-context.c b/src/afb-context.c index 33cca0e9..4cdaa6f7 100644 --- a/src/afb-context.c +++ b/src/afb-context.c @@ -102,13 +102,6 @@ void afb_context_disconnect(struct afb_context *context) } } -const char *afb_context_sent_token(struct afb_context *context) -{ - if (context->session == NULL || context->closing || context->super) - return NULL; - return afb_session_token(context->session); -} - const char *afb_context_uuid(struct afb_context *context) { return context->session ? afb_session_uuid(context->session) : ""; diff --git a/src/afb-context.h b/src/afb-context.h index 2d44611b..83d01218 100644 --- a/src/afb-context.h +++ b/src/afb-context.h @@ -44,7 +44,6 @@ extern void afb_context_subinit(struct afb_context *context, struct afb_context extern int afb_context_connect(struct afb_context *context, const char *uuid, const char *token); extern int afb_context_connect_validated(struct afb_context *context, const char *uuid); extern void afb_context_disconnect(struct afb_context *context); -extern const char *afb_context_sent_token(struct afb_context *context); extern const char *afb_context_sent_uuid(struct afb_context *context); extern const char *afb_context_uuid(struct afb_context *context); diff --git a/src/afb-hook.c b/src/afb-hook.c index 6b1ab10c..1379caf8 100644 --- a/src/afb-hook.c +++ b/src/afb-hook.c @@ -1531,7 +1531,7 @@ static void _hook_session_(struct afb_session *session, const char *format, ...) static void hook_session_create_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session) { - _hook_session_(session, "create -> token=%s", afb_session_token(session)); + _hook_session_(session, "create"); } static void hook_session_close_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session) diff --git a/src/afb-monitor.c b/src/afb-monitor.c index 13687d36..e32c85ac 100644 --- a/src/afb-monitor.c +++ b/src/afb-monitor.c @@ -381,9 +381,8 @@ static void f_session(afb_req_t req) } /* make the result */ - wrap_json_pack(&r, "{s:s,s:s,s:i,s:i}", + wrap_json_pack(&r, "{s:s,s:i,s:i}", "uuid", afb_session_uuid(xreq->context.session), - "token", afb_session_token(xreq->context.session), "timeout", afb_session_timeout(xreq->context.session), "remain", afb_session_what_remains(xreq->context.session)); afb_req_success(req, r, NULL); diff --git a/src/afb-msg-json.c b/src/afb-msg-json.c index b1a83e73..fc736321 100644 --- a/src/afb-msg-json.c +++ b/src/afb-msg-json.c @@ -27,7 +27,7 @@ static const char _success_[] = "success"; struct json_object *afb_msg_json_reply(struct json_object *resp, const char *error, const char *info, struct afb_context *context) { json_object *msg, *request; - const char *token, *uuid; + const char *uuid; json_object *type_reply = NULL; msg = json_object_new_object(); @@ -45,10 +45,6 @@ struct json_object *afb_msg_json_reply(struct json_object *resp, const char *err json_object_object_add(request, "info", json_object_new_string(info)); if (context != NULL) { - token = afb_context_sent_token(context); - if (token != NULL) - json_object_object_add(request, "token", json_object_new_string(token)); - uuid = afb_context_sent_uuid(context); if (uuid != NULL) json_object_object_add(request, "uuid", json_object_new_string(uuid)); diff --git a/src/afb-session.c b/src/afb-session.c index 8fa44341..bb10c2cb 100644 --- a/src/afb-session.c +++ b/src/afb-session.c @@ -540,7 +540,7 @@ int afb_session_check_token (struct afb_session *session, const char *token) session_lock(session); r = !session->closed && session->expiration >= NOW - && !(session->token && strcmp(token, afb_session_token(session))); + && !(session->token && strcmp(token, afb_token_string(session->token))); session_unlock(session); return r; } @@ -551,12 +551,6 @@ const char *afb_session_uuid (struct afb_session *session) return session->uuid; } -/* Returns the token of 'session' */ -const char *afb_session_token (struct afb_session *session) -{ - return afb_token_string(session->token); -} - /** * Get the index of the 'key' in the cookies array. * @param key the key to scan diff --git a/src/afb-session.h b/src/afb-session.h index f6e848c8..6d17f87f 100644 --- a/src/afb-session.h +++ b/src/afb-session.h @@ -41,7 +41,6 @@ extern void afb_session_close(struct afb_session *session); extern int afb_session_is_closed (struct afb_session *session); extern int afb_session_check_token(struct afb_session *session, const char *token); -extern const char *afb_session_token(struct afb_session *session); extern int afb_session_timeout(struct afb_session *session); extern int afb_session_what_remains(struct afb_session *session); diff --git a/src/afb-supervision.c b/src/afb-supervision.c index 1575ae29..df045806 100644 --- a/src/afb-supervision.c +++ b/src/afb-supervision.c @@ -292,10 +292,8 @@ int afb_supervision_init(struct afb_apiset *apiset, struct json_object *config) static void slist(void *closure, struct afb_session *session) { struct json_object *list = closure; - struct json_object *item; - wrap_json_pack(&item, "{ss}", "token", afb_session_token(session)); - json_object_object_add(list, afb_session_uuid(session), item); + json_object_object_add(list, afb_session_uuid(session), NULL); } /****************************************************************************** diff --git a/src/afb-trace.c b/src/afb-trace.c index 5e349c7e..5f8ec64c 100644 --- a/src/afb-trace.c +++ b/src/afb-trace.c @@ -853,7 +853,7 @@ static void hook_session(void *closure, const struct afb_hookid *hookid, struct static void hook_session_create(void *closure, const struct afb_hookid *hookid, struct afb_session *session) { - hook_session(closure, hookid, session, "create", "{ss}", "token", afb_session_token(session)); + hook_session(closure, hookid, session, "create", NULL); } static void hook_session_close(void *closure, const struct afb_hookid *hookid, struct afb_session *session) diff --git a/src/afb-ws-json1.c b/src/afb-ws-json1.c index d0cca2bd..743f5a52 100644 --- a/src/afb-ws-json1.c +++ b/src/afb-ws-json1.c @@ -260,7 +260,7 @@ static void wsreq_reply(struct afb_xreq *xreq, struct json_object *object, const reply = afb_msg_json_reply(object, error, info, &xreq->context); rc = (error ? afb_wsj1_reply_error_j : afb_wsj1_reply_ok_j)( - wsreq->msgj1, reply, afb_context_sent_token(&wsreq->xreq.context)); + wsreq->msgj1, reply, NULL); if (rc) ERROR("Can't send reply: %m"); } diff --git a/src/tests/session/test-session.c b/src/tests/session/test-session.c index 444475ef..acdfcef4 100644 --- a/src/tests/session/test-session.c +++ b/src/tests/session/test-session.c @@ -53,13 +53,10 @@ START_TEST (check_creation) /* the session is valid */ ck_assert(afb_session_uuid(s) != NULL); - ck_assert(afb_session_token(s) != NULL); ck_assert(!afb_session_is_closed(s)); /* token is the initial one */ - ck_assert_str_eq(afb_session_token(s), GOOD_UUID); ck_assert(afb_session_check_token(s, GOOD_UUID)); - ck_assert(afb_session_check_token(s, afb_session_token(s))); /* query the session */ uuid = strdup(afb_session_uuid(s)); |