diff options
author | Fulup Ar Foll <fulup@iot.bzh> | 2016-05-30 18:56:37 +0200 |
---|---|---|
committer | Fulup Ar Foll <fulup@iot.bzh> | 2016-05-30 18:56:37 +0200 |
commit | 8e83c4de6a2366b96ab950c1d69db830483fb9ff (patch) | |
tree | 62f6ffe982ff12f3a2a37e5e01599bf80323b2a5 | |
parent | 8902bb356f6b67c31e54cb23c27cd375f2f4ccdb (diff) |
afb-application-writing.md review
-rw-r--r-- | doc/afb-application-writing.md | 137 | ||||
-rw-r--r-- | nbproject/configurations.xml | 174 |
2 files changed, 163 insertions, 148 deletions
diff --git a/doc/afb-application-writing.md b/doc/afb-application-writing.md index a2bbf4d5..ee583479 100644 --- a/doc/afb-application-writing.md +++ b/doc/afb-application-writing.md @@ -6,109 +6,104 @@ HOWTO WRITE an APPLICATION above AGL FRAMEWORK TABLE-OF-CONTENT-HERE -Languages for writing Applications ----------------------------------- +Programmation Languages for Applications +----------------------------------------- ### Writing an HTML5 application -Developpers of HTML5 applications (client side) can easyly create -applications for AGL framework using their prefered -HTML framework. +Developers of HTML5 applications (client side) can easily create +applications for AGL framework using their preferred +HTML5 framework. -Developpers can also create powerful server side plugins to improve -their application. This server side plugin should return the mime-type -application/json and can be accessed either by HTTP or by Websockets. +Developers may also take advantage of powerful server side plugins to improve +application behavior. Server side plugins return an application/json mine-type +and can be accessed though either HTTP or Websockets. -In a near future, the JSON-RPC protocol will be available together -with the current x-afb-json1 protocol. +In a near future, JSON-RPC protocol should be added to complete current x-afb-json1 protocol. Two examples of HTML5 applications are given: -- [afb-client](https://github.com/iotbzh/afb-client) a simple "hello world" application +- [afb-client](https://github.com/iotbzh/afb-client) a simple "hello world" application template -- [afm-client](https://github.com/iotbzh/afm-client) a simple "Home screen" application +- [afm-client](https://github.com/iotbzh/afm-client) a simple "Home screen" application template ### Writing a Qt application -Writing Qt applications is also possible because Qt offers APIs to -make HTTP queries and to connect using WebSockets. +Writing Qt applications is also supported. Qt offers standard API to send request through HTTP or WebSockets. -It is even possible to write a QML application. -It is demontrated by the sample application token-websock: +It is also possible to write QML applications. A sample QML application [token-websock] is avaliable.. - [token-websock](https://github.com/iotbzh/afb-daemon/blob/master/test/token-websock.qml) a simple "hello world" application in QML -### Writing a C application +### Writing "C" application -C applications can use the binder afb-daemon through a websocket connection. +C applications can use afb-daemon binder through a websocket connection. -The library **libafbwsc** is made for C clients that want -to connect to the afb-daemon binder. +The library **libafbwsc** is provided for C clients that need +to connect with an afb-daemon binder. -The program **afb-client-demo** is the C program that use -the provided library **libafbwsc**. -Its source code is here +The program **afb-client-demo** is the C example that use +**libafbwsc** library. +Source code is available here [src/afb-client-demo.c](https://github.com/iotbzh/afb-daemon/blob/master/src/afb-client-demo.c). -The current implementation use libsystemd and file descriptors. -This may be changed in the future to also support secure sockets -and being less dependant of libsystemd. +Current implementation relies on libsystemd and file descriptors. +This model might be review in the future to support secure sockets +and free the dependency with libsystemd. Handling sessions within applications ------------------------------------- -Applications must be aware of the the features session and token -when they interact with the binder afb-daemon. +Applications should understand sessions and tokens management when interacting with afb-daemon binder. -Applications are communicating with their binder afb-daemon using -a network connection or a kind of network connection (unix domain -socket isn't currently implemented but could be used in near future). -Also, HTTP protocol is not a connected protocol. It means that -the socket connection can not be used to authenticate a client. +Applications are communicating with their private binder(afb-daemon) using +a network connection or potentially any other connection channel. While current version +does not yet implement unix domain this feature might be added in a near future. +Developers need to be warn that HTTP protocol is a none connected protocol. This prevents +from using HTTP socket connection to authenticate clients. For this reason, the binder should authenticate the application -by using a commonly shared secret named token and the identification -of the client named session. +by using a shared secret. The secret is named "token" and the identification +of client is named "session". The examples **token-websock.qml** and **afb-client** are demonstrating how authentication and sessions are managed. ### Handling sessions -Plugins and features of the binder need to keep track of the client -instances. This of importance for plugins running as service -because they may have to separate the data of each client. +Plugins and other binder feature need to keep track of client +instances. This is especially important for plugins running as services +as they may typically have to keep each client's data separated. For HTML5 applications, the web runtime handles the cookie of session that the binder afb-daemon automatically sets. -In any case, the session identifier can be set using the parameters -**uuid** or **x-afb-uuid** in the request uri. That is understood -by HTTP requests and by the negociation of websockets. +Session identifier can be set using the parameter +**uuid** or **x-afb-uuid** in URI requests. Within current version of the +framework session UUID is supported by both HTTP requests and websocket negotiation. ### Exchanging tokens -At start, the framework communicates a common secret to both the binder -and its client: the application. This initial secret is the -initial token. +At application start, AGL framework communicates a shared secret to both binder +and client application. This initial secret is called the "initial token". For each of its client application, the binder manages a current active -token for the session. This authentication token can be a requirement for -accessing some methods. +token for session management. This authentication token can be use to restrict +access to some plugin's methods. -The token must be passed in the request uri on HTTP or at connecting -websockets using the parameter **token** or **x-afb-token**. +The token must be included in URI request on HTTP or during websockets +connection using parameter **token** or **x-afb-token**. To ensure security, tokens must be refreshed periodically. ### Example of session management -For the following exmples, we suppose that you launched **afb-daemon** like that or similar: +In following examples, we suppose that **afb-daemon** is launched with something equivalent to: $ afb-daemon --port=1234 --token=123456 [...] -with the expectation that the plugin **AuthLogin** is loaded. +making the expectation that **AuthLogin** plugin is requested as default. #### Using curl @@ -125,10 +120,10 @@ First, connects with the initial token, 123456: "response": {"token": "A New Token and Session Context Was Created"} } -It returns an answer containing the uuid of the session, 850c4594-1be1-4e9b-9fcc-38cc3e6ff015, -and the refreshed token, 850c4594-1be1-4e9b-9fcc-38cc3e6ff015. +It returns an answer containing session UUID, 850c4594-1be1-4e9b-9fcc-38cc3e6ff015, +and a refreshed token, 850c4594-1be1-4e9b-9fcc-38cc3e6ff015. -Let check that it is available: +Check if session and token is valid: $ curl http://localhost:1234/api/auth/check?token=0aef6841-2ddd-436d-b961-ae78da3b5c5f\&uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015 { @@ -137,7 +132,7 @@ Let check that it is available: "response": {"isvalid":true} } -It works! So try now to refresh the token: +Refresh the token: $ curl http://localhost:1234/api/auth/refresh?token=0aef6841-2ddd-436d-b961-ae78da3b5c5f\&uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015 { @@ -149,7 +144,7 @@ It works! So try now to refresh the token: "response": {"token":"Token was refreshed"} } -Let now close the session: +Close the session: curl http://localhost:1234/api/auth/logout?token=b8ec3ec3-6ffe-448c-9a6c-efda69ad7bd9\&uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015 { @@ -158,7 +153,7 @@ Let now close the session: "response": {"info":"Token and all resources are released"} } -So now, checking for the uuid will be refused: +Checking on closed session for uuid should be refused: curl http://localhost:1234/api/auth/check?token=b8ec3ec3-6ffe-448c-9a6c-efda69ad7bd9\&uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015 { @@ -189,12 +184,12 @@ Here is an example of exchange using **afb-client-demo**: ON-REPLY 6:auth/refresh: {"jtype":"afb-reply","request":{"status":"success", "token":"e83b36f8-d945-463d-b983-5d8ed73ba529"},"response":{"token":"Token was refreshed"}} -Then you leave. And can reconnect as below: +After closing connection, reconnect as here after: $ afb-client-demo ws://localhost:1234/api?token=e83b36f8-d945-463d-b983-5d8ed73ba529\&uuid=5fcc3f3d-4b84-4fc7-ba66-2d8bd34ae7d1 auth check ON-REPLY 1:auth/check: {"jtype":"afb-reply","request":{"status":"success"},"response":{"isvalid":true}} -The same can be continued using **curl**: +Same connection check using **curl**: $ curl http://localhost:1234/api/auth/check?token=e83b36f8-d945-463d-b983-5d8ed73ba529\&uuid=5fcc3f3d-4b84-4fc7-ba66-2d8bd34ae7d1 {"jtype":"afb-reply","request":{"status":"success"},"response":{"isvalid":true}} @@ -202,19 +197,19 @@ The same can be continued using **curl**: Format of replies ----------------- -The replies are made of one javascript object returned using JSON serialization. +Replies use javascript object returned as serialized JSON. -This object containts at least 2 mandatory fields of name **jtype** and **request** -and an optionnal field of name **response**. +This object contains at least 2 mandatory fields of name **jtype** and **request** +and one optional field of name **response**. ### Field jtype -The field **jtype** must have a value of type string equel to **"afb-reply"**. +The field **jtype** must have a value of type string equal to **"afb-reply"**. ### Field request The field **request** must have a value of type object. This request object -has at least one field named **status** and four optionnal fields of name +has at least one field named **status** and four optional fields named **info**, **token**, **uuid**, **reqid**. #### Subfield request.status @@ -224,26 +219,26 @@ only in case of success. #### Subfield request.info -**info** is of type string and represent optionnal the information added to the reply. +**info** is of type string and represent optional information added to the reply. #### Subfield request.token -**token** is of type string. It is sent either on the creation of the -session or when the token is refreshed. +**token** is of type string. It is sent either at session creation +or when the token is refreshed. #### Subfield request.uuid -**uuid** is of type string. It is sent on the creation of the session. +**uuid** is of type string. It is sent at session creation. #### Subfield request.reqid -**reqid** is of type string. It is sent in response of HTTP requests -that added a parameter of name **reqid** or **x-afb-reqid**. The value -sent in the reply is the exact value received on the request. +**reqid** is of type string. It is sent in response to HTTP requests +that added a parameter of name **reqid** or **x-afb-reqid** at request time. +Value returns in the reply has the exact same value as the one received in the request. ### Field response -This field response optionnaly containts the object returned with successful replies. +This field response optionally contains an object returned when request succeeded. ### Template diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index 40d93459..e7a060ac 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -70,9 +70,8 @@ <rebuildPropChanged>false</rebuildPropChanged> </toolsSet> <flagsDictionary> - <element flagsID="0" commonFlags="-fPIC"/> - <element flagsID="1" commonFlags="-fPIE"/> - <element flagsID="2" commonFlags="-mtune=generic -march=x86-64 -fPIC"/> + <element flagsID="0" commonFlags="-fPIE"/> + <element flagsID="1" commonFlags="-mtune=generic -march=x86-64 -fPIC"/> </flagsDictionary> <codeAssistance> </codeAssistance> @@ -82,7 +81,7 @@ <buildCommand>${MAKE} -f Makefile</buildCommand> <cleanCommand>${MAKE} -f Makefile clean</cleanCommand> <executablePath>build/afb-daemon</executablePath> - <cTool flags="2"> + <cTool flags="1"> </cTool> </makeTool> <preBuild> @@ -103,28 +102,30 @@ <folder path="0/plugins/afm-main-plugin"> <cTool> <incDir> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> - <pElem>build/plugins/afm-main-plugin</pElem> + <pElem>plugins/afm-main-plugin</pElem> </incDir> <preprocessorList> <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> - <Elem>afm_main_api_EXPORTS</Elem> + <Elem>__PIC__=2</Elem> + <Elem>__REGISTER_PREFIX__=</Elem> + <Elem>__USER_LABEL_PREFIX__=</Elem> + <Elem>__pic__=2</Elem> + <Elem>afm_main_api_EXPORTS=1</Elem> </preprocessorList> </cTool> </folder> <folder path="0/plugins/audio"> <cTool> <incDir> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> - <pElem>build/plugins/audio</pElem> + <pElem>plugins/audio</pElem> </incDir> <preprocessorList> <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> - <Elem>audio_api_EXPORTS</Elem> + <Elem>__PIC__=2</Elem> + <Elem>__REGISTER_PREFIX__=</Elem> + <Elem>__USER_LABEL_PREFIX__=</Elem> + <Elem>__pic__=2</Elem> + <Elem>audio_api_EXPORTS=1</Elem> </preprocessorList> </cTool> </folder> @@ -142,27 +143,31 @@ <folder path="0/plugins/samples"> <cTool> <incDir> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> + <pElem>plugins/samples</pElem> <pElem>build/plugins/samples</pElem> </incDir> <preprocessorList> <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> + <Elem>__PIC__=2</Elem> + <Elem>__REGISTER_PREFIX__=</Elem> + <Elem>__USER_LABEL_PREFIX__=</Elem> + <Elem>__pic__=2</Elem> </preprocessorList> </cTool> </folder> <folder path="0/plugins/session"> <cTool> <incDir> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> + <pElem>plugins/session</pElem> <pElem>build/plugins/session</pElem> </incDir> <preprocessorList> <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> - <Elem>token_api_EXPORTS</Elem> + <Elem>__PIC__=2</Elem> + <Elem>__REGISTER_PREFIX__=</Elem> + <Elem>__USER_LABEL_PREFIX__=</Elem> + <Elem>__pic__=2</Elem> + <Elem>token_api_EXPORTS=1</Elem> </preprocessorList> </cTool> </folder> @@ -170,59 +175,83 @@ ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> + <incDir> + <pElem>include</pElem> + <pElem>/usr/include/uuid</pElem> + <pElem>build/plugins/afm-main-plugin</pElem> + </incDir> </cTool> </item> <item path="plugins/afm-main-plugin/utils-jbus.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> + <incDir> + <pElem>/usr/lib64/dbus-1.0/include/dbus</pElem> + <pElem>/usr/include/dbus-1.0/dbus</pElem> + <pElem>/usr/include/dbus-1.0</pElem> + <pElem>/usr/lib64/dbus-1.0/include</pElem> + <pElem>build/plugins/afm-main-plugin</pElem> + </incDir> </cTool> </item> <item path="plugins/audio/audio-alsa.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> + <incDir> + <pElem>include</pElem> + <pElem>/usr/include/json-c</pElem> + <pElem>/usr/include/uuid</pElem> + <pElem>build/plugins/audio</pElem> + </incDir> </cTool> </item> <item path="plugins/audio/audio-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> + <incDir> + <pElem>/usr/include/json-c</pElem> + <pElem>include</pElem> + <pElem>/usr/include/uuid</pElem> + <pElem>build/plugins/audio</pElem> + </incDir> </cTool> </item> <item path="plugins/radio/radio-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="2"> + <cTool flags="1"> </cTool> </item> <item path="plugins/radio/radio-rtlsdr.c" ex="false" tool="0" flavor2="2"> - <cTool flags="2"> + <cTool flags="1"> </cTool> </item> <item path="plugins/samples/ClientCtx.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <preprocessorList> - <Elem>clientCtx_api_EXPORTS</Elem> + <Elem>clientCtx_api_EXPORTS=1</Elem> </preprocessorList> </cTool> </item> <item path="plugins/samples/HelloWorld.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <preprocessorList> - <Elem>helloWorld_api_EXPORTS</Elem> + <Elem>helloWorld_api_EXPORTS=1</Elem> </preprocessorList> </cTool> </item> <item path="plugins/samples/SamplePost.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <preprocessorList> - <Elem>samplePost_api_EXPORTS</Elem> + <Elem>samplePost_api_EXPORTS=1</Elem> </preprocessorList> </cTool> </item> <item path="plugins/session/token-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> </cTool> </item> <item path="src/afbs-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="1"> + <cTool flags="0"> <incDir> <pElem>plugins/audio</pElem> <pElem>/usr/include/json-c</pElem> @@ -236,7 +265,7 @@ </cTool> </item> <item path="src/alsa-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="1"> + <cTool flags="0"> <incDir> <pElem>plugins/audio</pElem> <pElem>/usr/include/json-c</pElem> @@ -250,23 +279,25 @@ </cTool> </item> <item path="src/config.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <incDir> - <pElem>include</pElem> + <pElem>src</pElem> <pElem>/usr/include/json-c</pElem> + <pElem>include</pElem> <pElem>/usr/include/uuid</pElem> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> <pElem>build/src</pElem> </incDir> <preprocessorList> <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> + <Elem>__PIC__=2</Elem> + <Elem>__REGISTER_PREFIX__=</Elem> + <Elem>__USER_LABEL_PREFIX__=</Elem> + <Elem>__pic__=2</Elem> </preprocessorList> </cTool> </item> <item path="src/dbus-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="1"> + <cTool flags="0"> <incDir> <pElem>plugins/audio</pElem> <pElem>/usr/include/json-c</pElem> @@ -280,55 +311,47 @@ </cTool> </item> <item path="src/helper-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <incDir> - <pElem>include</pElem> + <pElem>src</pElem> <pElem>/usr/include/json-c</pElem> + <pElem>include</pElem> <pElem>/usr/include/uuid</pElem> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> <pElem>build/src</pElem> </incDir> - <preprocessorList> - <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> - </preprocessorList> </cTool> </item> <item path="src/http-svc.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <incDir> - <pElem>include</pElem> + <pElem>src</pElem> <pElem>/usr/include/json-c</pElem> + <pElem>include</pElem> <pElem>/usr/include/uuid</pElem> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> <pElem>build/src</pElem> </incDir> - <preprocessorList> - <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> - </preprocessorList> </cTool> </item> <item path="src/main.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <incDir> - <pElem>include</pElem> + <pElem>src</pElem> <pElem>/usr/include/json-c</pElem> + <pElem>include</pElem> <pElem>/usr/include/uuid</pElem> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> <pElem>build/src</pElem> </incDir> <preprocessorList> <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> + <Elem>__PIC__=2</Elem> + <Elem>__REGISTER_PREFIX__=</Elem> + <Elem>__USER_LABEL_PREFIX__=</Elem> + <Elem>__pic__=2</Elem> </preprocessorList> </cTool> </item> <item path="src/radio-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="1"> + <cTool flags="0"> <incDir> <pElem>plugins/audio</pElem> <pElem>/usr/include/json-c</pElem> @@ -346,34 +369,31 @@ </cTool> </item> <item path="src/rest-api.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <incDir> - <pElem>include</pElem> + <pElem>src</pElem> <pElem>/usr/include/json-c</pElem> + <pElem>include</pElem> <pElem>/usr/include/uuid</pElem> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> <pElem>build/src</pElem> </incDir> - <preprocessorList> - <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> - </preprocessorList> </cTool> </item> <item path="src/session.c" ex="false" tool="0" flavor2="2"> - <cTool flags="0"> + <cTool flags="1"> <incDir> - <pElem>include</pElem> + <pElem>src</pElem> <pElem>/usr/include/json-c</pElem> <pElem>/usr/include/uuid</pElem> - <pElem>/usr/include/dbus-1.0</pElem> - <pElem>/usr/lib64/dbus-1.0/include</pElem> - <pElem>/usr/include/alsa</pElem> + <pElem>include</pElem> <pElem>build/src</pElem> </incDir> <preprocessorList> <Elem>PLUGIN_INSTALL_DIR="/usr/local/lib64/afb"</Elem> + <Elem>__PIC__=2</Elem> + <Elem>__REGISTER_PREFIX__=</Elem> + <Elem>__USER_LABEL_PREFIX__=</Elem> + <Elem>__pic__=2</Elem> </preprocessorList> </cTool> </item> |