Change-Id: Id7c183face3179a3b9cec7ed128e3a2561d9f3ad
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
### Application Framework Binder
### Application Framework Binder
-This is an undergoing work, publication is only intended for developers to review and provide feedback.
+This is an undergoing work, publication is only intended for developers to review and provide feedback.
or under Fedora (excepting libmicrohttpd and rtl-sdr):
```
$ dnf install git passwd iproute openssh-server openssh-client openssh-server # Tools needed on top of Docker Minimal Fedora
or under Fedora (excepting libmicrohttpd and rtl-sdr):
```
$ dnf install git passwd iproute openssh-server openssh-client openssh-server # Tools needed on top of Docker Minimal Fedora
-$ dnf install file-devel gcc gdb make pkgconfig cmake # install gcc developement tool chain + cmake
-$ dnf install file-devel json-c-devel libuuid-devel systemd-devel openssl-devel
+$ dnf install file-devel gcc gdb make pkgconfig cmake # install gcc development tool chain + cmake
+$ dnf install file-devel json-c-devel libuuid-devel systemd-devel openssl-devel
$ dnf install alsa-lib-devel pulseaudio-libs-devel glib2-devel gupnp-av-devel # optional but require to build audio plugin
```
$ dnf install alsa-lib-devel pulseaudio-libs-devel glib2-devel gupnp-av-devel # optional but require to build audio plugin
```
$ git clone https://gerrit.automotivelinux.org/gerrit/src/app-framework-binder ${AFB_DAEMON_DIR}
$ cd ${AFB_DAEMON_DIR}
$ mkdir -p build; cd build<br />
$ git clone https://gerrit.automotivelinux.org/gerrit/src/app-framework-binder ${AFB_DAEMON_DIR}
$ cd ${AFB_DAEMON_DIR}
$ mkdir -p build; cd build<br />
-$ export PKG_CONFIG_PATH=${LIBMICRODEST}/lib/pkgconfig
+$ export PKG_CONFIG_PATH=${LIBMICRODEST}/lib/pkgconfig
$ sudo make install<br />
```
$ sudo make install<br />
```
### Testing/Debug
```
$ ${AFB_DAEMON_DIR}/build/src/afb-daemon --help
### Testing/Debug
```
$ ${AFB_DAEMON_DIR}/build/src/afb-daemon --help
-$ ${AFB_DAEMON_DIR}/build/src/afb-daemon --port=1234 --token='' --ldpaths=${AFB_DAEMON_DIR}/build --sessiondir=/tmp --rootdir=${AFB_DAEMON_DIR}/test
+$ ${AFB_DAEMON_DIR}/build/src/afb-daemon --port=1234 --token='' --ldpaths=${AFB_DAEMON_DIR}/build --sessiondir=/tmp --rootdir=${AFB_DAEMON_DIR}/test
$ afb-daemon --verbose --port=<port> --token='' --sessiondir=<working directory> --rootdir=<web directory (index.html)>
```
$ afb-daemon --verbose --port=<port> --token='' --sessiondir=<working directory> --rootdir=<web directory (index.html)>
```
### REST API
Developers are intended to provide a structure containing : API name, corresponding methods/callbacks, and optionally a context and a handle.
### REST API
Developers are intended to provide a structure containing : API name, corresponding methods/callbacks, and optionally a context and a handle.
-A handle is a void* structure automatically passed to API callbacks.
-Callbacks also receive HTTP GET data as well as HTTP POST data, in case a POST method was used.
+A handle is a void* structure automatically passed to API callbacks.
+Callbacks also receive HTTP GET data as well as HTTP POST data, in case a POST method was used.
Every method should return a JSON object or NULL in case of error.
API plugins can be protected from timeout and other errors. By default this behaviour is deactivated, use --apitimeout to activate it.
Every method should return a JSON object or NULL in case of error.
API plugins can be protected from timeout and other errors. By default this behaviour is deactivated, use --apitimeout to activate it.
STATIC AFB_restapi myApis[]= {
{"ping" , AFB_SESSION_NONE, (AFB_apiCB)ping, "Ping Function"},
{"action1" , AFB_SESSION_CHECK, (AFB_apiCB)action1 , "Action-1"},
STATIC AFB_restapi myApis[]= {
{"ping" , AFB_SESSION_NONE, (AFB_apiCB)ping, "Ping Function"},
{"action1" , AFB_SESSION_CHECK, (AFB_apiCB)action1 , "Action-1"},
AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
plugin->type = AFB_PLUGIN_JSON;
plugin->info = "Plugin Sample";
AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
plugin->type = AFB_PLUGIN_JSON;
plugin->info = "Plugin Sample";
- plugin->prefix= "myPlugin";
+ plugin->prefix= "myPlugin";
plugin->apis = myApis;
return (plugin);
}
### HTML5 and AngularJS Redirects
plugin->apis = myApis;
return (plugin);
}
### HTML5 and AngularJS Redirects
-Binder supports HTML5 redirect mode even with an application baseurl.
-Default value for application base URL is /opa.
+Binder supports HTML5 redirect mode even with an application baseurl.
+Default value for application base URL is /opa.
See Application Framework HTML5 Client template at https://github.com/iotbzh/afb-client-sample
See Application Framework HTML5 Client template at https://github.com/iotbzh/afb-client-sample
-If the Binder receives something like _http://myopa/sample_ when sample is not the homepage of the AngularJS OPA,
-it will redirect to _http://myopa/#!sample_.
+If the Binder receives something like _http://myopa/sample_ when sample is not the homepage of the AngularJS OPA,
+it will redirect to _http://myopa/#!sample_.
This redirect will return the _index.html_ OPA file and will notify AngularJS not to display the homepage, but the sample page.
This redirect will return the _index.html_ OPA file and will notify AngularJS not to display the homepage, but the sample page.
-Warning: in order for AngularJS applications to be able to work with both BASEURL="/" and BASEURL="/MyApp/", all page references have to be relative.
+Warning: in order for AngularJS applications to be able to work with both BASEURL="/" and BASEURL="/MyApp/", all page references have to be relative.
Recommended model is to develop with a BASEURL="/opa" as any application working with a BASEURL will work without, while the opposite is not true.
Recommended model is to develop with a BASEURL="/opa" as any application working with a BASEURL will work without, while the opposite is not true.
-Note: If a resource is not accessible from ROOTDIR then the "--alias" switch should be used, as in: --alias=/icons:/usr/share/icons.
+Note: If a resource is not accessible from ROOTDIR then the "--alias" switch should be used, as in: --alias=/icons:/usr/share/icons.
Only use alias for external support static files. This should not be used for API and OPA.
Only use alias for external support static files. This should not be used for API and OPA.
Run the supervisor on the target for the public IP:
---------------------------------------------------
Run the supervisor on the target for the public IP:
---------------------------------------------------
- # afs-supervisor --port 1619 --token HELLO
+ # afs-supervisor --port 1619 --token HELLO
Run the client
--------------
Run the client
--------------
execute the API/VERB(ARGS) for the daemon of pid X
execute the API/VERB(ARGS) for the daemon of pid X
- usefull for (s/g)etting monitor info. ex: monitor/get({"apis":true})
+ useful for (s/g)etting monitor info. ex: monitor/get({"apis":true})
bound to the current client session (to be checked: usurpation of session?)
- trace {"pid":X, ...}
bound to the current client session (to be checked: usurpation of session?)
- trace {"pid":X, ...}
- like monitor/trace but not bound to session (in the future monitor/trace
+ like monitor/trace but not bound to session (in the future monitor/trace
will be bound to sessions)
allows to trace specific session or any session
the pid isn't returned in the event (not sure to want it but open...)
will be bound to sessions)
allows to trace specific session or any session
the pid isn't returned in the event (not sure to want it but open...)
- use "name" and "tag" feature of "trace" to discrimate events on the client side.
+ use "name" and "tag" feature of "trace" to discriminate events on the client side.
Examples of dialog:
-------------------
Examples of dialog:
-------------------
do { srd = read(fd, &initiator, sizeof initiator); } while(srd < 0 && errno == EINTR);
if (srd < 0) {
NOTICE("Can't read supervisor %s: %m", supervisor_socket_path);
do { srd = read(fd, &initiator, sizeof initiator); } while(srd < 0 && errno == EINTR);
if (srd < 0) {
NOTICE("Can't read supervisor %s: %m", supervisor_socket_path);
- * initalize the supervision
+ * initialize the supervision
*/
int afb_supervision_init()
{
*/
int afb_supervision_init()
{
}
/*
* Establish a websocket-like client connection to the API of 'uri' and if successful
}
/*
* Establish a websocket-like client connection to the API of 'uri' and if successful
- * instanciate a client afb_proto_ws websocket for this API using 'itf' and 'closure'.
+ * instantiate a client afb_proto_ws websocket for this API using 'itf' and 'closure'.
* (see afb_proto_ws_create_client).
* The systemd event loop 'eloop' is used to handle the websocket.
* (see afb_proto_ws_create_client).
* The systemd event loop 'eloop' is used to handle the websocket.
- * Returns NULL in case of failure with errno set appriately.
+ * Returns NULL in case of failure with errno set appropriately.
*/
struct afb_proto_ws *afb_ws_client_connect_api(struct sd_event *eloop, const char *uri, struct afb_proto_ws_client_itf *itf, void *closure)
{
*/
struct afb_proto_ws *afb_ws_client_connect_api(struct sd_event *eloop, const char *uri, struct afb_proto_ws_client_itf *itf, void *closure)
{
/*
* Makes the WebSocket handshake at the 'uri' and if successful
/*
* Makes the WebSocket handshake at the 'uri' and if successful
- * instanciate a wsj1 websocket for this connection using 'itf' and 'closure'.
+ * instantiate a wsj1 websocket for this connection using 'itf' and 'closure'.
* (see afb_wsj1_create).
* The systemd event loop 'eloop' is used to handle the websocket.
* (see afb_wsj1_create).
* The systemd event loop 'eloop' is used to handle the websocket.
- * Returns NULL in case of failure with errno set appriately.
+ * Returns NULL in case of failure with errno set appropriately.
*/
extern struct afb_wsj1 *afb_ws_client_connect_wsj1(struct sd_event *eloop, const char *uri, struct afb_wsj1_itf *itf, void *closure);
/*
* Establish a websocket-like client connection to the API of 'uri' and if successful
*/
extern struct afb_wsj1 *afb_ws_client_connect_wsj1(struct sd_event *eloop, const char *uri, struct afb_wsj1_itf *itf, void *closure);
/*
* Establish a websocket-like client connection to the API of 'uri' and if successful
- * instanciate a client afb_proto_ws websocket for this API using 'itf' and 'closure'.
+ * instantiate a client afb_proto_ws websocket for this API using 'itf' and 'closure'.
* (see afb_proto_ws_create_client).
* The systemd event loop 'eloop' is used to handle the websocket.
* (see afb_proto_ws_create_client).
* The systemd event loop 'eloop' is used to handle the websocket.
- * Returns NULL in case of failure with errno set appriately.
+ * Returns NULL in case of failure with errno set appropriately.
*/
extern struct afb_proto_ws *afb_ws_client_connect_api(struct sd_event *eloop, const char *uri, struct afb_proto_ws_client_itf *itf, void *closure);
*/
extern struct afb_proto_ws *afb_ws_client_connect_api(struct sd_event *eloop, const char *uri, struct afb_proto_ws_client_itf *itf, void *closure);
struct afb_context context; /**< context of the request */
struct afb_apiset *apiset; /**< apiset of the xreq */
struct json_object *json; /**< the json object (or NULL) */
struct afb_context context; /**< context of the request */
struct afb_apiset *apiset; /**< apiset of the xreq */
struct json_object *json; /**< the json object (or NULL) */
- const struct afb_xreq_query_itf *queryitf; /**< interface of xreq implmentation functions */
+ const struct afb_xreq_query_itf *queryitf; /**< interface of xreq implementation functions */
int refcount; /**< current ref count */
int replied; /**< is replied? */
int hookflags; /**< flags for hooking */
int refcount; /**< current ref count */
int replied; /**< is replied? */
int hookflags; /**< flags for hooking */
/**
* Macro for retrieve the pointer of a structure of 'type' having a field named 'field'
/**
* Macro for retrieve the pointer of a structure of 'type' having a field named 'field'
* @param type the type that has the 'field' (ex: "struct mystruct")
* @param field the name of the field within the structure 'type'
* @param ptr the pointer to an element 'field'
* @param type the type that has the 'field' (ex: "struct mystruct")
* @param field the name of the field within the structure 'type'
* @param ptr the pointer to an element 'field'
/**
* Macro for retrieve the pointer of a structure of 'type' having a field named "xreq"
/**
* Macro for retrieve the pointer of a structure of 'type' having a field named "xreq"
* @param type the type that has the field "xreq" (ex: "struct mystruct")
* @param x the pointer to the field "xreq"
* @return the pointer to the structure that contains the field "xreq" of address 'x'
* @param type the type that has the field "xreq" (ex: "struct mystruct")
* @param x the pointer to the field "xreq"
* @return the pointer to the structure that contains the field "xreq" of address 'x'
{SET_AUTH_TOKEN, 1, "token", "Initial Secret [default=" AFS_SUPERVISOR_TOKEN ", use --token="" to allow any token]"},
{SET_AUTH_TOKEN, 1, "token", "Initial Secret [default=" AFS_SUPERVISOR_TOKEN ", use --token="" to allow any token]"},
- {WS_SERVICE, 1, "ws-server", "Povide supervisor as websocket"},
+ {WS_SERVICE, 1, "ws-server", "Provide supervisor as websocket"},
{DISPLAY_VERSION, 0, "version", "Display version and copyright"},
{DISPLAY_HELP, 0, "help", "Display this help"},
{DISPLAY_VERSION, 0, "version", "Display version and copyright"},
{DISPLAY_HELP, 0, "help", "Display this help"},
- * initalize the supervision
+ * initialize the supervision
*/
int main(int ac, char **av)
{
*/
int main(int ac, char **av)
{
- * packet initialy sent by monitor at start
+ * packet initially sent by monitor at start
*/
struct afs_supervision_initiator
{
*/
struct afs_supervision_initiator
{
/*************************************************************************************/
/**
/*************************************************************************************/
/**
- * initalize the supervisor
+ * initialize the supervisor
*/
static int init_supervisor()
{
*/
static int init_supervisor()
{