Remove returning token
[src/app-framework-binder.git] / docs / protocol-x-afb-ws-json1.md
index cc5fe91..3e3064f 100644 (file)
@@ -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
+```