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
 
 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.
 
 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:
 
 
 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:
 
 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):
 [ 2, ID, PROCN, ARGS ]
 [ 2, ID, PROCN, ARGS, TOKEN ]
 ```
 
 Replies (3: OK, 4: ERROR):
-```
+
+```txt
 [ 3, ID, RESP ]
 [ 3, ID, RESP ]
-[ 3, ID, RESP, TOKEN ]
 [ 4, ID, RESP ]
 [ 4, ID, RESP ]
-[ 4, ID, RESP, TOKEN ]
 ```
 
 Events:
 ```
 
 Events:
-```
+
+```txt
 [ 5, EVTN, OBJ ]
 ```
 
 [ 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
 | 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:
 
 | 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"}}]
 ```
 
 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:
 
 
 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.
 
 
 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.
 
 
 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")
 AFB = function(base, initialtoken){
 
 if (typeof base != "object")
-       base = { base: base, token: initialtoken };
+   base = { base: base, token: initialtoken };
 
 var initial = {
 
 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;
 };
 
 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 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 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 {
 /****                                     ****/
 /*********************************************/
 return {
-       context: AFB_context,
-       ws: AFB_websocket
+   context: AFB_context,
+   ws: AFB_websocket
 };
 };
 };
 };
-```
\ No newline at end of file
+```