Compare commits

...

198 Commits

Author SHA1 Message Date
c1501cba28 [RELEASE] Release v1.0.0 2021-02-16 21:47:29 +01:00
2cf3dd9189 [DEBUG] update new API of lutin log 2019-05-03 10:18:22 +02:00
3dd3b7526d [DEBUG] set zeus framework work again 2019-04-01 22:06:03 +02:00
1ae7682017 [DEBUG] set zeus work again 2018-10-30 22:06:43 +01:00
bfe15a00fa [DEV] update new etk Uri API 2018-10-23 22:19:32 +02:00
e02f711d66 [DEV] update new URI 2018-10-09 23:03:07 +02:00
30c36d9bc1 [DEV] update etk null 2018-06-19 22:13:48 +02:00
e94abc47f3 [DEBUG] correct etk toLower 2018-06-19 21:18:39 +02:00
2033bf86ee [DEV] add microsoft mime type 2018-04-24 23:51:03 +02:00
0e3f4b5311 [DEBUG] correct build of the player 2017-11-07 13:36:58 +01:00
1d791be465 [DEV] update to the new ETK allocator wrapper 2017-10-21 19:05:21 +02:00
e8a09ef7d2 [DEV/DEBUG] add etk::typeInfo declaration and correct add and remove object in list not thread safe 2017-10-14 11:27:20 +02:00
046e270179 [DEBUG] correct wrong init 2017-10-14 11:25:16 +02:00
e7771b706d [DEV] add support of redirect the client on direct connection of the gateway (if authorised in routeur config file) 2017-10-14 11:24:45 +02:00
27a7c404fb [DEV] gateway support the direct connection of client with dynamic port 2017-10-14 11:23:37 +02:00
c11e723363 [DOC] change help on architecture 2017-10-14 11:22:33 +02:00
be0d3a6d23 [DEV] add factore to file to permit to have virtual file 2017-10-09 23:50:10 +02:00
a02d121421 [DEV] update new ETK 2017-09-26 15:51:25 +02:00
c8a9290648 [DEV] continue removing STL 2017-09-14 00:59:21 +02:00
dff27aed6d [DEV] remove STL 2017-09-07 23:38:26 +02:00
b1b52cef16 [DEV] continue removing stl 2017-08-28 00:06:18 +02:00
ce60711d56 [DEV] add videoPlayer thumb 2017-06-28 08:30:03 +02:00
ef2b52dc1b [DEV] add the small image in the group 2017-06-25 15:03:16 +02:00
c5f58d6af6 [DEBUG] correct the service video return 2017-06-25 15:01:58 +02:00
feaa41eb15 [DEV] add cover management at the video interface 2017-06-24 13:51:32 +02:00
cb52e084d5 [DEBUG] correct override missing 2017-06-24 13:50:57 +02:00
2a5f0bcda8 [DEBUG] missing \ befor the " elements 2017-06-24 13:10:12 +02:00
48b6f823f8 [DEBUG] coorect the dead lock of each thead in the thread pool 2017-06-23 01:14:59 +02:00
16fee04656 [DEV] correct the video display 2017-06-18 14:01:55 +02:00
0a8dc71521 [DEV] correct basic client 2017-06-15 23:42:22 +02:00
6951f04742 [DEV] add basic client 2017-06-14 08:27:06 +02:00
a57925d535 [DOC] write 80% of the documentation 2017-06-13 13:27:52 +02:00
56072e960e [DEBUG] try to stabilyse the media stream and the call stability 2017-06-09 00:55:40 +02:00
62c1cf74c2 [DEBUG] remove some log not needed anymore (use to find the ARM bug) 2017-06-07 01:02:52 +02:00
e7d0f634b5 [DEBUG] missing functionnal 2017-06-07 00:25:25 +00:00
0bf98b19fb [DEBUG] start correct android RPC segfault ==> pointer alignement error 2017-06-07 00:24:06 +02:00
f15e8d450d [DEV] correct the Future::get that does not work anymore 2017-06-01 06:41:31 +02:00
826ac3c053 [DEV/DEBUG] action signal is working and might be working as generic signaling 2017-06-01 06:41:31 +02:00
4801cb8306 [DEV] better integration of test base and actions/signals 2017-06-01 06:41:31 +02:00
309c106962 [DEBUG] correct the bug of sending files on remotes server 2017-06-01 06:41:31 +02:00
cc7493c079 [DEV] continue thinking about signal and progression 2017-06-01 06:41:31 +02:00
7840f2231e [DEV] think at new interface event 2017-06-01 06:41:31 +02:00
4bfdd57093 [DEV] better callback api but error on a mutable and const elements ... 2017-05-31 07:37:51 +02:00
cdfcede4c9 [DEV] continue integration of actions 2017-05-29 00:42:41 +02:00
6ee0c7047e [DEV] add service and object action notification bases 2017-05-28 16:22:54 +02:00
e4ddecc0eb [DEV] build back 2017-05-26 23:27:31 +00:00
2073938bc5 [DEV] start dev of the future progress return 2017-05-03 11:50:48 +00:00
502f431d5f [DEV] add parse of the other title in the () date element 2017-05-03 11:50:25 +00:00
07aca1dcb6 [DEV] update the level of release log 2017-05-03 11:49:00 +00:00
6f2ec947ed [DEV] better management of he sha512 acquisition ==> faster and detect pb in release of remote object... 2017-05-01 22:27:51 +00:00
f5a1f4b463 [DEBUG] correct a gat answer type 2017-04-29 14:01:42 +00:00
da8896228a [DEV] try find android crash 2017-04-28 23:28:43 +02:00
68e91f2296 [DEV] better display 2017-04-28 21:10:53 +02:00
94c5a4acce [DEBUG] remove android warning 2017-04-28 21:08:21 +02:00
b25b660728 [DEBUG] not build 2017-04-28 21:59:12 +02:00
3ba5889541 [DEV] support multiple acces when download a file 2017-04-28 21:57:50 +02:00
958060692c [DEV] better interface for file sha512 2017-04-28 00:00:39 +00:00
6e0d0e2ffc [DEV] good load of metadata and better display, add fullscreen and back button 2017-04-27 22:35:49 +02:00
f99ffecc31 [DEBUG] correct error in sending data coruption 2017-04-27 22:08:12 +02:00
ebdf836ab1 [DEBUG] many correction of low level interface 2017-04-27 22:17:19 +02:00
a4f861886d [DEV] correct the init sequency 2017-04-26 23:42:21 +00:00
a58076f0f7 [DEV] try to optimize the view of metadata 2017-04-26 21:23:02 +02:00
256a2f22d9 [DEV] stupid bug 2017-04-25 23:28:43 +02:00
3fd99a2f5a [DEV] set work on android 2017-04-25 22:16:15 +02:00
2738f7d0e2 [DEV] try update the non socket interface 2017-04-25 21:47:45 +02:00
879cb30426 [DOC] update readme 2017-04-24 23:00:41 +00:00
bf346d2f26 [DEV] stupid patch for android ==> TODO: understand why 2017-04-24 22:32:49 +02:00
9913b58998 [DEV] better search of the group ==> single methode display list 2017-04-20 21:03:04 +02:00
713313bcdc [DEV] store file with more than the sha1 (add some human readable parameters) 2017-04-19 23:03:16 +02:00
2f45546540 [DEV] better interaction and display 2017-04-18 21:44:32 +02:00
b6af117397 [DEV] better dislay and view saison in files 2017-04-16 23:24:07 +02:00
9f72146bf2 [DEV] keep aspect ratio & add log in the stdout for router 2017-04-16 16:26:21 +02:00
88af61bc85 [DEBUG] correct cli-player and cli-video interface 2017-04-14 23:48:31 +02:00
4ad6f382dd [DEV] converge to use only object instead of single service API 2017-04-14 21:19:19 +02:00
723c092756 [DEV] corect print in test software in release 2017-04-14 00:11:41 +02:00
b4e84394e4 [DEBUG] correct extetion parsing 2017-04-14 00:06:35 +02:00
5cd91b9c2a [DEBUG] coorect build error 2017-04-14 00:04:06 +02:00
c2e96b5e74 [DEV] update systemd service 2017-04-14 00:01:46 +02:00
beeed946bf [DEV] add capability to change log 2017-04-14 00:00:32 +02:00
0ced25aed1 [DEV]play sound not so bad ... 2017-04-13 23:42:00 +02:00
6f75373855 [DEV/DEBUG] cli enterprete server name and correct the mpeg-ts mine type (not official) 2017-04-13 00:16:24 +02:00
cf93a425ba [DEV] add a simple line command to acces on video service 2017-04-11 23:56:16 +02:00
e3a2b86a55 [DEV] add default systemd interface 2017-04-11 23:49:45 +00:00
f4a41e57e9 [DEV] add a remote to stop or restart a personal server 2017-04-11 22:06:08 +02:00
746c8ceac4 [DEV] update seek and better display 2017-04-08 23:06:00 +02:00
7cc209a13e [DEV] add viewer of the download of the remote file 2017-03-27 21:16:52 +02:00
6091275c64 [DEV] add wait for service (2sec) and api to get list of service availlable 2017-03-26 23:16:21 +02:00
abb81cd61a [DEBUG] generation error and routeur running gateway path error 2017-03-22 21:08:15 +01:00
61022b00df [DEBUG] correct IDL generation 2017-03-06 22:12:23 +01:00
ec9f88fccb [DEV] set back display of the video ==> must do it better 2017-02-22 22:18:47 +01:00
2c85f1992b [DEV] add the capabilities to change the disconnection of gateway on the router 2017-02-21 21:46:51 +01:00
8a92ef772b [DEV] not work display player, but need to same on git 2017-02-15 21:04:13 +01:00
3b0a4cd27c [DEV] display film correctly not seek for now 2017-02-09 23:31:54 +01:00
27e0a4e603 [DEV] Continue integration for a better player video 2017-02-07 21:35:58 +01:00
fe927ac297 [DEV] Better API for future::andXXX 2017-02-07 21:35:22 +01:00
fe53d10b86 [DEV] start rework connection methode (GUI) 2017-02-04 10:47:06 +01:00
5f35b6e912 [DEV] better async but not work on GUI when request mark to redraw 2017-02-02 00:26:38 +01:00
95fdcfcc34 [DEV] try to have faster load of every element in the listView 2017-02-01 00:03:38 +01:00
557545b74a [DEV] play video from server ==> copy and play... (TODO: copy by part) 2017-01-30 00:24:02 +01:00
6792ab72c8 [DEV] add help in test client 2017-01-30 00:24:02 +01:00
58b9de3354 [DEBUG] correct the code generated, missing Future<XXX>::get() 2017-01-30 00:24:02 +01:00
a061c684df Change licence APACHE-2 to MPL-2 ==> force source redistribution and permit static link 2017-01-05 21:28:23 +01:00
84c9ca1cdc [DEV] continue integration of the media player with zeus 2017-01-04 22:53:46 +01:00
24e7c0efc8 [DEV] start the gateway when not started with the router (bad things wait 500 ms that the process is started) 2017-01-04 21:58:34 +01:00
1f7e9e79d3 [DEV] Try to launch gateway in a subprocess of router 2017-01-04 00:02:22 +01:00
58f880f244 [DEV] continue integration of player video 2017-01-03 22:31:44 +01:00
22c82ecc49 [DEV] correct launch in gateway of service and correct the test client API 2017-01-02 22:34:51 +01:00
4df96d11ce [DEV] try to add launcher in gateway 2017-01-01 17:47:45 +01:00
dd16edd4e8 [DEV] start dev of the remote player 2016-12-29 21:27:03 +01:00
ac206580d3 [DEV] start think at video interface 2016-12-28 15:34:05 +01:00
7f1883dbea [DEBUG] correct future time-out and remove remote object 2016-12-13 22:58:01 +01:00
4b961dbc84 [DEV] add support of metadata 2016-12-14 23:09:28 +01:00
325c740290 [DEV] continue integration of service-picture 2016-12-13 22:58:01 +01:00
3e8524feb2 [DEV] continue integration of picture 2016-12-12 22:42:03 +01:00
26843381d7 [DEV] add factory and tools in IDL and store list of file in the picture engine 2016-12-12 21:09:55 +01:00
559752a3b9 [DEV] add sha512 calculation and catche exception std::xxx when have an error on functioncall in RPC 2016-12-12 08:48:46 +01:00
d439fb5bc2 [DEV] remove remote object and transfer ownership ... 2016-12-12 08:48:33 +01:00
0efb75039b [DEV] continue better management of connection and add display of current object list 2016-12-08 22:13:16 +01:00
fe4ba85a05 [DEV/DEBUG] corect the interface of connection/deiconection 2016-12-08 21:38:28 +01:00
0619e613eb [DEBUG/DEV] Buffer to message naming is OK, correct disconnection and add router optionnal for the gateway 2016-12-08 00:16:40 +01:00
f1937e97d1 [DEV] rework source tree 2016-12-07 22:18:34 +01:00
07dcff3647 [DEV] firl transfer is OK 2016-12-07 11:36:07 +01:00
d13a239878 [DEV] nearly finish the send and get file 2016-12-06 21:14:11 +01:00
615486529d [DEV] nearly work, need to update the get and set parameter with the web interface 2016-12-05 22:17:47 +01:00
e49c34b260 [DEV] strt update file 2016-12-04 22:38:23 +01:00
aeb151e525 [DEV] add raw stream 2016-12-02 23:36:19 +01:00
9e2a9ed301 [DEV] add the basic File Object 2016-12-02 23:05:29 +01:00
697b2a743d [DEV] update to the new property methodologie 2016-12-02 22:36:06 +01:00
619604b6c5 [DEV] get the service and call it ... 2016-12-02 21:49:55 +01:00
db1affa89c [DEV) write code to return object and service in generique mode is done, runtime bug ... 2016-12-02 00:20:26 +01:00
aabcf5b9ce [DEV] nearly ready to send Object throw the network 2016-12-01 21:06:35 +01:00
53fc5a2506 [DEV] continue think about object methodes and attributes 2016-12-01 00:26:10 +01:00
584f56aa29 [DEV] get service and call element on it 2016-11-30 22:09:16 +01:00
b13a79fe5d [DEV] continue refactor PB with object return 2016-11-29 23:14:49 +01:00
fa38f8d637 [DEV] review entire model... 2016-11-29 21:39:39 +01:00
be919abb1e [DEV] change think of the interface to have the capabilities to have object/service/structure and provide it as a client 2016-11-29 00:33:31 +01:00
42e6f1da59 [DEV] send file is OF, not get 2016-11-28 21:29:45 +01:00
9f4872ba7b [DEV] Work is back but no transfer of files with IDL ==> need to add it ... 2016-11-28 21:28:26 +01:00
fac9c55b9e [DEV] continue integration to simplify user interface, but not work and does not parmit to have object and stream 2016-11-27 20:54:38 +01:00
1d0f1265eb [DEV] continue integration of user frendly use of API and multiple service start in launcher 2016-11-25 22:02:05 +01:00
5e1300867d [DEV] port all with IDL 2016-11-24 22:11:58 +01:00
a31212ce48 [DEV] base of machro generation 2016-11-24 21:56:24 +01:00
bca8a8f2bd [DEV] start test of generation from .zeus.idl 2016-11-24 01:00:58 +01:00
bd19e37031 [DEV] think about a basic IDL 2016-11-23 22:25:25 +01:00
8780e9fe45 [DEV] rename gateway front and back in gateway and router 2016-11-23 22:03:04 +01:00
7cef0f6b08 [DEV] luncher work well bun run only one service (Missing set of the user data in a specific path) 2016-11-23 21:38:34 +01:00
9b7cff391d try to create a launcher and a package group 2016-11-23 00:11:41 +01:00
940dc0458a [DEBUG] update picture service 2016-11-22 21:36:41 +01:00
5601fde3db [DEV] seem to work corectly 2016-11-22 21:19:00 +01:00
92a2f74062 [DEV] simplify the interface of a service 2016-11-22 00:20:18 +01:00
040eaf491f [DEV] update interface with a double gateway to permit to have a dockerisation of user service 2016-11-21 22:15:46 +01:00
07c58bc94f [DEBUG] correct the subfolder parsing 2016-11-20 14:27:22 +01:00
973a65660f [DEV] add video service (copy of picture) 2016-11-20 14:19:40 +01:00
ccc08d6bdc [DEV] rename service bases 2016-11-20 14:04:28 +01:00
7d471b0af5 [DEV] have next/previous/play/pause fully functionnal 2016-11-18 00:32:03 +01:00
0f2da05591 [DEV] separate decoder 2016-11-17 22:38:37 +01:00
7d24032c1d [DEBUG/DEV] correct planar audio and add seek interface 2016-11-17 21:50:56 +01:00
b6c7d5fc82 [DEBUG] find a bug in the planar interface of data ==> need to investigate 2016-11-17 00:21:45 +01:00
147cab19fe [DEV] have sound but not work corectly, playing cyclke is correct 2016-11-16 21:24:22 +01:00
d136aa51fb [DEV] set multithread decoding... 2016-11-15 23:51:33 +01:00
f0407db37f [DEV] video-player Start dev of the basic view of a simple file (not link with zeus now ... 2016-11-15 21:44:11 +01:00
42529814fa [DEV] update dev tag version 2016-10-28 06:51:05 +02:00
6f5032aef3 [RELEASE] new version 0.4.0 2016-10-28 06:50:55 +02:00
8bf0bfa9fb [DEBUG] Correct the MacOs port of size_t 2016-10-28 06:50:41 +02:00
67bf580102 [CI] update build 2016-10-25 21:56:55 +02:00
090c280e34 [DEV] remove dependency of unistd.h 2016-10-13 21:29:18 +02:00
c6a592592a [DEV] add an init needed for enet 2016-10-07 18:14:28 +02:00
7a0e0ab117 [DEV] Update new lutin 2.2.0 (no legacy support) 2016-10-04 23:41:29 +02:00
2e9f2cb20f [DEBUG] correct .hpp port + clean libC include 2016-10-02 23:49:48 +02:00
40853a9949 [DEV/API] change .h in .hpp 2016-10-02 17:01:22 +02:00
c8d8d55a59 [DEV] correct flags 2016-09-15 21:46:39 +02:00
64de814a8b [DOC] basic documantation 2016-09-14 21:18:13 +02:00
c5246906d7 [DEV] update dev tag version 2016-09-12 21:07:12 +02:00
e95b1b2681 [RELEASE] create release 0.3.0 2016-09-12 21:06:37 +02:00
bfa565dd6d [DEV] update to future lutin 2.0 2016-09-08 21:35:02 +02:00
f653b392df [DEV] update dev tag version 2016-08-30 22:54:57 +02:00
545166170f [RELEASE] create release 0.2.0 2016-08-30 22:54:08 +02:00
3287796807 [DEBUG] correct order of parameter in c++
gcc of rpi3 change it order of usnig parameter ==> I need to check it at the runtime now.
2016-08-03 21:31:06 +02:00
47c69df1e0 [DEV] add mine format for raw images and add setter of data after init 2016-07-26 23:21:27 +02:00
338fbfac4b [DEBUG] wrong order parameter 2016-07-25 23:26:30 +02:00
185c427453 [DEV] update the API of user interface 2016-07-25 22:29:00 +02:00
fa702798cb [DEBUG] build back gateway 2016-07-19 22:31:27 +02:00
8fb622717b [DEV] update sharedPtr 2016-07-19 21:43:58 +02:00
7a9ef2f4f7 [DEV] update new ememory::SharedPtr 2016-07-15 21:22:11 +02:00
39ee4f0343 [DEV] separate buffer class ==> done 2016-07-11 23:36:41 +02:00
df3d8ec285 [DEV] start think to cut buffer in multiple files 2016-07-06 21:57:05 +02:00
009448cac4 [DEBUG] protocol work again ... 2016-07-05 22:21:17 +02:00
8b21709a01 [DEV] correct rework of buffer interface to manage more type of messages ... 2016-07-04 21:13:20 +02:00
42ada729aa [DEBUG] correct the future multiple packet element and some other hiden error 2016-07-01 23:41:23 +02:00
bae883a836 [DEV] correct the template specializatin compilation with g++ 2016-07-01 15:01:40 +02:00
f76787a7d2 [DEV/DOC] add basic comment and some change (NOT WORK) 2016-06-24 23:24:42 +02:00
7ee8e2332c [DEV/DOC] clean documentation and code 2016-06-23 22:08:11 +02:00
19948e45f0 [DEBUG] correct sendig of data (now must generize the multiple send data 2016-06-22 23:35:10 +02:00
ae7d28552a [DEV] start send file data throw the service 2016-06-22 22:52:18 +02:00
7ce31359c9 [DEV] simplify protocol and add multiple packect base interface 2016-06-21 23:35:08 +02:00
c362381107 [DEV] finish chaneg in zeus and set interface with websocket 2016-06-20 23:07:25 +02:00
fcfffdd6b0 [DEV] rename the library jus -> zeus (I remove je json interface then the libname was wrong) 2016-06-20 22:20:11 +02:00
557eb8736b [DEV] complete remove of json to better manage of websocket 2016-06-16 21:15:53 +02:00
267 changed files with 26020 additions and 8742 deletions

93
.travis.yml Normal file
View File

@ -0,0 +1,93 @@
language: cpp
sudo: required
dist: trusty
branches:
only:
- master
- dev
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
- expect
- binutils-mingw-w64-x86-64 # 64bit MinGW
- gcc-mingw-w64-x86-64
- g++-mingw-w64-x86-64
matrix:
include:
- os: linux
env: CONF=release BUILDER=gcc TARGET=Linux TAG=Linux COMPILATOR_OPTION="--compilator-version=4.9" GCOV=--gcov
compiler: gcc
- os: linux
env: CONF=debug BUILDER=clang TARGET=Linux
compiler: clang
- os: linux
env: CONF=release BUILDER=gcc TARGET=Windows TAG=Mingw
compiler: x86_64-w64-mingw32-gcc
- os: linux
env: CONF=release BUILDER=gcc TARGET=Android TAG=Android DISABLE_PACKAGE=-p
compiler: gcc
- os: osx
env: CONF=release BUILDER=clang TARGET=MacOs TAG=MacOs
compiler: clang
- os: osx
env: CONF=release BUILDER=clang TARGET=IOs TAG=IOs
compiler: clang
install:
- cd ..
- pip install --user lutin
- if [ "$TAG" == "Android" ]; then
git clone --depth 1 --branch master https://github.com/HeeroYui/android-download-tool;
./android-download-tool/dl-android.sh;
fi
- git clone --depth 1 --branch master https://github.com/atria-soft/ci.git
- cd -
before_script:
- cd ..
- git clone https://github.com/atria-soft/elog.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/ememory.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/echrono.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/algue.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/etk.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/enet.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/eproperty.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/ejson.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/ethread.git -b $TRAVIS_BRANCH
- git clone https://github.com/generic-library/gtest-lutin.git --recursive
- git clone https://github.com/generic-library/z-lutin.git --recursive
- git clone https://github.com/generic-library/openssl-lutin.git --recursive
- pwd
- ls -l
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
export PATH=$PATH:/Users/travis/Library/Python/2.7/bin/;
fi
- ./ci/build_send.py --tag=$TAG --status=START;
script:
- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE zeus-*; STATUS=$?
- ./ci/build_send.py --tag=$TAG --status="$STATUS";
after_script:
- if [ "$GCOV" != "" ]; then
./ci/warning_send.py --find-path ./out/Linux_x86_64/$CONF/build/$BUILDER/zeus/;
fi
- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE zeus-test-client?run:--elog-level=3 | tee out_test.txt
- if [ "$GCOV" != "" ]; then
./ci/test_send.py --file=out_test.txt;
lutin -C -P -t $TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF -p zeus?gcov;
./ci/coverage_send.py --json=out/Linux_x86_64/$CONF/build/$BUILDER/zeus/zeus_coverage.json;
fi
notifications:
email:
- yui.heero@gmail.com

510
LICENSE
View File

@ -1,201 +1,373 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Mozilla Public License Version 2.0
==================================
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions
--------------
1. Definitions.
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
1.3. "Contribution"
means Covered Software of a particular Contributor.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
1.5. "Incompatible With Secondary Licenses"
means
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
1.6. "Executable Form"
means any form of the work other than Source Code Form.
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
1.8. "License"
means this document.
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
1.10. "Modifications"
means any of the following:
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(b) any new file in Source Code Form that contains any Covered
Software.
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
2. License Grants and Conditions
--------------------------------
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
2.1. Grants
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
2.2. Effective Date
END OF TERMS AND CONDITIONS
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
APPENDIX: How to apply the Apache License to your work.
2.3. Limitations on Grant Scope
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
Copyright {yyyy} {name of copyright owner}
(a) for any code that a Contributor has removed from Covered Software;
or
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
http://www.apache.org/licenses/LICENSE-2.0
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

View File

@ -1,22 +1,91 @@
jus
===
zeus
====
`jus` is a Json µ-service
`zeus` is a Zeus ewol µ-service
Instructions
============
TODO ...
messaging engine drived by data and message based on websocket api
License (APACHE v2.0)
Start basic service engine
==========================
Start The router interface:
```
lutin -cclang -mdebug zeus-package-base?build?run%zeus-router
```
You need for the current version create your user configuration file...
Add the file ```~/.local/share/zeus-router/router-database.json``` and edit it:
```
{
"users":[
{
"name":"User Name A",
"path":"/PATH/TO/The/User/PERSONAL/FOLDER_1/"
},{
"name":"USER_NAME B",
"path":"/PATH/TO/The/User/PERSONAL/FOLDER_2/"
}
]
}
```
You have now multiple choice:
* Single process start:
```
#Start a single gateWay with basic with no user service associated:
lutin -cclang -mdebug zeus-package-base?build?run%zeus-gateway:--user=userName~server.org
# start service is separated process: (the user service is needed all the time ...)
lutin -cclang -mdebug zeus-package-base?build?run%zeus-launch:--srv=user
lutin -cclang -mdebug zeus-package-base?build?run%zeus-launch:--srv=picture
lutin -cclang -mdebug zeus-package-base?build?run%zeus-launch:--srv=video
```
* Start your gateway with the service in a single process (faster: No inter-process messaging)
```
lutin -cclang -mdebug zeus-package-base?build?run%zeus-gateway:--user=userName~server.org:--srv=user:--srv=picture:--srv=video
```
Install and auto run:
=====================
Copyright jus Edouard DUPIN
Licensed under the Apache License, Version 2.0 (the "License");
copy systemd file ```tools/router/data/zeus-router.service``` in ```/usr/lib/systemd/system/zeus-router.service```
Jump in ```ROOT```
Force systemd toupdate his dataBase
systemctl daemon-reload
Start the service:
systemctl start zeus-router.service
Run some command tools:
=======================
Access to the video backend:
```
lutin -cclang -mdebug zeus-package-base?run%zeus-cli-video:--login=HeeroYui:--pass=plop:list
```
License (MPL v2.0)
=====================
Copyright zeus Edouard DUPIN
Licensed under the Mozilla Public License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
https://www.mozilla.org/MPL/2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,

1
authors.txt Normal file
View File

@ -0,0 +1 @@
MR Edouard DUPIN <yui.heero@gmail.com>

118
doc/build.md Normal file
View File

@ -0,0 +1,118 @@
Build lib & build sample {#zeus_build}
========================
@tableofcontents
Download: {#zeus_build_download}
=========
ege use some tools to manage source and build it:
need google repo: {#zeus_build_download_repo}
-----------------
see: http://source.android.com/source/downloading.html#installing-repo
On all platform:
```{.sh}
mkdir ~/.bin
PATH=~/.bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
chmod a+x ~/.bin/repo
```
On ubuntu
```{.sh}
sudo apt-get install repo
```
On archlinux
```{.sh}
sudo pacman -S repo
```
lutin (build-system): {#zeus_build_download_lutin}
---------------------
```{.sh}
pip install lutin --user
# optionnal dependency of lutin (manage image changing size for application release)
pip install pillow --user
```
dependency: {#zeus_build_download_dependency}
-----------
```{.sh}
mkdir -p WORKING_DIRECTORY/framework
cd WORKING_DIRECTORY/framework
repo init -u git://github.com/atria-soft/manifest.git
repo sync -j8
cd ../..
```
sources: {#zeus_build_download_sources}
--------
They are already download in the repo manifest in:
```{.sh}
cd WORKING_DIRECTORY/framework/atria-soft/zeus
```
Build: {#zeus_build_build}
======
you must stay in zour working directory...
```{.sh}
cd WORKING_DIRECTORY
```
library: {#zeus_build_build_library}
--------
```{.sh}
lutin -mdebug zeus
```
Sample: {#zeus_build_build_sample}
-------
```{.sh}
# generic gateway (with acces control)
lutin -mdebug zeus-gateway
# control acces with the user property
lutin -mdebug zeus-system-user
# simple picture service (example)
lutin -mdebug zeus-picture
# test service
lutin -mdebug zeus-test-service1
# test client
lutin -mdebug zeus-test-client
```
A fast way:
```{.sh}
lutin -mdebug zeus-*
```
Run sample: {#zeus_build_run_sample}
===========
you must copy a configuration file:
```{.sh}
mkdir -p ~/.local/share/zeus-system-user/
cp framework/atria-soft/zeus/test1#atria-soft.com.json ~/.local/share/zeus-system-user/test1~atria-soft.com.json
```
in distinct bash:
```{.sh}
lutin -mdebug zeus-gateway?run
lutin -mdebug zeus-system-user?run
lutin -mdebug zeus-picture?run
lutin -mdebug zeus-test-service1?run
lutin -mdebug zeus-test-client?run
```

65
doc/mainpage.md Normal file
View File

@ -0,0 +1,65 @@
ZEUS library {#mainpage}
=============
@tableofcontents
What is ZEUS: {#zeus_mainpage_what}
==============
ZEUS, or Zeus Ewol micro-service. It is a developement to create c++ microservice compatible with the web generic ineterface.
My objective are:
- create a facebook, tweeter, snapsher heberged on my own server and not dependent on the "big enterprise" that I do not know what they do on my "PERSONAL DATA"
- Have a real sharing on personal picture and video with the circle I want
- Create a separate Front end that can acces on an other service that is own on an other server ==> generic API ==> 1 Front end
- shared My phone and personal data with all my friend and family ==> ne need to update the information, this is automatic...
- ...
I love Free Internat that I can be free on big compagny !!!!
What it does: {#zeus_mainpage_what_it_does}
-------------
This is a prototype (need more developpers)
TBD ...
ZEUS is dependent of the STL (compatible with MacOs stl (CXX))
What languages are supported? {#zeus_mainpage_language}
=============================
ZEUS is written in C++.
Are there any licensing restrictions? {#zeus_mainpage_license_restriction}
=====================================
ZEUS is **FREE software** and _all sub-library are FREE and staticly linkable !!!_
License (MPL v2.0) {#zeus_mainpage_license}
==================
Copyright ZEUS Edouard DUPIN
Licensed under the Mozilla Public License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
<https://www.mozilla.org/MPL/2.0>
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Other pages {#zeus_mainpage_sub_page}
===========
- @ref zeus_build
- [**ewol coding style**](http://atria-soft.github.io/ewol/ewol_coding_style.html)

34
doxy_zeus.py Normal file
View File

@ -0,0 +1,34 @@
#!/usr/bin/python
import os
import doxy.module as module
import doxy.debug as debug
import doxy.tools as tools
def create(target, module_name):
my_module = module.Module(__file__, module_name)
my_module.set_version("version.txt")
my_module.set_title("zeus: Zeus ewol micro-service interface")
my_module.set_website("http://atria-soft.github.io/" + module_name)
my_module.set_website_sources("http://github.com/atria-soft/" + module_name)
my_module.add_path([
module_name,
"doc"
])
my_module.add_depend([
'etk',
'enet',
'ememory',
'eproperty'
])
my_module.add_exclude_symbols([
'*operator<<*',
])
my_module.add_exclude_file([
'debug.hpp',
])
my_module.add_file_patterns([
'*.hpp',
'*.md',
])
return my_module

View File

@ -1,147 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/AbstractFunction.h>
#include <jus/debug.h>
#include <etk/os/FSNode.h>
jus::Buffer jus::createBinaryCall(uint64_t _transactionId, const std::string& _functionName, const jus::Buffer& _params) {
jus::Buffer callElem = createBinaryBaseCall(_transactionId, _functionName);
//callElem.add("param", _params);
return callElem;
}
jus::Buffer jus::createBinaryBaseCall(uint64_t _transactionId, const std::string& _functionName, const uint32_t& _serviceId) {
jus::Buffer obj;
obj.setServiceId(_serviceId);
obj.setCall(_functionName);
obj.setTransactionId(_transactionId);
return obj;
}
void jus::createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction, int32_t _paramId, jus::Buffer& _obj) {
// Finish recursive parse ...
}
enum jus::AbstractFunction::type jus::AbstractFunction::getType() const {
return m_type;
}
void jus::AbstractFunction::setType(enum jus::AbstractFunction::type _type) {
m_type = _type;
}
const std::string& jus::AbstractFunction::getName() const {
return m_name;
}
const std::string& jus::AbstractFunction::getDescription() const {
return m_description;
}
void jus::AbstractFunction::setDescription(const std::string& _desc) {
m_description = _desc;
}
void jus::AbstractFunction::setParam(int32_t _idParam, const std::string& _name, const std::string& _desc) {
JUS_TODO("not implemented set param ... '" << _name << "'");
}
void jus::AbstractFunction::addParam(const std::string& _name, const std::string& _desc) {
m_paramsDescription.push_back(std::make_pair(_name, _desc));
}
void jus::AbstractFunction::setReturn(const std::string& _desc) {
m_returnDescription = _desc;
}
std::string jus::AbstractFunction::getPrototypeFull() const {
std::string out = getPrototypeReturn();
out += " ";
out += m_name;
out += "(";
std::vector<std::string> tmp = getPrototypeParam();
for (size_t iii=0; iii<tmp.size(); ++iii) {
if (iii != 0) {
out += ", ";
}
out += tmp[iii];
if (iii < m_paramsDescription.size()) {
out += " " + m_paramsDescription[iii].first;
}
}
out += ");";
return out;
}
jus::AbstractFunction::AbstractFunction(const std::string& _name,
const std::string& _desc):
m_type(jus::AbstractFunction::type::unknow),
m_name(_name),
m_description(_desc) {
}
bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const std::string& _params) {
if (createType<bool>() == _type) {
return _params == "bool";
}
if ( createType<int64_t>() == _type
|| createType<int32_t>() == _type
|| createType<int16_t>() == _type
|| createType<int8_t>() == _type
|| createType<uint64_t>() == _type
|| createType<uint32_t>() == _type
|| createType<uint16_t>() == _type
|| createType<uint8_t>() == _type
|| createType<float>() == _type
|| createType<double>() == _type) {
return _params == "int8"
|| _params == "int16"
|| _params == "int32"
|| _params == "int64"
|| _params == "uint8"
|| _params == "uint16"
|| _params == "uint32"
|| _params == "uint64"
|| _params == "float"
|| _params == "double";
}
if (createType<std::vector<std::string>>() == _type) {
return _params == "vector:string";
}
if ( createType<std::vector<bool>>() == _type
|| createType<std::vector<int64_t>>() == _type
|| createType<std::vector<int32_t>>() == _type
|| createType<std::vector<int16_t>>() == _type
|| createType<std::vector<int8_t>>() == _type
|| createType<std::vector<uint64_t>>() == _type
|| createType<std::vector<uint32_t>>() == _type
|| createType<std::vector<uint16_t>>() == _type
|| createType<std::vector<uint8_t>>() == _type
|| createType<std::vector<float>>() == _type
|| createType<std::vector<double>>() == _type) {
return _params == "vector:int8"
|| _params == "vector:int16"
|| _params == "vector:int32"
|| _params == "vector:int64"
|| _params == "vector:uint8"
|| _params == "vector:uint16"
|| _params == "vector:uint32"
|| _params == "vector:uint64"
|| _params == "vector:float"
|| _params == "vector:double"
|| _params == "vector:empty";
}
if (createType<jus::File>() == _type) {
return _params == "file";
}
if (createType<std::string>() == _type) {
return _params == "string";
}
return false;
}

View File

@ -1,111 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <eproperty/Value.h>
#include <jus/debug.h>
#include <jus/ParamType.h>
#include <jus/File.h>
#include <jus/Buffer.h>
namespace jus {
class TcpString;
// define basic async call element ...
using ActionAsyncClient = std::function<bool(TcpString* _interface, const uint32_t& _serviceId, uint64_t _transactionId, uint64_t _part)>;
}
namespace jus {
class AbstractFunction {
public:
enum class type {
unknow,
global,
local,
service,
object,
};
protected:
enum type m_type;
public:
enum type getType() const;
void setType(enum type _type);
protected:
std::string m_name;
public:
const std::string& getName() const;
protected:
std::string m_description;
public:
const std::string& getDescription() const;
void setDescription(const std::string& _desc);
protected:
std::vector<std::pair<std::string, std::string>> m_paramsDescription;
public:
void setParam(int32_t _idParam, const std::string& _name, const std::string& _desc);
void addParam(const std::string& _name, const std::string& _desc);
protected:
std::string m_returnDescription;
public:
void setReturn(const std::string& _desc);
protected:
AbstractFunction(const std::string& _name, const std::string& _desc="");
public:
virtual ~AbstractFunction() {};
public:
bool checkCompatibility(const ParamType& _type, const std::string& _params);
public:
std::string getPrototypeFull() const;
virtual std::string getPrototype() const = 0;
virtual std::string getPrototypeReturn() const = 0;
virtual std::vector<std::string> getPrototypeParam() const = 0;
virtual void execute(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, jus::Buffer& _params, void* _class=nullptr) = 0;
};
jus::Buffer createBinaryBaseCall(uint64_t _transactionId, const std::string& _functionName, const uint32_t& _serviceId=0);
void createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction,
int32_t _paramId,
jus::Buffer& _obj);
template<class JUS_TYPE, class... _ARGS>
void createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction,
int32_t _paramId,
jus::Buffer& _obj,
const JUS_TYPE& _param,
_ARGS&&... _args) {
_obj.addParameter<JUS_TYPE>(/*_asyncAction, _paramId,*/ _param);
_paramId++;
createBinaryParam(_asyncAction, _paramId, _obj, std::forward<_ARGS>(_args)...);
}
// convert const char in std::string ...
template<class... _ARGS>
void createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction,
int32_t _paramId,
jus::Buffer& _obj,
const char* _param,
_ARGS&&... _args) {
createBinaryParam(_asyncAction, _paramId, _obj, std::string(_param), std::forward<_ARGS>(_args)...);
}
template<class... _ARGS>
jus::Buffer createBinaryCall(std::vector<ActionAsyncClient>& _asyncAction, uint64_t _transactionId, const std::string& _functionName, _ARGS&&... _args) {
jus::Buffer callElem = createBinaryBaseCall(_transactionId, _functionName);
createBinaryParam(_asyncAction, 0, callElem, std::forward<_ARGS>(_args)...);
return callElem;
}
template<class... _ARGS>
jus::Buffer createBinaryCallService(std::vector<ActionAsyncClient>& _asyncAction, uint64_t _transactionId, const uint32_t& _serviceName, const std::string& _functionName, _ARGS&&... _args) {
jus::Buffer callElem = createBinaryBaseCall(_transactionId, _functionName, _serviceName);
createBinaryParam(_asyncAction, 0, callElem, std::forward<_ARGS>(_args)...);
return callElem;
}
jus::Buffer createBinaryCall(uint64_t _transactionId, const std::string& _functionName, const jus::Buffer& _params);
}
#include <jus/TcpString.h>

View File

@ -1,243 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h>
#include <jus/debug.h>
#include <jus/AbstractFunction.h>
#include <jus/mineType.h>
#include <etk/os/FSNode.h>
namespace jus {
template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES>
void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
std::vector<ActionAsyncClient> asyncAction;
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
JUS_RETURN ret = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam++)...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
JUS_RETURN ret = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else
#error Must be implemented ...
JUS_RETURN ret;
return;
#endif
if (asyncAction.size() != 0) {
JUS_ERROR("Missing send async messages");
}
_interfaceClient->addAsync([=](TcpString* _interface) {
_interface->answerValue(_transactionId, ret, _clientId);
return true;
});
}
class SendFile {
private:
jus::FileServer m_data;
uint64_t m_transactionId;
uint64_t m_clientId;
uint32_t m_partId;
etk::FSNode m_node;
uint64_t m_size;
public:
SendFile(jus::FileServer _data,
uint64_t _transactionId,
uint64_t _clientId) :
m_data(_data),
m_transactionId(_transactionId),
m_clientId(_clientId),
m_partId(0),
m_node(_data.getFileName()),
m_size(0) {
}
~SendFile() {
//m_node.fileClose();
}
bool operator() (TcpString* _interface) {
jus::Buffer answer;
answer.setTransactionId(m_transactionId);
answer.setClientId(m_clientId);
answer.setPartId(m_partId);
answer.setPartFinish(false);
if (m_partId == 0) {
m_node.fileOpenRead();
std::string extention = std::string(m_data.getFileName().begin()+m_data.getFileName().size() -3, m_data.getFileName().end());
JUS_WARNING("send file: '" << m_data.getFileName() << "' with extention: '" << extention << "'");
m_size = m_node.fileSize();
jus::File tmpFile(jus::getMineType(extention), std::vector<uint8_t>(), m_size);
answer.addAnswer(tmpFile);
_interface->writeBinary(answer);
m_partId++;
return false;
}
int32_t tmpSize = 1024;
if (m_size < 1024) {
tmpSize = m_size;
}
uint8_t tmpData[1024];
m_node.fileRead(tmpData, 1, tmpSize);
answer.addData(tmpData, tmpSize);
m_size -= tmpSize;
if (m_size <= 0) {
answer.setPartFinish(true);
m_node.fileClose();
}
_interface->writeBinary(answer);;
m_partId++;
if (m_size <= 0) {
return true;
}
return false;
}
};
template <class JUS_CLASS_TYPE, class... JUS_TYPES>
void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam++)...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else
#error Must be implemented ...
jus::FileServer tmpElem;
return;
#endif
_interfaceClient->addAsync(SendFile(tmpElem, _transactionId, _clientId));
}
template <class JUS_CLASS_TYPE, class... JUS_TYPES>
void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
(*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam++)...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
(*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else
#error Must be implemented ...
return;
#endif
_interfaceClient->addAsync([=](TcpString* _interface) {
_interface->answerVoid(_transactionId, _clientId);
return true;
});
}
template <class JUS_RETURN, class JUS_CLASS_TYPE, class... JUS_TYPES>
class AbstractFunctionTypeClass: public jus::AbstractFunction {
protected:
static const ParamType m_returnType;
static const ParamType m_paramType[sizeof...(JUS_TYPES)];
public:
using functionType = JUS_RETURN (JUS_CLASS_TYPE::*)(JUS_TYPES...);
functionType m_function;
AbstractFunctionTypeClass(const std::string& _name, const std::string& _desc, functionType _fptr):
AbstractFunction(_name, _desc),
m_function(_fptr) {
}
std::string getPrototype() const override {
std::string ret;
ret += m_returnType.getName();
ret += " ";
ret += m_name;
ret += "(";
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (iii != 0) {
ret += ", ";
}
ret += m_paramType[iii].getName();
}
ret += ");";
return ret;
}
std::string getPrototypeReturn() const override {
return m_returnType.getName();
}
std::vector<std::string> getPrototypeParam() const override {
std::vector<std::string> out;
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
out.push_back(m_paramType[iii].getName());
}
return out;
}
void execute(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
jus::Buffer& _obj,
void* _class) override {
JUS_CLASS_TYPE* tmpClass = nullptr;
if (_class != nullptr) {
tmpClass = (JUS_CLASS_TYPE*)_class;
}
// check parameter number
if (_obj.getNumberParameter() != sizeof...(JUS_TYPES)) {
JUS_ERROR("Wrong number of Parameters ...");
std::string help = "request ";
help += etk::to_string(_obj.getNumberParameter());
help += " parameters and need ";
help += etk::to_string(sizeof...(JUS_TYPES));
help += " parameters. prototype function:";
help += getPrototype();
_interfaceClient->answerError(_transactionId,
"WRONG-PARAMETER-NUMBER",
help,
_clientId);
return;
}
// check parameter compatibility
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (checkCompatibility(m_paramType[iii], _obj.getParameterType(iii)) == false) {
_interfaceClient->answerError(_transactionId,
"WRONG-PARAMETER-TYPE",
std::string("Parameter id ") + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'",
_clientId);
return;
}
}
// execute cmd:
jus::executeClassCall(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _obj);
}
};
template <class JUS_RETURN, class JUS_CLASS_TYPE, class... JUS_TYPES>
const ParamType AbstractFunctionTypeClass<JUS_RETURN, JUS_CLASS_TYPE, JUS_TYPES...>::m_returnType = createType<JUS_RETURN>();
template <class JUS_RETURN, class JUS_CLASS_TYPE, class... JUS_TYPES>
const ParamType AbstractFunctionTypeClass<JUS_RETURN, JUS_CLASS_TYPE, JUS_TYPES...>::m_paramType[sizeof...(JUS_TYPES)] = {createType<JUS_TYPES>()...};
template <typename JUS_RETURN, class JUS_CLASS_TYPE, typename... JUS_TYPES>
AbstractFunction* createAbstractFunctionClass(const std::string& _name, const std::string& _desc, JUS_RETURN (JUS_CLASS_TYPE::*_fffp)(JUS_TYPES...)) {
return new AbstractFunctionTypeClass<JUS_RETURN, JUS_CLASS_TYPE, JUS_TYPES...>(_name, _desc, _fffp);
}
}

View File

@ -1,141 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h>
#include <jus/debug.h>
#include <jus/AbstractFunction.h>
namespace jus {
template <class JUS_RETURN, class... JUS_TYPES>
void executeCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_RETURN (*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
JUS_RETURN ret = _func(_obj.getParameter<JUS_TYPES>(idParam++)...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
JUS_RETURN ret = _func(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else
#error Must be implemented ...
#endif
_interfaceClient->addAsync([=](TcpString* _interface) {
_interface->answerValue(_transactionId, ret, _clientId);
return true;
});
}
template <class... JUS_TYPES>
void executeCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
void (*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
_func(_obj.getParameter<JUS_TYPES>(idParam++)...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
_func(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else
#error Must be implemented ...
#endif
_interfaceClient->addAsync([=](TcpString* _interface) {
_interface->answerVoid(_transactionId, _clientId);
return true;
});
}
template <class JUS_RETURN, class... JUS_TYPES>
class AbstractFunctionTypeDirect: public jus::AbstractFunction {
protected:
static const ParamType m_returnType;
static const ParamType m_paramType[sizeof...(JUS_TYPES)];
public:
using functionType = JUS_RETURN (*)(JUS_TYPES...);
functionType m_function;
AbstractFunctionTypeDirect(const std::string& _name, const std::string& _desc, functionType _fptr):
AbstractFunction(_name, _desc),
m_function(_fptr) {
}
std::string getPrototype() const override {
std::string ret;
ret += m_returnType.getName();
ret += " ";
ret += m_name;
ret += "(";
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (iii != 0) {
ret += ", ";
}
ret += m_paramType[iii].getName();
}
ret += ");";
return ret;
}
std::string getPrototypeReturn() const override {
return m_returnType.getName();
}
std::vector<std::string> getPrototypeParam() const override {
std::vector<std::string> out;
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
out.push_back(m_paramType[iii].getName());
}
return out;
}
void execute(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
jus::Buffer& _obj,
void* _class) override {
// check parameter number
if (_obj.getNumberParameter() != sizeof...(JUS_TYPES)) {
std::string help = "request ";
help += etk::to_string(_obj.getNumberParameter());
help += " parameters and need ";
help += etk::to_string(sizeof...(JUS_TYPES));
help += " parameters. prototype function:";
help += getPrototype();
_interfaceClient->answerError(_transactionId,
"WRONG-PARAMETER-NUMBER",
help,
_clientId);
return;
}
// check parameter compatibility
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (checkCompatibility(m_paramType[iii], _obj.getParameterType(iii)) == false) {
_interfaceClient->answerError(_transactionId,
"WRONG-PARAMETER-TYPE",
std::string("Parameter id ") + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'",
_clientId);
return;
}
}
// execute cmd:
jus::executeCall(_interfaceClient, _transactionId, _clientId, m_function, _obj);
}
};
template <class JUS_RETURN, class... JUS_TYPES>
const ParamType AbstractFunctionTypeDirect<JUS_RETURN, JUS_TYPES...>::m_returnType = createType<JUS_RETURN>();
template <class JUS_RETURN, class... JUS_TYPES>
const ParamType AbstractFunctionTypeDirect<JUS_RETURN, JUS_TYPES...>::m_paramType[sizeof...(JUS_TYPES)] = {createType<JUS_TYPES>()...};
template <typename JUS_RETURN, typename... JUS_TYPES>
AbstractFunction* createAbstractFunctionDirect(const std::string& _name, const std::string& _desc, JUS_RETURN (*_fffp)(JUS_TYPES...)) {
return new AbstractFunctionTypeDirect<JUS_RETURN, JUS_TYPES...>(_name, _desc, _fffp);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,205 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/types.h>
#include <ejson/ejson.h>
namespace jus {
//U32 message lenght
#pragma pack(push,1)
struct headerBin {
uint32_t lenght;
uint16_t versionProtocol; // protocol Version (might be 1)
uint32_t transactionID;
uint32_t clientID; // same as sevice ID
int16_t partID; // if < 0 the partId ifs the last (start at 0 if multiple or 0x8000 if single message)
uint16_t typeMessage; //TypeMessgae (1:call, 2:Answer, 4:event)
uint16_t numberOfParameter; //TypeMessgae (1:call, 2:Answer, 4:event)
};
#pragma pack(pop)
/*
// not needed ==> can be deduced with parameter number ... U16 Offset String call Name (start of the buffer) end with \0
======================
== call
======================
U16 param count
U16[param count] parameters offset (first offset is the "callName" and limit size of the number of parameter
CALL Name (funtion name)
[param 1]
[param 2]
[param 3]
[param 4]
======================
== Answer
======================
U16 param count = 3
U16[param count]
[param 1] (return value)
[param 2] (error value)
[param 3] (error help)
[error] (constituated with 2 strings (error type and comment)
======================
== event
======================
U16[param count] parameters offset (first offset is the "callName" and limit size of the number of parameter
event Name
[param 1]
[param 2]
[param 3]
[param 4]
---------------------------
parameter and return value is contituated like :
TYPE,DATAs....(in raw)
Type is write in ascii in the list end with '\0':
- void
- bool
- float
- double
- int64
- int32
- int16
- int8
- uint64
- uint32
- uint16
- uint8
- string
- vector:bool
- vector:float
- vector:double
- vector:int64
- vector:int32
- vector:int16
- vector:int8
- vector:uint64
- vector:uint32
- vector:uint16
- vector:uint8
- vector:string
- obj:file
*/
class Buffer {
private:
headerBin m_header;
std::vector<uint16_t> m_paramOffset;
std::vector<uint8_t> m_data;
public:
const uint8_t* getHeader() const {
return reinterpret_cast<const uint8_t*>(&m_header);
}
uint32_t getHeaderSize() const {
return sizeof(headerBin);
}
const uint8_t* getParam() const {
return reinterpret_cast<const uint8_t*>(&m_paramOffset[0]);
}
uint32_t getParamSize() const {
return m_paramOffset.size() * 2;
}
const uint8_t* getData() const {
return &m_data[0];
}
uint32_t getDataSize() const {
return m_data.size();
}
private:
void internalComposeWith(const uint8_t* _buffer, uint32_t _lenght);
public:
Buffer();
void composeWith(const std::vector<uint8_t>& _buffer);
void composeWith(const std::string& _buffer);
std::string generateHumanString();
void clear();
uint16_t getProtocalVersion() const;
void setProtocolVersion(uint16_t _value);
uint32_t getTransactionId() const;
void setTransactionId(uint32_t _value);
uint32_t getClientId() const;// this is the same as serviceId
void setClientId(uint32_t _value);
uint32_t getServiceId() const {
return getClientId();
}
void setServiceId(uint32_t _value) {
setClientId(_value);
}
// note limited 15 bits
uint16_t getPartId() const;
void setPartId(uint16_t _value);
bool getPartFinish() const;
void setPartFinish(bool _value);
enum class typeMessage {
call = 0x0001,
answer = 0x0002,
event = 0x0004,
data = 0x0008,
};
enum typeMessage getType() const;
void setType(enum typeMessage _value);
// ===============================================
// == Section call
// ===============================================
private:
template<class JUS_TYPE_DATA>
JUS_TYPE_DATA internalGetParameter(int32_t _id) const;
std::string internalGetParameterType(int32_t _id) const;
const uint8_t* internalGetParameterPointer(int32_t _id) const;
uint32_t internalGetParameterSize(int32_t _id) const;
public:
std::string getCall() const;
void setCall(std::string _value);
uint16_t getNumberParameter() const;
std::string getParameterType(int32_t _id) const;
const uint8_t* getParameterPointer(int32_t _id) const;
uint32_t getParameterSize(int32_t _id) const;
private:
// add parameter for transcription of json element
void addParameter(ejson::Value _value);
public:
template<class JUS_TYPE_DATA>
void addParameter(const JUS_TYPE_DATA& _value);
void addParameterEmptyVector();
void addParameter();
template<class JUS_TYPE_DATA>
JUS_TYPE_DATA getParameter(int32_t _id) const {
return internalGetParameter<JUS_TYPE_DATA>(_id+1);
}
// ===============================================
// == Section Answer
// ===============================================
public:
template<class JUS_TYPE_DATA>
void addAnswer(const JUS_TYPE_DATA& _value) {
addParameter(_value);
}
// TODO : Do it better check error ... ==> can be good ...
template<class JUS_TYPE_DATA>
JUS_TYPE_DATA getAnswer() const {
return internalGetParameter<JUS_TYPE_DATA>(0);
}
void addError(const std::string& _value, const std::string& _comment);
bool hasError();
std::string getError();
std::string getErrorHelp();
public:
//multiple section of data (part ...)
void addData(void* _data, uint32_t _size);
void prepare();
ejson::Object toJson() const;
void fromJson(const ejson::Object& _data);
};
std::ostream& operator <<(std::ostream& _os, enum jus::Buffer::typeMessage _value);
template<class JUS_TYPE>
ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size);
}

View File

@ -1,77 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <enet/TcpClient.h>
#include <jus/Client.h>
#include <jus/debug.h>
#include <unistd.h>
jus::Client::Client() :
propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Client::onPropertyChangeIp),
propertyPort(this, "port", 1983, "Port to connect server", &jus::Client::onPropertyChangePort) {
}
jus::Client::~Client() {
}
void jus::Client::onClientData(jus::Buffer& _value) {
JUS_ERROR("Get Data On the Communication interface that is not understand ... : " << _value.generateHumanString());
}
jus::ServiceRemote jus::Client::getService(const std::string& _name) {
return jus::ServiceRemote(m_interfaceClient, _name);
}
void jus::Client::onPropertyChangeIp() {
disconnect();
}
void jus::Client::onPropertyChangePort(){
disconnect();
}
bool jus::Client::connect(const std::string& _remoteUserToConnect){
JUS_DEBUG("connect [START]");
disconnect();
enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort));
m_interfaceClient = std::make_shared<jus::TcpString>();
if (m_interfaceClient == nullptr) {
JUS_ERROR("Allocate connection error");
return false;
}
m_interfaceClient->connect(this, &jus::Client::onClientData);
m_interfaceClient->setInterface(std::move(connection));
m_interfaceClient->connect();
JUS_WARNING("Request connect user " << _remoteUserToConnect);
jus::Future<bool> ret = call("connectToUser", _remoteUserToConnect, "jus-client");
ret.wait();
if (ret.hasError() == true) {
JUS_WARNING("Can not connect to user named: '" << _remoteUserToConnect << "' ==> return error");
return false;
}
if (ret.get() == true) {
JUS_WARNING(" ==> accepted connection");
} else {
JUS_WARNING(" ==> Refuse connection");
}
return ret.get();
}
void jus::Client::disconnect() {
JUS_DEBUG("disconnect [START]");
if (m_interfaceClient != nullptr) {
m_interfaceClient->disconnect();
m_interfaceClient.reset();
} else {
JUS_VERBOSE("Nothing to disconnect ...");
}
JUS_DEBUG("disconnect [STOP]");
}

View File

@ -1,82 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h>
#include <jus/debug.h>
#include <chrono>
#include <unistd.h>
#include <jus/Future.h>
#include <jus/connectionMode.h>
#include <jus/ServiceRemote.h>
namespace jus {
class Client : public eproperty::Interface {
friend class ServiceRemote;
public:
eproperty::Value<std::string> propertyIp;
eproperty::Value<uint16_t> propertyPort;
private:
ememory::SharedPtr<jus::TcpString> m_interfaceClient;
public:
/**
* @brief Create a client on a specific user in a client mode with the tocken associated
* @param[in] _address Address of the user: "ABCD.efgh#atria-soft.com:1993"
* @param[in]
* @param[in]
*/
//Client(const std::string& _address, const std::string& _clientName, const std::string& _clientTocken);
/**
* @brief Create a client on a specific user in a user mode (connect to your personnal account)
* @param[in] _address Address of the user: "ABCD.efgh#atria-soft.com:1993"
* @param[in] _userPassword Password of the user
*/
//Client(const std::string& _address, const std::string& _userPassword);
/**
* @brief Create a client on a specific user in an ANONIMOUS way
* @param[in] _address Address of the user: "ABCD.efgh#atria-soft.com:1993"
*/
//Client(const std::string& _address);
Client();
virtual ~Client();
bool connect(const std::string& _remoteUserToConnect);
void disconnect();
public:
jus::ServiceRemote getService(const std::string& _serviceName);
// Connect that is not us
//bool identify("clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968");
// Connect to ourself:
//client1.authentificate("coucou");
private:
void onClientData(jus::Buffer& _value);
public:
template<class... _ARGS>
jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) {
if (m_interfaceClient == nullptr) {
jus::Buffer ret;
ret.addError("NULLPTR", "call " + _functionName + " with no interface open");
return jus::FutureBase(0, true, ret);
}
return m_interfaceClient->call(_functionName, _args...);
}
template<class... _ARGS>
jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
if (m_interfaceClient == nullptr) {
jus::Buffer ret;
ret.addError("NULLPTR", "call " + _functionName + " with no interface open");
return jus::FutureBase(0, true, ret, _callback);
}
return m_interfaceClient->callAction(_functionName, _args..., _callback);
}
private:
void onPropertyChangeIp();
void onPropertyChangePort();
};
}

View File

@ -1,62 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/File.h>
#include <jus/debug.h>
#include <etk/types.h>
#include <etk/stdTools.h>
#include <jus/mineType.h>
#include <etk/os/FSNode.h>
jus::File::File() {
}
jus::File::File(const std::string& _filename) {
m_data = etk::FSNodeReadAllDataType<uint8_t>(_filename);
std::string extention = std::string(_filename.begin()+_filename.size() -3, _filename.end());
JUS_WARNING("send file: '" << _filename << "' with extention: '" << extention << "'");
m_mineType = jus::getMineType(extention);
}
void jus::File::storeIn(const std::string& _filename) const {
etk::FSNodeWriteAllDataType(_filename, m_data);
}
jus::File::File(const std::string& _mineType, std::vector<uint8_t> _data, int32_t _fileSize):
m_mineType(_mineType),
m_data(_data) {
if (_fileSize < 0){
m_fileSize = m_data.size();
} else {
m_fileSize = _fileSize;
}
}
void jus::File::setData(uint64_t _offset, const std::vector<uint8_t>& _data) {
// TODO : Check size/offset before set
memcpy(&m_data[_offset], &_data[0], _data.size());
}
jus::FileServer::FileServer() {
}
jus::FileServer::FileServer(const std::string& _filename) :
m_name(_filename) {
}
namespace etk {
template<>
std::string to_string<jus::FileServer>(jus::FileServer const& _obj) {
return "";
}
}

View File

@ -1,45 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/types.h>
namespace jus {
class File {
private:
std::string m_mineType;
int32_t m_fileSize;
std::vector<uint8_t> m_data;
public:
File();
File(const std::string& _filename);
File(const std::string& _mineType, std::vector<uint8_t> _data, int32_t _fileSize = -1);
void storeIn(const std::string& _filename) const;
const std::string& getMineType() const {
return m_mineType;
}
void setMineType(const std::string& _type) {
m_mineType = _type;
}
void preSetDataSize(uint64_t _size) {
m_data.resize(_size, 0);
}
const std::vector<uint8_t>& getData() const {
return m_data;
}
void setData(uint64_t _offset, const std::vector<uint8_t>& _data);
};
class FileServer {
private:
std::string m_name;
public:
FileServer();
FileServer(const std::string& _filename);
const std::string& getFileName() {
return m_name;
}
};
}

View File

@ -1,338 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/Future.h>
#include <jus/debug.h>
#include <unistd.h>
#include <jus/File.h>
namespace jus {
template<>
bool jus::Future<bool>::get() {
if (m_data == nullptr) {
return false;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return false;
}
return m_data->m_returnData.getAnswer<bool>();
}
template<>
int64_t jus::Future<int64_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<bool>();
}
template<>
int32_t jus::Future<int32_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<int32_t>();
}
template<>
int16_t jus::Future<int16_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<int16_t>();
}
template<>
int8_t jus::Future<int8_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<int8_t>();
}
template<>
uint64_t jus::Future<uint64_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<int64_t>();
}
template<>
uint32_t jus::Future<uint32_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<uint32_t>();
}
template<>
uint16_t jus::Future<uint16_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<uint16_t>();
}
template<>
uint8_t jus::Future<uint8_t>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0;
}
return m_data->m_returnData.getAnswer<uint8_t>();
}
template<>
double jus::Future<double>::get() {
if (m_data == nullptr) {
return 0;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0.0;
}
return m_data->m_returnData.getAnswer<double>();
}
template<>
float jus::Future<float>::get() {
if (m_data == nullptr) {
return 0.0f;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return 0.0f;
}
return m_data->m_returnData.getAnswer<float>();
}
template<>
std::string jus::Future<std::string>::get() {
if (m_data == nullptr) {
return "";
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return "";
}
return m_data->m_returnData.getAnswer<std::string>();
}
template<>
std::vector<int64_t> jus::Future<std::vector<int64_t>>::get() {
std::vector<int64_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<int64_t>>();
return out;
}
template<>
std::vector<int32_t> jus::Future<std::vector<int32_t>>::get() {
std::vector<int32_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<int32_t>>();
return out;
}
template<>
std::vector<int16_t> jus::Future<std::vector<int16_t>>::get() {
std::vector<int16_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<int16_t>>();
return out;
}
template<>
std::vector<int8_t> jus::Future<std::vector<int8_t>>::get() {
std::vector<int8_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<int8_t>>();
return out;
}
template<>
std::vector<uint64_t> jus::Future<std::vector<uint64_t>>::get() {
std::vector<uint64_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<uint64_t>>();
return out;
}
template<>
std::vector<uint32_t> jus::Future<std::vector<uint32_t>>::get() {
std::vector<uint32_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<uint32_t>>();
return out;
}
template<>
std::vector<uint16_t> jus::Future<std::vector<uint16_t>>::get() {
std::vector<uint16_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<uint16_t>>();
return out;
}
template<>
std::vector<uint8_t> jus::Future<std::vector<uint8_t>>::get() {
std::vector<uint8_t> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<uint8_t>>();
return out;
}
template<>
std::vector<double> jus::Future<std::vector<double>>::get() {
std::vector<double> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<double>>();
return out;
}
template<>
std::vector<float> jus::Future<std::vector<float>>::get() {
std::vector<float> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<float>>();
return out;
}
template<>
std::vector<std::string> jus::Future<std::vector<std::string>>::get() {
std::vector<std::string> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<std::string>>();
return out;
}
template<>
std::vector<bool> jus::Future<std::vector<bool>>::get() {
std::vector<bool> out;
if (m_data == nullptr) {
return out;
}
if (m_data->m_returnData.getType() != jus::Buffer::typeMessage::answer) {
JUS_WARNING("No Return value ...");
return out;
}
out = m_data->m_returnData.getAnswer<std::vector<bool>>();
return out;
}
template<>
jus::File jus::Future<jus::File>::get() {
jus::File out;
if (m_data == nullptr) {
return out;
}
/* TODO : ...
ejson::Value val = m_data->m_returnData["return"];
if (val.exist() == false) {
JUS_WARNING("No Return value ...");
return out;
}
if (val.isObject() == false) {
JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Object'");
return out;
}
ejson::Object retVal = val.toObject();
if (retVal["type"].toString().get() != "file") {
JUS_WARNING("Wrong return object-type get '" << retVal["type"].toString().get() << " instead of 'file'");
return out;
}
out.setMineType(retVal["mine-type"].toString().get());
out.preSetDataSize(retVal["size"].toNumber().getU64());
// no data might be stored in the first packet ...
uint64_t offset = 0;
// TODO: check part ID
for (auto &it : m_data->m_returnDataPart) {
ejson::String valData = it.toString();
std::vector<uint8_t> tmpData = ejson::base64::decode(valData.get());
out.setData(offset, tmpData);
offset += tmpData.size();
}
*/
return out;
}
}

View File

@ -1,36 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/FutureBase.h>
namespace jus {
template<class JUS_RETURN>
class Future : public jus::FutureBase {
public:
Future(const jus::FutureBase& _base):
jus::FutureBase(_base) {
}
jus::Future<JUS_RETURN>& operator= (const jus::FutureBase& _base) {
m_data = _base.m_data;
return *this;
}
JUS_RETURN get();
};
template<>
class Future<void> : public jus::FutureBase {
public:
Future(const jus::FutureBase& _base):
jus::FutureBase(_base) {
}
jus::Future<void>& operator= (const jus::FutureBase& _base) {
m_data = _base.m_data;
return *this;
}
};
}

View File

@ -1,218 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/FutureBase.h>
#include <jus/debug.h>
#include <unistd.h>
jus::FutureBase::FutureBase(const jus::FutureBase& _base):
m_data(_base.m_data) {
}
jus::FutureBase::FutureBase() {
m_data = nullptr;
}
jus::FutureBase::FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback) {
m_data = std::make_shared<jus::FutureData>();
if (m_data == nullptr) {
return;
}
m_data->m_sendTime = std::chrono::steady_clock::now();
m_data->m_transactionId = _transactionId;
m_data->m_isFinished = false;
m_data->m_isSynchronous = false;
m_data->m_callbackFinish = _callback;
}
const jus::Buffer& jus::FutureBase::getRaw() {
if (m_data == nullptr) {
static jus::Buffer tmpp;
return tmpp;
}
return m_data->m_returnData;
}
jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, jus::Buffer _returnData, jus::FutureData::ObserverFinish _callback) {
m_data = std::make_shared<jus::FutureData>();
if (m_data == nullptr) {
return;
}
m_data->m_sendTime = std::chrono::steady_clock::now();
m_data->m_transactionId = _transactionId;
m_data->m_isFinished = _isFinished;
m_data->m_isSynchronous = false;
m_data->m_returnData = _returnData;
m_data->m_callbackFinish = _callback;
if (m_data->m_isFinished == true) {
m_data->m_receiveTime = std::chrono::steady_clock::now();
if (m_data->m_callbackFinish != nullptr) {
m_data->m_callbackFinish(*this);
}
}
}
std::chrono::nanoseconds jus::FutureBase::getTransmitionTime() {
if (m_data == nullptr) {
return std::chrono::nanoseconds(0);
}
if (m_data->m_isFinished == false) {
return std::chrono::nanoseconds(0);
}
return m_data->m_receiveTime - m_data->m_sendTime;
}
jus::FutureBase jus::FutureBase::operator= (const jus::FutureBase& _base) {
m_data = _base.m_data;
return *this;
}
bool jus::FutureBase::setAnswer(const jus::Buffer& _returnValue) {
if (m_data == nullptr) {
JUS_ERROR(" Not a valid future ...");
return true;
}
m_data->m_receiveTime = std::chrono::steady_clock::now();
if (m_data->m_isSynchronous == true) {
m_data->m_returnData = _returnValue;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
return true;
}
/* TODO : ...
if (_returnValue.valueExist("part") == true) {
uint64_t idPart = _returnValue["part"].toNumber().getU64();
if (idPart == 0) {
m_data->m_returnData = _returnValue;
} else {
m_data->m_returnDataPart.push_back(_returnValue["data"]);
}
if (_returnValue.valueExist("finish") == true) {
if (_returnValue["finish"].toBoolean().get() == true) {
m_data->m_isFinished = true;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
return true;
}
// finish is false ==> normal case ...
}
return false;
}*/
m_data->m_returnData = _returnValue;
m_data->m_isFinished = true;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
return true;
}
void jus::FutureBase::setSynchronous() {
if (m_data == nullptr) {
return;
}
m_data->m_isSynchronous = true;
}
uint64_t jus::FutureBase::getTransactionId() {
if (m_data == nullptr) {
return 0;
}
return m_data->m_transactionId;
}
bool jus::FutureBase::hasError() {
if (m_data == nullptr) {
return true;
}
return m_data->m_returnData.hasError();
}
std::string jus::FutureBase::getErrorType() {
if (m_data == nullptr) {
return "NULL_PTR";
}
return m_data->m_returnData.getError();
}
std::string jus::FutureBase::getErrorHelp() {
if (m_data == nullptr) {
return "Thsi is a nullptr future";
}
return m_data->m_returnData.getErrorHelp();
}
bool jus::FutureBase::isValid() {
return m_data != nullptr;
}
bool jus::FutureBase::isFinished() {
if (m_data == nullptr) {
return true;
}
return m_data->m_isFinished;
}
jus::FutureBase& jus::FutureBase::wait() {
while (isFinished() == false) {
// TODO : Do it better ... like messaging/mutex_locked ...
usleep(10000);
}
return *this;
}
jus::FutureBase& jus::FutureBase::waitFor(std::chrono::microseconds _delta) {
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
while ( std::chrono::steady_clock::now() - start < _delta
&& isFinished() == false) {
// TODO : Do it better ... like messaging/mutex_locked ...
usleep(10000);
start = std::chrono::steady_clock::now();
}
return *this;
}
jus::FutureBase& jus::FutureBase::waitUntil(std::chrono::steady_clock::time_point _endTime) {
while ( std::chrono::steady_clock::now() < _endTime
&& isFinished() == false) {
// TODO : Do it better ... like messaging/mutex_locked ...
usleep(10000);
}
return *this;
}
jus::FutureCall::FutureCall(uint64_t _clientId, uint64_t _transactionId, jus::Buffer& _callValue) :
m_transactionId(_transactionId),
m_clientId(_clientId),
m_isFinished(false) {
m_data = _callValue;
m_isFinished = m_data.getPartFinish();
}
void jus::FutureCall::appendData(jus::Buffer& _callValue) {
m_dataMultiplePack.push_back(_callValue);
m_isFinished = _callValue.getPartFinish();
}
uint64_t jus::FutureCall::getTransactionId() {
return m_transactionId;
}
uint64_t jus::FutureCall::getClientId() {
return m_clientId;
}
bool jus::FutureCall::isFinished() {
return m_isFinished;
}
jus::Buffer& jus::FutureCall::getRaw() {
return m_data;
}
std::chrono::nanoseconds jus::FutureCall::getTransmitionTime() {
return m_answerTime - m_receiveTime;
}

View File

@ -1,53 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/FutureData.h>
namespace jus {
class FutureBase {
public:
ememory::SharedPtr<jus::FutureData> m_data;
public:
FutureBase(const jus::FutureBase& _base);
FutureBase();
FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback=nullptr);
FutureBase(uint64_t _transactionId, bool _isFinished, jus::Buffer _returnData, jus::FutureData::ObserverFinish _callback=nullptr);
jus::FutureBase operator= (const jus::FutureBase& _base);
bool setAnswer(const jus::Buffer& _returnValue);
void setSynchronous();
uint64_t getTransactionId();
bool hasError();
std::string getErrorType();
std::string getErrorHelp();
bool isValid();
bool isFinished();
FutureBase& wait();
FutureBase& waitFor(std::chrono::microseconds _delta = std::chrono::seconds(30));
FutureBase& waitUntil(std::chrono::steady_clock::time_point _endTime);
const jus::Buffer& getRaw();
std::chrono::nanoseconds getTransmitionTime();
};
class FutureCall {
private:
uint64_t m_transactionId;
uint64_t m_clientId;
bool m_isFinished;
jus::Buffer m_data;
std::vector<jus::Buffer> m_dataMultiplePack;
std::chrono::steady_clock::time_point m_receiveTime;
std::chrono::steady_clock::time_point m_answerTime;
public:
FutureCall(uint64_t _clientId, uint64_t _transactionId, jus::Buffer& _callValue);
void appendData(jus::Buffer& _callValue);
uint64_t getTransactionId();
uint64_t getClientId();
bool isFinished();
std::chrono::nanoseconds getTransmitionTime();
jus::Buffer& getRaw();
};
}

View File

@ -1,28 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/types.h>
#include <jus/Buffer.h>
namespace jus {
class FutureBase;
class FutureData {
public:
using ObserverFinish = std::function<bool(jus::FutureBase)>; //!< Define an Observer: function pointer
public:
uint64_t m_transactionId;
bool m_isSynchronous;
bool m_isFinished;
jus::Buffer m_returnData;
//std::vector<ejson::Value> m_returnDataPart;
ObserverFinish m_callbackFinish;
std::chrono::steady_clock::time_point m_sendTime;
std::chrono::steady_clock::time_point m_receiveTime;
};
}

View File

@ -1,206 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/GateWay.h>
#include <jus/debug.h>
#include <enet/TcpServer.h>
namespace jus {
class TcpServerInput {
private:
enet::TcpServer m_interface;
std::thread* m_thread;
bool m_threadRunning;
jus::GateWay* m_gateway;
bool m_service;
public:
TcpServerInput(jus::GateWay* _gateway, bool _service) :
m_thread(nullptr),
m_threadRunning(false),
m_gateway(_gateway),
m_service(_service) {
}
virtual ~TcpServerInput() {}
void start(const std::string& _host, uint16_t _port) {
m_interface.setHostNane(_host);
m_interface.setPort(_port);
m_interface.link();
m_threadRunning = true;
m_thread = new std::thread([&](void *){ this->threadCallback();}, nullptr);
if (m_thread == nullptr) {
m_threadRunning = false;
JUS_ERROR("creating callback thread!");
return;
}
}
void stop() {
if (m_thread != nullptr) {
m_threadRunning = false;
}
m_interface.unlink();
if (m_thread != nullptr) {
m_thread->join();
delete m_thread;
m_thread = nullptr;
}
}
void threadCallback() {
// get datas:
while (m_threadRunning == true) {
// READ section data:
enet::Tcp data = std::move(m_interface.waitNext());
JUS_VERBOSE("New connection");
if (m_service == true) {
m_gateway->newService(std::move(data));
} else {
m_gateway->newClient(std::move(data));
}
}
}
};
}
void jus::GateWay::newService(enet::Tcp _connection) {
JUS_WARNING("New TCP connection (service)");
ememory::SharedPtr<jus::GateWayService> tmp = std::make_shared<jus::GateWayService>(std::move(_connection), this);
tmp->start();
m_serviceList.push_back(tmp);
}
void jus::GateWay::newClient(enet::Tcp _connection) {
JUS_WARNING("New TCP connection (client)");
ememory::SharedPtr<jus::GateWayClient> tmp = std::make_shared<jus::GateWayClient>(std::move(_connection), this);
tmp->start(m_clientUID++, m_clientUID++);
m_clientList.push_back(tmp);
}
jus::GateWay::GateWay() :
m_clientUID(1),
propertyClientIp(this, "client-ip", "127.0.0.1", "Ip to listen client", &jus::GateWay::onPropertyChangeClientIp),
propertyClientPort(this, "client-port", 1983, "Port to listen client", &jus::GateWay::onPropertyChangeClientPort),
propertyClientMax(this, "client-max", 80, "Maximum of client at the same time", &jus::GateWay::onPropertyChangeClientMax),
propertyServiceIp(this, "service-ip", "127.0.0.1", "Ip to listen client", &jus::GateWay::onPropertyChangeServiceIp),
propertyServicePort(this, "service-port", 1982, "Port to listen client", &jus::GateWay::onPropertyChangeServicePort),
propertyServiceMax(this, "service-max", 80, "Maximum of client at the same time", &jus::GateWay::onPropertyChangeServiceMax) {
m_interfaceClientServer = std::make_shared<jus::TcpServerInput>(this, false);
m_interfaceServiceServer = std::make_shared<jus::TcpServerInput>(this, true);
}
jus::GateWay::~GateWay() {
}
void jus::GateWay::start() {
m_interfaceClientServer->start(*propertyClientIp, *propertyClientPort);
m_interfaceServiceServer->start(*propertyServiceIp, *propertyServicePort);
}
void jus::GateWay::stop() {
}
ememory::SharedPtr<jus::GateWayService> jus::GateWay::get(const std::string& _serviceName) {
for (auto &it : m_serviceList) {
if (it == nullptr) {
continue;
}
if (it->getName() != _serviceName) {
continue;
}
return it;
}
return nullptr;
}
std::vector<std::string> jus::GateWay::getAllServiceName() {
std::vector<std::string> out;
for (auto &it : m_serviceList) {
if (it == nullptr) {
continue;
}
out.push_back(it->getName());
}
return out;
}
void jus::GateWay::answer(uint64_t _userSessionId, jus::Buffer& _data) {
for (auto &it : m_clientList) {
if (it == nullptr) {
continue;
}
if (it->checkId(_userSessionId) == false) {
continue;
}
it->returnMessage(_data);
return;
}
}
void jus::GateWay::cleanIO() {
auto it = m_serviceList.begin();
while (it != m_serviceList.end()) {
if (*it != nullptr) {
if ((*it)->isAlive() == false) {
it = m_serviceList.erase(it);
continue;
}
} else {
it = m_serviceList.erase(it);
continue;
}
++it;
}
auto it2 = m_clientList.begin();
while (it2 != m_clientList.end()) {
if (*it2 != nullptr) {
if ((*it2)->isAlive() == false) {
it2 = m_clientList.erase(it2);
continue;
}
} else {
it2 = m_clientList.erase(it2);
continue;
}
++it2;
}
}
void jus::GateWay::onClientConnect(const bool& _value) {
JUS_TODO("Client connection: " << _value);
}
void jus::GateWay::onServiceConnect(const bool& _value) {
JUS_TODO("Service connection: " << _value);
}
void jus::GateWay::onPropertyChangeClientIp() {
}
void jus::GateWay::onPropertyChangeClientPort() {
}
void jus::GateWay::onPropertyChangeClientMax() {
}
void jus::GateWay::onPropertyChangeServiceIp() {
}
void jus::GateWay::onPropertyChangeServicePort() {
}
void jus::GateWay::onPropertyChangeServiceMax() {
}

View File

@ -1,50 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/GateWayService.h>
#include <jus/GateWayClient.h>
namespace jus {
class TcpServerInput;
class GateWay : public eproperty::Interface {
private:
uint64_t m_clientUID;
private:
std::vector<ememory::SharedPtr<jus::GateWayService>> m_serviceList; //!< List of all service availlable with their specific connection interface
std::vector<ememory::SharedPtr<jus::GateWayClient>> m_clientList; //!< List of all Client interface with their own connection
//TODO: std::vector<jus::GateWayServer> m_ServerList; //!< List of all Server connected to this gateway
ememory::SharedPtr<jus::TcpServerInput> m_interfaceClientServer;
ememory::SharedPtr<jus::TcpServerInput> m_interfaceServiceServer;
public:
eproperty::Value<std::string> propertyClientIp;
eproperty::Value<uint16_t> propertyClientPort;
eproperty::Value<uint16_t> propertyClientMax;
eproperty::Value<std::string> propertyServiceIp;
eproperty::Value<uint16_t> propertyServicePort;
eproperty::Value<uint16_t> propertyServiceMax;
public:
GateWay();
virtual ~GateWay();
void start();
void stop();
ememory::SharedPtr<jus::GateWayService> get(const std::string& _serviceName);
std::vector<std::string> getAllServiceName();
void answer(uint64_t _userSessionId, jus::Buffer& _data);
void newService(enet::Tcp _connection);
void newClient(enet::Tcp _connection);
void cleanIO();
private:
void onPropertyChangeClientIp();
void onPropertyChangeClientPort();
void onPropertyChangeClientMax();
void onPropertyChangeServiceIp();
void onPropertyChangeServicePort();
void onPropertyChangeServiceMax();
void onClientConnect(const bool& _value);
void onServiceConnect(const bool& _value);
};
}

View File

@ -1,366 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/debug.h>
#include <jus/GateWayClient.h>
#include <ejson/ejson.h>
#include <jus/GateWay.h>
#include <unistd.h>
#include <jus/AbstractFunction.h>
static const std::string protocolError = "PROTOCOL-ERROR";
jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface) :
m_state(jus::GateWayClient::state::unconnect),
m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)) {
JUS_INFO("----------------");
JUS_INFO("-- NEW Client --");
JUS_INFO("----------------");
}
jus::GateWayClient::~GateWayClient() {
JUS_TODO("Call All unlink ...");
stop();
JUS_INFO("-------------------");
JUS_INFO("-- DELETE Client --");
JUS_INFO("-------------------");
}
void jus::GateWayClient::start(uint64_t _uid, uint64_t _uid2) {
m_uid = _uid;
m_uid2 = _uid2;
m_state = jus::GateWayClient::state::connect;
m_interfaceClient.connect(this, &jus::GateWayClient::onClientData);
m_interfaceClient.connect(true);
m_interfaceClient.setInterfaceName("cli-" + etk::to_string(m_uid));
}
void jus::GateWayClient::stop() {
for (auto &it : m_listConnectedService) {
if (it == nullptr) {
continue;
}
it->m_interfaceClient.callClient(m_uid, "_delete");
/*
ejson::Object linkService;
linkService.add("call", ejson::String("_delete"));
linkService.add("id", ejson::Number(m_transactionLocalId++));
linkService.add("param", ejson::Array());
it->SendData(m_uid, linkService);
*/
}
if (m_userService != nullptr) {
m_userService->m_interfaceClient.callClient(m_uid2, "_delete");
/*
ejson::Object linkService;
linkService.add("call", ejson::String("_delete"));
linkService.add("id", ejson::Number(m_transactionLocalId++));
linkService.add("param", ejson::Array());
m_userService->SendData(m_uid2, linkService);
*/
m_userService = nullptr;
}
m_listConnectedService.clear();
m_interfaceClient.disconnect();
}
bool jus::GateWayClient::isAlive() {
return m_interfaceClient.isActive();
}
void jus::GateWayClient::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) {
m_interfaceClient.answerError(_transactionId, protocolError, _errorHelp);
m_state = jus::GateWayClient::state::disconnect;
m_interfaceClient.disconnect(true);
}
void jus::GateWayClient::onClientData(jus::Buffer& _value) {
uint32_t transactionId = _value.getTransactionId();
if (transactionId == 0) {
JUS_ERROR("Protocol error ==>missing id");
answerProtocolError(transactionId, "missing parameter: 'id'");
return;
}
if (_value.getType() != jus::Buffer::typeMessage::call) {
JUS_ERROR("Protocol error ==>missing 'call'");
answerProtocolError(transactionId, "missing parameter: 'call' / wrong type 'call'");
return;
}
std::string callFunction = _value.getCall();
switch (m_state) {
case jus::GateWayClient::state::disconnect:
case jus::GateWayClient::state::unconnect:
{
JUS_ERROR("Must never appear");
answerProtocolError(transactionId, "Gateway internal error");
return;
}
case jus::GateWayClient::state::connect:
{
if (m_userConnectionName != "") {
answerProtocolError(transactionId, "Gateway internal error 2");
return;
}
if (callFunction == "setMode") {
std::string mode = _value.getParameter<std::string>(0);
if (mode == "JSON") {
JUS_WARNING("[" << m_uid << "] Change mode in: JSON");
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeJson);
} else if (mode == "BIN") {
JUS_WARNING("[" << m_uid << "] Change mode in: BINARY");
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeBinary);
} else if (mode == "XML") {
JUS_WARNING("[" << m_uid << "] Change mode in: XML");
//m_interfaceMode = jus::connectionMode::modeXml;
m_interfaceClient.answerValue(transactionId, false);
} else {
answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]");
}
return;
} else if (callFunction == "connectToUser") {
m_userConnectionName = _value.getParameter<std::string>(0);
if (m_userConnectionName == "") {
answerProtocolError(transactionId, "Call connectToUser with no parameter 'user'");
} else {
JUS_WARNING("[" << m_uid << "] Set client connect to user : '" << m_userConnectionName << "'");
m_userService = m_gatewayInterface->get("system-user");
if (m_userService == nullptr) {
answerProtocolError(transactionId, "Gateway internal error 'No user interface'");
} else {
jus::Future<bool> futLocalService = m_userService->m_interfaceClient.callClient(m_uid2, "_new", m_userConnectionName, "**Gateway**", std::vector<std::string>());
futLocalService.wait(); // TODO: Set timeout ...
m_state = jus::GateWayClient::state::userIdentify;
m_interfaceClient.answerValue(transactionId, true);
}
}
return;
}
JUS_WARNING("[" << m_uid << "] Client must send conection to user name ...");
answerProtocolError(transactionId, "Missing call of connectToUser");
return;
}
case jus::GateWayClient::state::userIdentify:
{
m_clientServices.clear();
m_clientgroups.clear();
m_clientName.clear();
if ( callFunction != "identify"
&& callFunction != "auth"
&& callFunction != "anonymous") {
answerProtocolError(transactionId, "Client must call: identify/auth/anonymous");
return;
}
if (callFunction == "identify") {
std::string clientName = _value.getParameter<std::string>(0);
std::string clientTocken = _value.getParameter<std::string>(1);
if (m_userService == nullptr) {
answerProtocolError(transactionId, "gateWay internal error 3");
return;
}
jus::Future<bool> fut = m_userService->m_interfaceClient.callClient(m_uid2, "checkTocken", clientName, clientTocken);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = clientName;
}
if (callFunction == "auth") {
std::string password = _value.getParameter<std::string>(0);
jus::Future<bool> fut = m_userService->m_interfaceClient.callClient(m_uid2, "checkAuth", password);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = m_userConnectionName;
}
if (callFunction == "anonymous") {
m_clientName = "";
}
// --------------------------------
// -- Get groups:
// --------------------------------
jus::Future<std::vector<std::string>> futGroup = m_userService->m_interfaceClient.callClient(m_uid2, "getGroups", m_clientName);
futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) {
JUS_ERROR("Get error from the service ...");
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "grouping error");
return;
}
m_clientgroups = futGroup.get();
// --------------------------------
// -- Get services:
// --------------------------------
std::vector<std::string> currentServices = m_gatewayInterface->getAllServiceName();
jus::Future<std::vector<std::string>> futServices = m_userService->m_interfaceClient.callClient(m_uid2, "filterServices", m_clientName, currentServices);
futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) {
JUS_ERROR("Get error from the service ...");
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "service filtering error");
return;
}
m_clientServices = futServices.get();
JUS_WARNING("Connection of: '" << m_clientName << "' to '" << m_userConnectionName << "'");
JUS_WARNING(" groups: " << etk::to_string(m_clientgroups));
JUS_WARNING(" services: " << etk::to_string(m_clientServices));
m_interfaceClient.answerValue(transactionId, true);
m_state = jus::GateWayClient::state::clientIdentify;
return;
}
break;
case jus::GateWayClient::state::clientIdentify:
{
uint32_t serviceId = _value.getServiceId();
if (serviceId == 0) {
// This is 2 default service for the cient interface that manage the authorisation of view:
if (callFunction == "getServiceCount") {
m_interfaceClient.answerValue(transactionId, m_clientServices.size());
return;
}
if (callFunction == "getServiceList") {
m_interfaceClient.answerValue(transactionId, m_clientServices);
//listService.add(ejson::String("ServiceManager/v0.1.0"));
return;
}
if (callFunction == "link") {
// first param:
std::string serviceName = _value.getParameter<std::string>(0);
// Check if service already link:
auto it = m_listConnectedService.begin();
while (it != m_listConnectedService.end()) {
if (*it == nullptr) {
++it;
continue;
}
if ((*it)->getName() != serviceName) {
++it;
continue;
}
break;
}
if (it == m_listConnectedService.end()) {
// check if service is connectable ...
if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) {
m_interfaceClient.answerError(transactionId, "UN-AUTHORIZED-SERVICE");
return;
}
ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName);
if (srv != nullptr) {
jus::Future<bool> futLink = srv->m_interfaceClient.callClient(m_uid, "_new", m_userConnectionName, m_clientName, m_clientgroups);
futLink.wait(); // TODO: Set timeout ...
if (futLink.hasError() == true) {
JUS_ERROR("Get error from the service ... LINK");
m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService.push_back(srv);
m_interfaceClient.answerValue(transactionId, m_listConnectedService.size());
return;
}
m_interfaceClient.answerError(transactionId, "CAN-NOT-CONNECT-SERVICE");
return;
}
m_interfaceClient.answerError(transactionId, "SERVICE-ALREADY-CONNECTED");;
return;
}
if (callFunction == "unlink") {
// first param: the service we want to unconnect ...
int64_t localServiceID = _value.getParameter<int64_t>(0)-1;
// Check if service already link:
if (localServiceID >= m_listConnectedService.size()) {
m_interfaceClient.answerError(transactionId, "NOT-CONNECTED-SERVICE");
return;
}
jus::Future<bool> futUnLink = m_listConnectedService[localServiceID]->m_interfaceClient.callClient(m_uid, "_delete");
futUnLink.wait(); // TODO: Set timeout ...
if (futUnLink.hasError() == true) {
JUS_ERROR("Get error from the service ... UNLINK");
m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService[localServiceID] = nullptr;
m_interfaceClient.answerValue(transactionId, true);
return;
}
JUS_ERROR("Function does not exist ... '" << callFunction << "'");
m_interfaceClient.answerError(transactionId, "CALL-UNEXISTING");
return;
}
// decrease service ID ...
serviceId -= 1;
if (serviceId >= m_listConnectedService.size()) {
m_interfaceClient.answerError(transactionId, "NOT-CONNECTED-SERVICE");
return;
} else {
if (m_listConnectedService[serviceId] == nullptr) {
// TODO ...
JUS_ERROR("TODO : Manage this case ...");
return;
}
uint16_t partId = _value.getPartId();
if (partId != 0) {
m_listConnectedService[serviceId]->m_interfaceClient.callForwardMultiple(
m_uid,
_value,
(uint64_t(m_uid) << 32) + uint64_t(transactionId));
return;
}
m_listConnectedService[serviceId]->m_interfaceClient.callForward(
m_uid,
_value,
(uint64_t(m_uid) << 32) + uint64_t(transactionId),
[=](jus::FutureBase _ret) {
jus::Buffer tmpp = _ret.getRaw();
JUS_DEBUG(" ==> transmit : " << tmpp.getTransactionId() << " -> " << transactionId);
JUS_DEBUG(" msg=" << tmpp.generateHumanString());
tmpp.setTransactionId(transactionId);
tmpp.setServiceId(serviceId+1);
JUS_DEBUG("transmit=" << tmpp.generateHumanString());
if (m_interfaceClient.getMode() == jus::connectionMode::modeJson) {
ejson::Object obj = tmpp.toJson();
m_interfaceClient.writeJson(obj);
} else if (m_interfaceClient.getMode() == jus::connectionMode::modeBinary) {
m_interfaceClient.writeBinary(tmpp);
} else if (m_interfaceClient.getMode() == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
// multiple send element ...
return tmpp.getPartFinish();
});
}
}
}
}
void jus::GateWayClient::returnMessage(jus::Buffer& _data) {
JUS_ERROR("Get call from the Service to the user ...");
}

View File

@ -1,65 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <ememory/memory.h>
#include <esignal/Signal.h>
#include <jus/GateWayService.h>
#include <jus/Future.h>
#include <jus/AbstractFunction.h>
#include <jus/connectionMode.h>
namespace jus {
class GateWay;
class GateWayClient {
private:
enum class state {
unconnect, // starting sate
connect, // just get a TCP connection
userIdentify, // client set the user it want to access
clientIdentify, // client defien the mode of the acces (anonymous,client/user)
disconnect // client is dead or loal disconnection
};
enum state m_state; // state machine ...
private:
jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient;
public:
enum jus::connectionMode getMode() {
return m_interfaceClient.getMode();
}
public:
esignal::Signal<bool> signalIsConnected;
ememory::SharedPtr<jus::GateWayService> m_userService;
std::vector<ememory::SharedPtr<jus::GateWayService>> m_listConnectedService;
uint64_t m_uid;
uint64_t m_uid2;
std::string m_userConnectionName;
std::string m_clientName;
std::vector<std::string> m_clientgroups;
std::vector<std::string> m_clientServices;
public:
GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface);
virtual ~GateWayClient();
void start(uint64_t _uid, uint64_t _uid2);
void stop();
void onClientData(jus::Buffer& _value);
void returnMessage(jus::Buffer& _data);
bool checkId(uint64_t _id) const {
return m_uid == _id
|| m_uid2 == _id;
}
bool isAlive();
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
};
}

View File

@ -1,133 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/debug.h>
#include <jus/GateWayService.h>
#include <jus/GateWay.h>
#include <ejson/ejson.h>
// todo : cHANGE THIS ...
static const std::string protocolError = "PROTOCOL-ERROR";
jus::GateWayService::GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface) :
m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)) {
JUS_INFO("-----------------");
JUS_INFO("-- NEW Service --");
JUS_INFO("-----------------");
}
jus::GateWayService::~GateWayService() {
JUS_INFO("--------------------");
JUS_INFO("-- DELETE Service --");
JUS_INFO("--------------------");
}
bool jus::GateWayService::isAlive() {
return m_interfaceClient.isActive();
}
void jus::GateWayService::start() {
m_interfaceClient.connect(this, &jus::GateWayService::onServiceData);
m_interfaceClient.connect();
m_interfaceClient.setInterfaceName("srv-?");
}
void jus::GateWayService::stop() {
m_interfaceClient.disconnect();
}
void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) {
_data.add("client-id", ejson::Number(_userSessionId));
m_interfaceClient.writeJson(_data);
}
void jus::GateWayService::SendData(uint64_t _userSessionId, jus::Buffer& _data) {
_data.setClientId(_userSessionId);
_data.prepare();
if (m_interfaceClient.getMode() == jus::connectionMode::modeJson) {
ejson::Object obj = _data.toJson();
m_interfaceClient.writeJson(obj);
} else if (m_interfaceClient.getMode() == jus::connectionMode::modeXml) {
JUS_ERROR("NOT manage transcriptioon binary to XML ... ");
} else if (m_interfaceClient.getMode() == jus::connectionMode::modeBinary) {
m_interfaceClient.writeBinary(_data);
} else {
JUS_ERROR("NOT manage transcriptioon binary to ??? mode ... ");
}
}
void jus::GateWayService::onServiceData(jus::Buffer& _value) {
JUS_DEBUG("On service data: " << _value.toJson().generateHumanString());
uint32_t transactionId = _value.getTransactionId();
//data.add("from-service", ejson::String(m_name));
if (_value.getType() == jus::Buffer::typeMessage::event) {
/*
if (data.valueExist("event") == true) {
// No need to have a user ID ...
if (data["event"].toString().get() == "IS-ALIVE") {
JUS_VERBOSE("Service Alive ...");
if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(20)) {
ejson::Object tmpp;
tmpp.add("event", ejson::String("IS-ALIVE"));
m_interfaceClient.writeJson(tmpp);
}
} else {
JUS_INFO("Unknow service event: '" << data["event"].toString().get() << "'");
}
return;
}
*/
return;
}
if (_value.getType() == jus::Buffer::typeMessage::call) {
std::string callFunction = _value.getCall();
if (callFunction == "setMode") {
std::string mode = _value.getParameter<std::string>(0);
if (mode == "JSON") {
JUS_WARNING("Change mode in: JSON");
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeJson);
} else if (mode == "BIN") {
JUS_WARNING("Change mode in: BINARY");
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeBinary);
} else if (mode == "XML") {
JUS_WARNING("Change mode in: XML");
//m_interfaceMode = jus::connectionMode::modeXml;
m_interfaceClient.answerValue(transactionId, false);
} else {
answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]");
}
return;
} else if (callFunction == "connect-service") {
if (m_name != "") {
JUS_WARNING("Service interface ==> try change the servie name after init: '" << _value.getParameter<std::string>(0));
m_interfaceClient.answerValue(transactionId, false);
return;
}
m_name = _value.getParameter<std::string>(0);
m_interfaceClient.setInterfaceName("srv-" + m_name);
m_interfaceClient.answerValue(transactionId, true);
return;
}
answerProtocolError(transactionId, "unknow function");
}
if (_value.getClientId() == 0) {
JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'");
return;
}
m_gatewayInterface->answer(_value.getClientId(), _value);
}
void jus::GateWayService::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) {
m_interfaceClient.answerError(_transactionId, protocolError, _errorHelp);
m_interfaceClient.disconnect(true);
}

View File

@ -1,42 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <ememory/memory.h>
#include <esignal/Signal.h>
#include <ejson/ejson.h>
#include <jus/connectionMode.h>
namespace jus {
class GateWay;
class GateWayClient;
class GateWayService {
friend class jus::GateWayClient;
private:
jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient;
std::string m_name;
public:
esignal::Signal<bool> signalIsConnected;
public:
GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface);
virtual ~GateWayService();
void start();
void stop();
void onServiceData(jus::Buffer& _value);
public:
void SendData(uint64_t _userSessionId, ejson::Object _data);
void SendData(uint64_t _userSessionId, jus::Buffer& _data);
const std::string& getName() {
return m_name;
}
bool isAlive();
protected:
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
};
}

View File

@ -1,71 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/ParamType.h>
#include <jus/debug.h>
#include <jus/File.h>
jus::ParamType::ParamType(const char* _name):
m_typeName(_name) {
}
const char* jus::ParamType::getName() const {
return m_typeName;
}
bool jus::ParamType::operator == (const ParamType& _obj) const {
return m_typeName == _obj.m_typeName;
}
bool jus::ParamType::operator == (const std::string& _value) const {
return _value == m_typeName;
}
bool jus::ParamType::operator != (const std::string& _value) const {
return _value != m_typeName;
}
#define generate_basic_type(_type, _name) \
namespace jus { \
template<> jus::ParamType createType<_type>() {\
return jus::ParamType(_name); \
} \
}
generate_basic_type(void, "void");
generate_basic_type(bool, "bool");
generate_basic_type(float, "float");
generate_basic_type(double, "double");
generate_basic_type(int64_t, "int64");
generate_basic_type(int32_t, "int32");
generate_basic_type(int16_t, "int16");
generate_basic_type(int8_t, "int8");
generate_basic_type(uint64_t, "uint64");
generate_basic_type(uint32_t, "uint32");
generate_basic_type(uint16_t, "uint16");
generate_basic_type(uint8_t, "uint8");
generate_basic_type(std::string, "string");
generate_basic_type(std::vector<bool>, "vector:bool");
generate_basic_type(std::vector<float>, "vector:float");
generate_basic_type(std::vector<double>, "vector:double");
generate_basic_type(std::vector<int64_t>, "vector:int64");
generate_basic_type(std::vector<int32_t>, "vector:int32");
generate_basic_type(std::vector<int16_t>, "vector:int16");
generate_basic_type(std::vector<int8_t>, "vector:int8");
generate_basic_type(std::vector<uint64_t>, "vector:uint64");
generate_basic_type(std::vector<uint32_t>, "vector:uint32");
generate_basic_type(std::vector<uint16_t>, "vector:uint16");
generate_basic_type(std::vector<uint8_t>, "vector:uint8");
generate_basic_type(std::vector<std::string>, "vector:string");
generate_basic_type(jus::File, "file");
generate_basic_type(jus::FileServer, "file");

View File

@ -1,26 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <string>
namespace jus {
class ParamType {
protected:
const char* m_typeName;
public:
ParamType(const char* _name = "");
const char* getName() const;
bool operator == (const ParamType& _obj) const;
bool operator == (const std::string& _value) const;
bool operator != (const std::string& _value) const;
};
template<class JUS_TYPE>
ParamType createType();
}

View File

@ -1,242 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/RemoteProcessCall.h>
jus::RemoteProcessCall::RemoteProcessCall() :
m_type("UNKNOW"){
advertise("getDescription", &jus::RemoteProcessCall::getDescription);
setLastFuncDesc("Get description");
addLastFuncReturn("String version of the service number separate with dot with -dev at the end if developpement version, and '-number' or integration version uipdate : 1.5.2 or 1.8-dev 1.5.2-55");
advertise("getVersion", &jus::RemoteProcessCall::getVersion);
setLastFuncDesc("Get version");
addLastFuncReturn("String version of the service number separate with dot with -dev at the end if developpement version, and '-number' or integration version uipdate : 1.5.2 or 1.8-dev 1.5.2-55");
advertise("getType", &jus::RemoteProcessCall::getType);
setLastFuncDesc("Get type");
addLastFuncReturn("String of generic type of the service base on TYPE-ENTERPRISE.ENTERPRISE-NAME.SERVICE-TYPE/VERSION_PROTOCOL");
advertise("getAuthors", &jus::RemoteProcessCall::getAuthors2);
setLastFuncDesc("Get List of developper/maintainer");
addLastFuncReturn("list of personnes: 'NAME surname <email@xxx.yyy>'");
advertise("getFunctions", &jus::RemoteProcessCall::getFunctions);
setLastFuncDesc("Get List of function availlable (filter with right)");
addLastFuncReturn("list of function name");
advertise("getFunctionSignature", &jus::RemoteProcessCall::getFunctionSignature);
addLastFuncParam("func", "function name");
setLastFuncDesc("Get List type of return and after the parameters");
addLastFuncReturn("list of element type");
advertise("getFunctionPrototype", &jus::RemoteProcessCall::getFunctionPrototype);
addLastFuncParam("func", "function name");
setLastFuncDesc("Get List type of return and after the parameters");
addLastFuncReturn("list of element type");
advertise("getFunctionDescription", &jus::RemoteProcessCall::getFunctionDescription);
addLastFuncParam("func", "function name");
setLastFuncDesc("get function description");
addLastFuncReturn("generic string");
}
void jus::RemoteProcessCall::setDescription(const std::string& _desc) {
m_description = _desc;
}
std::string jus::RemoteProcessCall::getDescription() {
return m_description;
}
void jus::RemoteProcessCall::setVersion(const std::string& _desc) {
m_version = _desc;
}
std::string jus::RemoteProcessCall::getVersion() {
return m_version;
}
void jus::RemoteProcessCall::addAuthor(const std::string& _name, const std::string& _email) {
m_authors.push_back(std::make_pair(_name, _email));
}
const std::vector<std::pair<std::string,std::string>>& jus::RemoteProcessCall::getAuthors() const {
return m_authors;
}
std::vector<std::string> jus::RemoteProcessCall::getAuthors2() {
std::vector<std::string> out;
for (auto &it : m_authors) {
out.push_back(it.first + "<" + it.second + ">");
}
return out;
}
void jus::RemoteProcessCall::setLastFuncDesc(const std::string& _desc) {
if (m_listFunction.size() == 0) {
JUS_ERROR("Can not set description to a function with no function advertise before ...");
return;
}
if (m_listFunction[m_listFunction.size()-1] == nullptr) {
JUS_ERROR("Last element is nullptr ... ==> what are you doing??");
return;
}
m_listFunction[m_listFunction.size()-1]->setDescription(_desc);
}
void jus::RemoteProcessCall::setFuncDesc(const std::string& _funcName, const std::string& _desc) {
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() != _funcName) {
continue;
}
it->setDescription(_desc);
return;
}
JUS_ERROR("function '" << _funcName << "' des not exist");
}
void jus::RemoteProcessCall::addLastFuncParam(const std::string& _name, const std::string& _desc) {
if (m_listFunction.size() == 0) {
JUS_ERROR("Can not set description to a function with no function advertise before ...");
return;
}
if (m_listFunction[m_listFunction.size()-1] == nullptr) {
JUS_ERROR("Last element is nullptr ... ==> what are you doing??");
return;
}
m_listFunction[m_listFunction.size()-1]->addParam(_name, _desc);
}
void jus::RemoteProcessCall::setFuncParam(const std::string& _funcName, int32_t _idParam, const std::string& _name, const std::string& _desc) {
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() != _funcName) {
continue;
}
it->setParam(_idParam, _name, _desc);
return;
}
JUS_ERROR("function '" << _funcName << "' des not exist");
}
void jus::RemoteProcessCall::addLastFuncReturn(const std::string& _desc) {
if (m_listFunction.size() == 0) {
JUS_ERROR("Can not set return to a function with no function advertise before ...");
return;
}
if (m_listFunction[m_listFunction.size()-1] == nullptr) {
JUS_ERROR("Last element is nullptr ... ==> what are you doing??");
return;
}
m_listFunction[m_listFunction.size()-1]->setReturn(_desc);
}
void jus::RemoteProcessCall::setFuncReturn(const std::string& _funcName, const std::string& _desc) {
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() != _funcName) {
continue;
}
it->setReturn(_desc);
return;
}
JUS_ERROR("function '" << _funcName << "' des not exist");
}
std::string jus::RemoteProcessCall::getType() {
return m_type;
}
void jus::RemoteProcessCall::setType(const std::string& _type, uint16_t _version) {
m_type = _type + "/" + etk::to_string(_version);
}
std::vector<std::string> jus::RemoteProcessCall::getFunctions() {
std::vector<std::string> out;
for (auto &it: m_listFunction) {
if (it == nullptr) {
continue;
}
/*
if (isFunctionAuthorized(it->getName()) == false) {
continue;
}
*/
out.push_back(it->getName());
}
return out;
}
std::vector<std::string> jus::RemoteProcessCall::getFunctionSignature(std::string _funcName) {
/*
if (isFunctionAuthorized(_funcName) == false) {
return std::vector<std::string>();
}
*/
for (auto &it: m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() != _funcName) {
continue;
}
std::vector<std::string> out;
out = it->getPrototypeParam();
out.insert(out.begin(), it->getPrototypeReturn());
return out;
}
return std::vector<std::string>();
}
std::string jus::RemoteProcessCall::getFunctionPrototype(std::string _funcName) {
/*
if (isFunctionAuthorized(_funcName) == false) {
return "";
}
*/
for (auto &it: m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() != _funcName) {
continue;
}
return it->getPrototypeFull();
}
return "";
}
std::string jus::RemoteProcessCall::getFunctionDescription(std::string _funcName) {
/*
if (isFunctionAuthorized(_funcName) == false) {
return std::string("UNKNOW Function: ") + _funcName;
}
*/
for (auto &it: m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() != _funcName) {
continue;
}
return it->getDescription();
}
return "";
}
bool jus::RemoteProcessCall::isFunctionAuthorized(uint64_t _clientSessionID, const std::string& _funcName) {
return true;
}

View File

@ -1,109 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h>
#include <ejson/ejson.h>
#include <jus/AbstractFunctionTypeDirect.h>
#include <jus/AbstractFunctionTypeClass.h>
#include <jus/debug.h>
namespace jus {
class RemoteProcessCall {
public:
RemoteProcessCall();
protected:
std::vector<jus::AbstractFunction*> m_listFunction;
protected:
std::string m_description;
public:
void setDescription(const std::string& _desc);
std::string getDescription();
protected:
std::string m_version;
public:
void setVersion(const std::string& _desc);
std::string getVersion();
protected:
std::vector<std::pair<std::string,std::string>> m_authors;
public:
void addAuthor(const std::string& _name, const std::string& _email);
const std::vector<std::pair<std::string,std::string>>& getAuthors() const;
std::vector<std::string> getAuthors2();
protected:
std::string m_type;
public:
std::string getType();
void setType(const std::string& _type, uint16_t _version);
public:
std::vector<std::string> getFunctions();
std::vector<std::string> getFunctionSignature(std::string _funcName);
std::string getFunctionPrototype(std::string _funcName);
std::string getFunctionDescription(std::string _funcName);
public:
void setLastFuncDesc(const std::string& _desc);
void setFuncDesc(const std::string& _funcName, const std::string& _desc);
void addLastFuncParam(const std::string& _name, const std::string& _desc);
void setFuncParam(const std::string& _funcName, int32_t _idParam, const std::string& _name, const std::string& _desc);
void addLastFuncReturn(const std::string& _desc);
void setFuncReturn(const std::string& _funcName, const std::string& _desc);
protected:
virtual bool isFunctionAuthorized(uint64_t _clientSessionID, const std::string& _funcName);
public:
// Add global fuction (no link with this class)
template<class JUS_RETURN_VALUE,
class... JUS_FUNC_ARGS_TYPE>
void advertise(const std::string& _name,
JUS_RETURN_VALUE (*_func)(JUS_FUNC_ARGS_TYPE... _args),
const std::string& _desc = "") {
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() == _name) {
JUS_ERROR("Advertise function already bind .. ==> can not be done...: '" << _name << "'");
return;
}
}
AbstractFunction* tmp = createAbstractFunctionDirect(_name, _desc, _func);
if (tmp == nullptr) {
JUS_ERROR("can not create abstract function ... '" << _name << "'");
return;
}
tmp->setType(jus::AbstractFunction::type::global);
JUS_INFO("Add function '" << _name << "' in global mode");
m_listFunction.push_back(tmp);
}
// Add Local fuction (depend on this class)
template<class JUS_RETURN_VALUE,
class JUS_CLASS_TYPE,
class... JUS_FUNC_ARGS_TYPE>
void advertise(std::string _name,
JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args),
const std::string& _desc = "") {
_name = "sys." + _name;
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() == _name) {
JUS_ERROR("Advertise function already bind .. ==> can not be done...: '" << _name << "'");
return;
}
}
AbstractFunction* tmp = createAbstractFunctionClass(_name, _desc, _func);
if (tmp == nullptr) {
JUS_ERROR("can not create abstract function ... '" << _name << "'");
return;
}
tmp->setType(jus::AbstractFunction::type::local);
JUS_INFO("Add function '" << _name << "' in local mode");
m_listFunction.push_back(tmp);
}
};
}

View File

@ -1,176 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/Service.h>
#include <jus/debug.h>
#include <etk/stdTools.h>
#include <enet/TcpClient.h>
#include <ejson/ejson.h>
#include <unistd.h>
jus::Service::Service() :
propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Service::onPropertyChangeIp),
propertyPort(this, "port", 1982, "Port to connect server", &jus::Service::onPropertyChangePort) {
advertise("getExtention", &jus::Service::getExtention);
setLastFuncDesc("Get List of availlable extention of this service");
addLastFuncReturn("A list of extention register in the service");
}
jus::Service::~Service() {
}
std::vector<std::string> jus::Service::getExtention() {
return std::vector<std::string>();
}
void jus::Service::onClientData(jus::Buffer& _value) {
uint32_t tmpID = _value.getTransactionId();
uint32_t clientId = _value.getClientId();;
auto it = m_callMultiData.begin();
while (it != m_callMultiData.end()) {
if ( it->getTransactionId() == tmpID
&& it->getClientId() == clientId) {
JUS_WARNING("Append data ... " << tmpID);
it->appendData(_value);
if (it->isFinished() == true) {
JUS_WARNING("CALL Function ...");
callBinary(tmpID, it->getRaw());
it = m_callMultiData.erase(it);
}
return;
}
++it;
}
jus::FutureCall futCall(clientId, tmpID, _value);
if (futCall.isFinished() == true) {
JUS_INFO("Call Binary ..");
callBinary(tmpID, futCall.getRaw());
} else {
m_callMultiData.push_back(futCall);
}
}
void jus::Service::onPropertyChangeIp() {
disconnect();
}
void jus::Service::onPropertyChangePort(){
disconnect();
}
void jus::Service::connect(const std::string& _serviceName, uint32_t _numberRetry){
disconnect();
JUS_DEBUG("connect [START]");
enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort, _numberRetry));
if (connection.getConnectionStatus() != enet::Tcp::status::link) {
JUS_DEBUG("connect [STOP] ==> can not connect");
return;
}
m_interfaceClient = std::make_shared<jus::TcpString>();
if (m_interfaceClient == nullptr) {
JUS_ERROR("Can not allocate interface ...");
return;
}
m_interfaceClient->connect(this, &jus::Service::onClientData);
m_interfaceClient->setInterface(std::move(connection));
m_interfaceClient->connect();
jus::Future<bool> ret = m_interfaceClient->call("setMode", "BIN");
ret.wait();
if (ret.get() == false) {
JUS_ERROR("Can not communicate with the gateway in Binary mode ... STAY in JSON");
} else {
JUS_INFO("Change mode in Binary");
m_interfaceClient->setMode(jus::connectionMode::modeBinary);
}
ret = m_interfaceClient->call("connect-service", _serviceName);
ret.wait();
if (ret.get() == false) {
JUS_ERROR("Can not configure the interface for the service with the current name ...");
m_interfaceClient->disconnect();
return;
}
JUS_DEBUG("connect [STOP]");
}
void jus::Service::disconnect(){
JUS_DEBUG("disconnect [START]");
if (m_interfaceClient != nullptr) {
m_interfaceClient->disconnect();
m_interfaceClient.reset();
} else {
JUS_VERBOSE("Nothing to disconnect ...");
}
JUS_DEBUG("disconnect [STOP]");
}
bool jus::Service::GateWayAlive() {
if (m_interfaceClient == nullptr) {
return false;
}
return m_interfaceClient->isActive();
}
void jus::Service::pingIsAlive() {
if (std::chrono::steady_clock::now() - m_interfaceClient->getLastTimeSend() >= std::chrono::seconds(30)) {
/*
ejson::Object tmpp;
tmpp.add("event", ejson::String("IS-ALIVE"));
m_interfaceClient->writeJson(tmpp);
*/
}
}
void jus::Service::callBinary(uint32_t _transactionId, jus::Buffer& _obj) {
if (_obj.getType() == jus::Buffer::typeMessage::event) {
/*
std::string event = _obj["event"].toString().get();
if (event == "IS-ALIVE") {
// Gateway just aswer a keep alive information ...
// Nothing to do ...
} else {
JUS_ERROR("Unknow event: '" << event << "'");
}
*/
JUS_ERROR("Unknow event: '...'");
return;
}
if (_obj.getType() == jus::Buffer::typeMessage::answer) {
JUS_ERROR("Local Answer: '...'");
return;
}
//if (_obj.getType() == jus::Buffer::typeMessage::event) {
uint32_t clientId = _obj.getClientId();
std::string callFunction = _obj.getCall();
if (callFunction[0] == '_') {
if (callFunction == "_new") {
std::string userName = _obj.getParameter<std::string>(0);
std::string clientName = _obj.getParameter<std::string>(1);
std::vector<std::string> clientGroup = _obj.getParameter<std::vector<std::string>>(2);
clientConnect(clientId, userName, clientName, clientGroup);
} else if (callFunction == "_delete") {
clientDisconnect(clientId);
}
m_interfaceClient->answerValue(_transactionId, true, clientId);
return;
} else if (isFunctionAuthorized(clientId, callFunction) == true) {
callBinary2(_transactionId, clientId, callFunction, _obj);
return;
} else {
m_interfaceClient->answerError(_transactionId, "NOT-AUTHORIZED-FUNCTION", "", clientId);
return;
}
}

View File

@ -1,254 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h>
#include <ejson/ejson.h>
#include <jus/AbstractFunctionTypeDirect.h>
#include <jus/AbstractFunctionTypeClass.h>
#include <jus/debug.h>
#include <jus/RemoteProcessCall.h>
#include <jus/Future.h>
namespace jus {
class ClientProperty {
public:
ClientProperty(const std::string& _clientName="", const std::vector<std::string>& _groups = std::vector<std::string>()) :
m_name(_clientName),
m_groups(_groups) {
}
private:
std::string m_name;
public:
void setName(const std::string& _name) {
m_name = _name;
}
const std::string& getName() {
return m_name;
}
private:
std::vector<std::string> m_groups;
public:
void setGroups(std::vector<std::string> _groups) {
m_groups = _groups;
}
const std::vector<std::string>& getGroups() {
return m_groups;
}
private:
std::vector<std::string> m_listAthorizedFunction;
public:
void addAuthorized(const std::string& _funcName) {
m_listAthorizedFunction.push_back(_funcName);
}
bool isFunctionAuthorized(const std::string& _funcName) {
return std::find(m_listAthorizedFunction.begin(), m_listAthorizedFunction.end(), _funcName) != m_listAthorizedFunction.end();
}
};
}
namespace jus {
class Service : public eproperty::Interface, public jus::RemoteProcessCall {
protected:
std::mutex m_mutex;
public:
eproperty::Value<std::string> propertyIp;
eproperty::Value<uint16_t> propertyPort;
protected:
ememory::SharedPtr<jus::TcpString> m_interfaceClient;
uint32_t m_id;
std::vector<std::string> m_newData;
std::vector<jus::FutureCall> m_callMultiData;
public:
Service();
virtual ~Service();
void connect(const std::string& _serviceName, uint32_t _numberRetry = 1);
void disconnect();
private:
void onClientData(jus::Buffer& _value);
public:
void pingIsAlive();
bool GateWayAlive();
private:
void onPropertyChangeIp();
void onPropertyChangePort();
/**
* @brief A extern client connect on specific user
* @param[in] _clientId Source session Id on the client
* @param[in] _userName User name of the client to connect
* @todo Set a relur like ==> service not availlable / service close / service maintenance / service right reject
*/
virtual void clientConnect(uint64_t _clientId, const std::string& _userName, const std::string& _clientName, const std::vector<std::string>& _groups) = 0;
virtual void clientDisconnect(uint64_t _clientId) = 0;
// Genenric function call:
void callBinary(uint32_t _transactionId, jus::Buffer& _obj);
virtual void callBinary2(uint32_t _transactionId, uint64_t _clientId, const std::string& _call, jus::Buffer& _obj) = 0;
std::vector<std::string> getExtention();
public:
// Add Local fuction (depend on this class)
template<class JUS_RETURN_VALUE,
class JUS_CLASS_TYPE,
class... JUS_FUNC_ARGS_TYPE>
void advertise(std::string _name,
JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args),
const std::string& _desc = "") {
_name = "srv." + _name;
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() == _name) {
JUS_ERROR("Advertise function already bind .. ==> can not be done...: '" << _name << "'");
return;
}
}
AbstractFunction* tmp = createAbstractFunctionClass(_name, _desc, _func);
if (tmp == nullptr) {
JUS_ERROR("can not create abstract function ... '" << _name << "'");
return;
}
tmp->setType(jus::AbstractFunction::type::service);
JUS_INFO("Add function '" << _name << "' in local mode");
m_listFunction.push_back(tmp);
}
};
template<class JUS_TYPE_SERVICE, class JUS_USER_ACCESS>
class ServiceType : public jus::Service {
private:
JUS_USER_ACCESS& m_getUserInterface;
// no need of shared_ptr or unique_ptr (if service die all is lost and is client die, the gateway notify us...)
std::map<uint64_t, std::pair<ememory::SharedPtr<ClientProperty>, ememory::SharedPtr<JUS_TYPE_SERVICE>>> m_interface;
public:
template<class JUS_RETURN_VALUE,
class JUS_CLASS_TYPE,
class... JUS_FUNC_ARGS_TYPE>
void advertise(const std::string& _name,
JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args),
const std::string& _desc = "") {
if (etk::start_with(_name, "srv.") == true) {
JUS_ERROR("Advertise function start with 'srv.' is not permited ==> only allow for internal service: '" << _name << "'");
return;
}
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
if (it->getName() == _name) {
JUS_ERROR("Advertise function already bind .. ==> can not be done...: '" << _name << "'");
return;
}
}
AbstractFunction* tmp = createAbstractFunctionClass(_name, _desc, _func);
if (tmp == nullptr) {
JUS_ERROR("can not create abstract function ... '" << _name << "'");
return;
}
tmp->setType(jus::AbstractFunction::type::object);
JUS_INFO("Add function '" << _name << "' in object mode");
m_listFunction.push_back(tmp);
}
ServiceType(JUS_USER_ACCESS& _interface):
m_getUserInterface(_interface) {
}
bool isFunctionAuthorized(uint64_t _clientId, const std::string& _funcName) {
auto it = m_interface.find(_clientId);
if (it == m_interface.end()) {
return false;
}
return it->second.first->isFunctionAuthorized(_funcName);
}
void clientConnect(uint64_t _clientId, const std::string& _userName, const std::string& _clientName, const std::vector<std::string>& _groups) {
std::unique_lock<std::mutex> lock(m_mutex);
JUS_DEBUG("connect: " << _clientId << " to '" << _userName << "'");
JUS_DEBUG(" client name='" << _clientName << "'");
JUS_DEBUG(" groups=" << etk::to_string(_groups));
ememory::SharedPtr<ClientProperty> tmpProperty = std::make_shared<ClientProperty>(_clientName, _groups);
ememory::SharedPtr<JUS_TYPE_SERVICE> tmpSrv = std::make_shared<JUS_TYPE_SERVICE>(m_getUserInterface.getUser(_userName), tmpProperty);
m_interface.insert(std::make_pair(_clientId, std::make_pair(tmpProperty, tmpSrv)));
// enable list of function availlable:
for (auto &it : m_listFunction) {
if (it == nullptr) {
continue;
}
tmpProperty->addAuthorized(it->getName());
}
}
void clientDisconnect(uint64_t _clientId) {
std::unique_lock<std::mutex> lock(m_mutex);
JUS_DEBUG("disconnect: " << _clientId);
auto it = m_interface.find(_clientId);
if (it == m_interface.end()) {
JUS_WARNING("disconnect ==> Not find Client ID " << _clientId);
// noting to do ==> user never conected.
return;
}
m_interface.erase(it);
}
void clientSetName(uint64_t _clientId, const std::string& _clientName) {
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_interface.find(_clientId);
if (it == m_interface.end()) {
JUS_ERROR("Change the client property but client was not created ...");
return;
}
it->second.first->setName(_clientName);
}
void clientSetGroup(uint64_t _clientId, const std::vector<std::string>& _clientGroups) {
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_interface.find(_clientId);
if (it == m_interface.end()) {
JUS_ERROR("Change the client property but client was not created ...");
return;
}
it->second.first->setGroups(_clientGroups);
}
void callBinary2(uint32_t _transactionId, uint64_t _clientId, const std::string& _call, jus::Buffer& _obj) {
auto it = m_interface.find(_clientId);
if (it == m_interface.end()) {
m_interfaceClient->answerError(_transactionId, "CLIENT-UNKNOW", "", _clientId);
return;
}
for (auto &it2 : m_listFunction) {
if (it2 == nullptr) {
continue;
}
if (it2->getName() != _call) {
continue;
}
switch (it2->getType()) {
case jus::AbstractFunction::type::object: {
JUS_TYPE_SERVICE* elem = it->second.second.get();
it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)elem);
return;
}
case jus::AbstractFunction::type::local: {
it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)((RemoteProcessCall*)this));
return;
}
case jus::AbstractFunction::type::service: {
it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)this);
return;
}
case jus::AbstractFunction::type::global: {
it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, nullptr);
return;
}
case jus::AbstractFunction::type::unknow:
JUS_ERROR("Can not call unknow type ...");
break;
}
}
m_interfaceClient->answerError(_transactionId, "FUNCTION-UNKNOW", "", _clientId);
return;
}
};
}

View File

@ -1,53 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/ServiceRemote.h>
#include <jus/Client.h>
jus::ServiceRemote::ServiceRemote(ememory::SharedPtr<jus::TcpString> _clientLink, const std::string& _name):
m_interfaceClient(_clientLink),
m_name(_name),
m_serviceId(0),
m_isLinked(false) {
if (m_interfaceClient == nullptr) {
return;
}
// little hack : Call the service manager with the service ID=0 ...
jus::Future<uint32_t> ret = call("link", _name);
ret.wait();
if (ret.hasError() == true) {
JUS_WARNING("Can not link with the service named: '" << _name << "' ==> link error");
return;
}
m_isLinked = true;
m_serviceId = ret.get();
}
jus::ServiceRemote::~ServiceRemote() {
if (m_isLinked == true) {
uint32_t tmpLocalService = m_serviceId;
// little hack : Call the service manager with the service ID=0 ...
m_serviceId = 0;
jus::Future<bool> ret = call("unlink", tmpLocalService);
ret.wait();
if (ret.hasError() == true) {
JUS_WARNING("Can not unlink with the service id: '" << tmpLocalService << "' ==> link error");
m_serviceId = tmpLocalService;
return;
}
if (ret.get() == true) {
m_isLinked = false;
} else {
JUS_ERROR("Can not unlink with this service ....");
m_serviceId = tmpLocalService;
}
}
}
bool jus::ServiceRemote::exist() {
return m_isLinked;
}

View File

@ -1,51 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h>
#include <ejson/ejson.h>
#include <jus/debug.h>
#include <jus/AbstractFunction.h>
#include <jus/ServiceRemote.h>
#include <jus/Future.h>
#include <jus/connectionMode.h>
#include <jus/TcpString.h>
namespace jus {
class Client;
class ServiceRemote {
private:
ememory::SharedPtr<jus::TcpString> m_interfaceClient;
std::string m_name;
uint32_t m_serviceId;
bool m_isLinked;
public:
ServiceRemote(ememory::SharedPtr<jus::TcpString> _clientLink, const std::string& _name);
~ServiceRemote();
bool exist();
public:
template<class... _ARGS>
jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) {
if (m_interfaceClient == nullptr) {
jus::Buffer ret;
ret.addError("NULLPTR", "call " + _functionName + " with no interface open");
return jus::FutureBase(0, true, ret);
}
return m_interfaceClient->callService(m_serviceId, _functionName, _args...);
}
template<class... _ARGS>
jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
if (m_interfaceClient == nullptr) {
jus::Buffer ret;
ret.addError("NULLPTR", "call " + _functionName + " with no interface open");
return jus::FutureBase(0, true, ret, _callback);
}
return m_interfaceClient->callServiceAction(m_serviceId, _functionName, _args..., _callback);
}
};
}

View File

@ -1,617 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/TcpString.h>
#include <jus/debug.h>
#include <ethread/tools.h>
#include <unistd.h>
jus::TcpString::TcpString(enet::Tcp _connection) :
m_connection(std::move(_connection)),
m_thread(nullptr),
m_observerElement(nullptr),
m_threadAsync(nullptr) {
m_threadRunning = false;
m_threadAsyncRunning = false;
m_interfaceMode = jus::connectionMode::modeJson;
m_transmissionId = 1;
}
jus::TcpString::TcpString() :
m_connection(),
m_thread(nullptr),
m_observerElement(nullptr),
m_threadAsync(nullptr) {
m_threadRunning = false;
m_threadAsyncRunning = false;
m_interfaceMode = jus::connectionMode::modeJson;
m_transmissionId = 1;
}
void jus::TcpString::setInterface(enet::Tcp _connection) {
m_connection = std::move(_connection);
}
jus::TcpString::~TcpString() {
disconnect();
}
void jus::TcpString::setInterfaceName(const std::string& _name) {
ethread::setName(*m_thread, "Tcp-" + _name);
}
void jus::TcpString::threadCallback() {
ethread::setName("TcpString-input");
// get datas:
while ( m_threadRunning == true
&& m_connection.getConnectionStatus() == enet::Tcp::status::link) {
// READ section data:
read();
}
m_threadRunning = false;
JUS_DEBUG("End of thread");
}
bool jus::TcpString::isActive() const {
return m_threadRunning;
}
void jus::TcpString::connect(bool _async){
JUS_DEBUG("connect [START]");
m_threadRunning = true;
m_thread = new std::thread([&](void *){ this->threadCallback();}, nullptr);
if (m_thread == nullptr) {
m_threadRunning = false;
JUS_ERROR("creating callback thread!");
return;
}
m_threadAsyncRunning = true;
m_threadAsync = new std::thread([&](void *){ this->threadAsyncCallback();}, nullptr);
if (m_threadAsync == nullptr) {
m_threadAsyncRunning = false;
JUS_ERROR("creating async sender thread!");
return;
}
while ( _async == false
&& m_threadRunning == true
&& m_connection.getConnectionStatus() != enet::Tcp::status::link) {
usleep(50000);
}
//ethread::setPriority(*m_receiveThread, -6);
if (_async == true) {
JUS_DEBUG("connect [STOP] async mode");
} else {
JUS_DEBUG("connect [STOP]");
}
}
void jus::TcpString::disconnect(bool _inThreadStop){
JUS_DEBUG("disconnect [START]");
m_threadRunning = false;
m_threadAsyncRunning = false;
if (m_connection.getConnectionStatus() == enet::Tcp::status::link) {
uint32_t size = 0xFFFFFFFF;
m_connection.write(&size, 4);
}
if (m_connection.getConnectionStatus() != enet::Tcp::status::unlink) {
m_connection.unlink();
}
if (m_threadAsync != nullptr) {
m_threadAsync->join();
delete m_threadAsync;
m_threadAsync = nullptr;
}
if (_inThreadStop == false) {
if (m_thread != nullptr) {
m_thread->join();
delete m_thread;
m_thread = nullptr;
}
}
JUS_DEBUG("disconnect [STOP]");
}
int32_t jus::TcpString::writeJson(ejson::Object& _data) {
JUS_DEBUG("Send JSON '" << _data.generateHumanString() << "'");
if (m_threadRunning == false) {
return -2;
}
m_lastSend = std::chrono::steady_clock::now();
m_connection.write("J", 1);
std::string tmpData = _data.generateMachineString();
uint32_t dataSize = tmpData.size();
m_connection.write(&dataSize, sizeof(uint32_t));
m_connection.write(&tmpData[0], tmpData.size());
return 1;
}
int32_t jus::TcpString::writeBinary(jus::Buffer& _data) {
_data.prepare();
JUS_DEBUG("Send BINARY '" << _data.toJson().generateHumanString() << "'");
if (m_threadRunning == false) {
return -2;
}
m_lastSend = std::chrono::steady_clock::now();
m_connection.write("B", 1);
const uint8_t* data = nullptr;
uint32_t dataSize = 0;
data = _data.getHeader();
dataSize = _data.getHeaderSize();
m_connection.write(data, dataSize);
data = _data.getParam();
dataSize = _data.getParamSize();
m_connection.write(data, dataSize);
data = _data.getData();
dataSize = _data.getDataSize();
m_connection.write(data, dataSize);
return 1;
}
void jus::TcpString::read() {
JUS_VERBOSE("Read [START]");
if (m_threadRunning == false) {
JUS_DEBUG("Read [END] Disconected");
return;
}
// TODO : Do it better with a correct way to check data size ...
JUS_VERBOSE("Read [START]");
uint8_t type = 0;
int32_t len = m_connection.read(&type, 1);
if (len == 0) {
JUS_ERROR("Protocol error occured ==> No datas ...");
} else {
if (type == 'G') { // Get (This is a websocket first connection
std::string out = "G";
JUS_VERBOSE("Read HTTP first connection of a websocket [START]");
// get all data while we find "User-Agent **********\n" ==> After this is a TCP connection (need to answear)
while (true) {
int32_t len = m_connection.read(&type, 1);
if (len == 0) {
continue;
}
out += char(type);
JUS_INFO(" ** " << out);
if ( out[out.size()-1] == '\n'
&& out[out.size()-2] == '\n') {
break;
}
if (char(type) == '\n') {
if (out.find("User-Agent") != std::string::npos) {
break;
}
}
}
JUS_INFO("Find WebSocket ...");
JUS_INFO("data='" << out << "'");
if ( out[0] != 'G'
&& out[1] != 'E'
&& out[2] != 'T') {
std::string ret = "HTTP/1.0 400 Bad Request\n";
ret += "Content-Type : application/octet-stream\n";
ret += "\n";
m_connection.write(&ret[0], ret.size());
disconnect(true);
} else {
std::string ret = "HTTP/1.0 200 OK\n";
ret += "Content-Type : application/octet-stream\n";
ret += "\n";
m_connection.write(&ret[0], ret.size());
}
JUS_VERBOSE("Read HTTP first connection of a websocket [STOP]");
} else if (type == 'B') { // binary
// Binary mode ... start with the lenght of the stream
JUS_VERBOSE("Read Binary [START]");
uint32_t size = 0;
len = m_connection.read(&size, 4);
if (len != 4) {
JUS_ERROR("Protocol error occured ...");
} else {
if (size == -1) {
JUS_WARNING("Remote close connection");
m_threadRunning = false;
//m_connection.unlink();
} else {
int64_t offset = 0;
m_buffer.resize(size);
while (offset != size) {
len = m_connection.read(&m_buffer[offset], size-offset);
offset += len;
if (len == 0) {
JUS_WARNING("Read No data");
}
}
jus::Buffer dataRaw;
dataRaw.composeWith(m_buffer);
newBuffer(dataRaw);
}
}
JUS_VERBOSE("ReadRaw [STOP]");
} else if ( type == 'X' // XML
|| type == 'J' // JSON
) {
JUS_VERBOSE("Read sized String [START]");
// XML/JSON mode ... start with the lenght of the stream
std::string out;
uint32_t size = 0;
len = m_connection.read(&size, 4);
if (len != 4) {
JUS_ERROR("Protocol error occured ...");
} else {
if (size == -1) {
JUS_WARNING("Remote close connection");
m_threadRunning = false;
//m_connection.unlink();
} else {
int64_t offset = 0;
out.resize(size);
while (offset != size) {
len = m_connection.read(&out[offset], size-offset);
offset += len;
if (len == 0) {
JUS_WARNING("Read No data");
}
}
jus::Buffer dataRaw;
dataRaw.composeWith(out);
newBuffer(dataRaw);
}
}
JUS_VERBOSE("Read sized String [STOP]");
} else if (type == '{') {
// JSON Raw mode ... Finish with a \0
// TODO: m_dataBuffer
} else if (type == '<') {
// XML Raw mode ... Finish with a \0
// TODO : m_dataBuffer
}
}
}
void jus::TcpString::newBuffer(jus::Buffer& _buffer) {
JUS_VERBOSE("Receive Binary :" << _buffer.toJson().generateHumanString());
jus::FutureBase future;
uint64_t tid = _buffer.getTransactionId();
if (tid == 0) {
JUS_ERROR("Get a Protocol error ... No ID ...");
/*
if (obj["error"].toString().get() == "PROTOCOL-ERROR") {
JUS_ERROR("Get a Protocol error ...");
std::unique_lock<std::mutex> lock(m_mutex);
for (auto &it : m_pendingCall) {
if (it.isValid() == false) {
continue;
}
it.setAnswer(obj);
}
m_pendingCall.clear();
} else {
JUS_ERROR("call with no ID ==> error ...");
}
*/
return;
}
{
std::unique_lock<std::mutex> lock(m_pendingCallMutex);
auto it = m_pendingCall.begin();
while (it != m_pendingCall.end()) {
if (it->second.isValid() == false) {
it = m_pendingCall.erase(it);
continue;
}
if (it->second.getTransactionId() != tid) {
++it;
continue;
}
future = it->second;
break;
}
}
if (future.isValid() == false) {
// not a pending call ==> simple event or call ...
if (m_observerElement != nullptr) {
m_observerElement(_buffer);
}
return;
}
bool ret = future.setAnswer(_buffer);
if (ret == true) {
std::unique_lock<std::mutex> lock(m_pendingCallMutex);
auto it = m_pendingCall.begin();
while (it != m_pendingCall.end()) {
if (it->second.isValid() == false) {
it = m_pendingCall.erase(it);
continue;
}
if (it->second.getTransactionId() != tid) {
++it;
continue;
}
it = m_pendingCall.erase(it);
break;
}
}
}
void jus::TcpString::threadAsyncCallback() {
ethread::setName("Async-sender");
// get datas:
while ( m_threadAsyncRunning == true
&& m_connection.getConnectionStatus() == enet::Tcp::status::link) {
if (m_threadAsyncList.size() == 0) {
usleep(10000);
continue;
}
std::unique_lock<std::mutex> lock(m_threadAsyncMutex);
auto it = m_threadAsyncList.begin();
while (it != m_threadAsyncList.end()) {
bool ret = (*it)(this);
if (ret == true) {
// Remove it ...
it = m_threadAsyncList.erase(it);
} else {
++it;
}
}
}
m_threadRunning = false;
JUS_DEBUG("End of thread");
}
class SendAsyncJson {
private:
std::vector<jus::ActionAsyncClient> m_async;
uint64_t m_transactionId;
uint32_t m_serviceId;
uint32_t m_partId;
public:
SendAsyncJson(uint64_t _transactionId, const uint32_t& _serviceId, const std::vector<jus::ActionAsyncClient>& _async) :
m_async(_async),
m_transactionId(_transactionId),
m_serviceId(_serviceId),
m_partId(1) {
}
bool operator() (jus::TcpString* _interface){
auto it = m_async.begin();
while (it != m_async.end()) {
bool ret = (*it)(_interface, m_serviceId, m_transactionId, m_partId);
if (ret == true) {
// Remove it ...
it = m_async.erase(it);
} else {
++it;
}
m_partId++;
}
if (m_async.size() == 0) {
ejson::Object obj;
if (m_serviceId != 0) {
obj.add("service", ejson::Number(m_serviceId));
}
obj.add("id", ejson::Number(m_transactionId));
obj.add("part", ejson::Number(m_partId));
obj.add("finish", ejson::Boolean(true));
_interface->writeJson(obj);
return true;
}
return false;
}
};
jus::FutureBase jus::TcpString::callJson(uint64_t _transactionId,
ejson::Object _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback,
const uint32_t& _serviceId) {
JUS_VERBOSE("Send JSON [START] ");
if (isActive() == false) {
jus::Buffer obj;
obj.setType(jus::Buffer::typeMessage::answer);
obj.addError("NOT-CONNECTED", "Client interface not connected (no TCP)");
return jus::FutureBase(_transactionId, true, obj, _callback);
}
jus::FutureBase tmpFuture(_transactionId, _callback);
{
std::unique_lock<std::mutex> lock(m_pendingCallMutex);
m_pendingCall.push_back(std::make_pair(uint64_t(0), tmpFuture));
}
if (_async.size() != 0) {
_obj.add("part", ejson::Number(0));
}
writeJson(_obj);
if (_async.size() != 0) {
addAsync(SendAsyncJson(_transactionId, _serviceId, _async));
}
JUS_VERBOSE("Send JSON [STOP]");
return tmpFuture;
}
class SendAsyncBinary {
private:
std::vector<jus::ActionAsyncClient> m_async;
uint64_t m_transactionId;
uint32_t m_serviceId;
uint32_t m_partId;
public:
SendAsyncBinary(uint64_t _transactionId, const uint32_t& _serviceId, const std::vector<jus::ActionAsyncClient>& _async) :
m_async(_async),
m_transactionId(_transactionId),
m_serviceId(_serviceId),
m_partId(1) {
}
bool operator() (jus::TcpString* _interface){
auto it = m_async.begin();
while (it != m_async.end()) {
bool ret = (*it)(_interface, m_serviceId, m_transactionId, m_partId);
if (ret == true) {
// Remove it ...
it = m_async.erase(it);
} else {
++it;
}
m_partId++;
}
if (m_async.size() == 0) {
jus::Buffer obj;
obj.setServiceId(m_serviceId);
obj.setTransactionId(m_transactionId);
obj.setPartId(m_partId);
obj.setPartFinish(true);
_interface->writeBinary(obj);
return true;
}
return false;
}
};
jus::FutureBase jus::TcpString::callBinary(uint64_t _transactionId,
jus::Buffer& _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback,
const uint32_t& _serviceId) {
JUS_VERBOSE("Send Binary [START] ");
if (isActive() == false) {
jus::Buffer obj;
obj.setType(jus::Buffer::typeMessage::answer);
obj.addError("NOT-CONNECTED", "Client interface not connected (no TCP)");
return jus::FutureBase(_transactionId, true, obj, _callback);
}
jus::FutureBase tmpFuture(_transactionId, _callback);
{
std::unique_lock<std::mutex> lock(m_pendingCallMutex);
m_pendingCall.push_back(std::make_pair(uint64_t(0), tmpFuture));
}
if (_async.size() != 0) {
_obj.setPartFinish(false);
} else {
_obj.setPartFinish(true);
}
writeBinary(_obj);
if (_async.size() != 0) {
addAsync(SendAsyncBinary(_transactionId, _serviceId, _async));
}
JUS_VERBOSE("Send Binary [STOP]");
return tmpFuture;
}
jus::FutureBase jus::TcpString::callForward(uint32_t _clientId,
jus::Buffer& _buffer,
uint64_t _singleReferenceId,
jus::FutureData::ObserverFinish _callback) {
JUS_VERBOSE("Call Forward [START]");
//jus::FutureBase ret = callBinary(id, _Buffer, async, _callback);
//ret.setSynchronous();
if (isActive() == false) {
jus::Buffer obj;
obj.setType(jus::Buffer::typeMessage::answer);
obj.addError("NOT-CONNECTED", "Client interface not connected (no TCP)");
return jus::FutureBase(0, true, obj, _callback);
}
uint64_t id = getId();
_buffer.setTransactionId(id);
_buffer.setClientId(_clientId);
jus::FutureBase tmpFuture(id, _callback);
tmpFuture.setSynchronous();
{
std::unique_lock<std::mutex> lock(m_pendingCallMutex);
m_pendingCall.push_back(std::make_pair(_singleReferenceId, tmpFuture));
}
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object obj = _buffer.toJson();
writeJson(obj);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
writeBinary(_buffer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
JUS_VERBOSE("Send Forward [STOP]");
return tmpFuture;
}
void jus::TcpString::callForwardMultiple(uint32_t _clientId,
jus::Buffer& _buffer,
uint64_t _singleReferenceId){
// subMessage ... ==> try to forward message:
std::unique_lock<std::mutex> lock(m_pendingCallMutex);
for (auto &itCall : m_pendingCall) {
JUS_INFO(" compare : " << itCall.first << " =?= " << _singleReferenceId);
if (itCall.first == _singleReferenceId) {
// Find element ==> transit it ...
_buffer.setTransactionId(itCall.second.getTransactionId());
_buffer.setClientId(_clientId);
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object obj = _buffer.toJson();
writeJson(obj);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
writeBinary(_buffer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
return;
}
}
JUS_ERROR("Can not transfer part of a message ...");
}
void jus::TcpString::answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorHelp, uint32_t _clientId) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("error", ejson::String(_errorValue));
answer.add("id", ejson::Number(_clientTransactionId));
if (_clientId != 0) {
answer.add("client-id", ejson::Number(_clientId));
}
answer.add("error-help", ejson::String(_errorHelp));
writeJson(answer);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.setClientId(_clientId);
answer.addError(_errorValue, _errorHelp);
writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void jus::TcpString::answerVoid(uint64_t _clientTransactionId, uint32_t _clientId) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("id", ejson::Number(_clientTransactionId));
if (_clientId != 0) {
answer.add("client-id", ejson::Number(_clientId));
}
answer.add("return", ejson::Null());
writeJson(answer);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.setClientId(_clientId);
answer.addParameter();
writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}

View File

@ -1,211 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <eproperty/Value.h>
#include <esignal/Signal.h>
#include <jus/Buffer.h>
#include <enet/Tcp.h>
#include <thread>
#include <memory>
#include <jus/connectionMode.h>
#include <jus/AbstractFunction.h>
#include <jus/FutureBase.h>
namespace jus {
class TcpString : public eproperty::Interface {
private:
enet::Tcp m_connection;
std::thread* m_thread;
bool m_threadRunning;
uint16_t m_transmissionId;
uint16_t getId() {
return m_transmissionId++;
}
std::mutex m_pendingCallMutex;
std::vector<std::pair<uint64_t, jus::FutureBase>> m_pendingCall;
protected:
enum jus::connectionMode m_interfaceMode;
public:
enum jus::connectionMode getMode() {
return m_interfaceMode;
}
void setMode(enum jus::connectionMode _mode) {
m_interfaceMode = _mode;
}
std::vector<uint8_t> m_buffer;
std::vector<uint8_t> m_temporaryBuffer;
std::chrono::steady_clock::time_point m_lastReceive;
std::chrono::steady_clock::time_point m_lastSend;
public:
using Observer = std::function<void(jus::Buffer&)>; //!< Define an Observer: function pointer
Observer m_observerElement;
/**
* @brief Connect an function member on the signal with the shared_ptr object.
* @param[in] _class shared_ptr Object on whe we need to call ==> the object is get in keeped in weak_ptr.
* @param[in] _func Function to call.
* @param[in] _args Argument optinnal the user want to add.
*/
template<class CLASS_TYPE>
void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) {
m_observerElement = [=](jus::Buffer& _value){
(*_class.*_func)(_value);
};
}
public:
TcpString();
TcpString(enet::Tcp _connection);
virtual ~TcpString();
void setInterface(enet::Tcp _connection);
void connect(bool _async = false);
void disconnect(bool _inThreadStop = false);
bool isActive() const;
void setInterfaceName(const std::string& _name);
int32_t writeJson(ejson::Object& _data);
int32_t writeBinary(jus::Buffer& _data);
std::string asyncRead();
private:
void read();
void newBuffer(jus::Buffer& _buffer);
private:
void threadCallback();
public:
const std::chrono::steady_clock::time_point& getLastTimeReceive() {
return m_lastReceive;
}
const std::chrono::steady_clock::time_point& getLastTimeSend() {
return m_lastSend;
}
private:
using ActionAsync = std::function<bool(TcpString* _interface)>;
std::mutex m_threadAsyncMutex;
std::thread* m_threadAsync;
bool m_threadAsyncRunning;
std::vector<ActionAsync> m_threadAsyncList;
private:
void threadAsyncCallback();
public:
void addAsync(ActionAsync _elem) {
std::unique_lock<std::mutex> lock(m_threadAsyncMutex);
m_threadAsyncList.push_back(_elem);
}
private:
jus::FutureBase callJson(uint64_t _transactionId,
ejson::Object _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback=nullptr,
const uint32_t& _service=0);
jus::FutureBase callBinary(uint64_t _transactionId,
jus::Buffer& _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback=nullptr,
const uint32_t& _service=0);
public: // section call direct
template<class... _ARGS>
jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) {
uint16_t id = getId();
std::vector<jus::ActionAsyncClient> asyncAction;
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncAction);
} else {
jus::Buffer callElem = jus::createBinaryCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncAction);
}
}
template<class... _ARGS>
jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
uint16_t id = getId();
std::vector<jus::ActionAsyncClient> asyncAction;
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncAction, _callback);
} else {
jus::Buffer callElem = jus::createBinaryCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncAction, _callback);
}
}
public: // section call with service ID / Client ID
template<class... _ARGS>
jus::FutureBase callService(uint32_t _serviceId, const std::string& _functionName, _ARGS&&... _args) {
uint16_t id = getId();
std::vector<jus::ActionAsyncClient> asyncActionToDo;
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCallService(asyncActionToDo, id, _serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncActionToDo);
} else {
jus::Buffer callElem = jus::createBinaryCallService(asyncActionToDo, id, _serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncActionToDo);
}
}
template<class... _ARGS>
jus::FutureBase callServiceAction(uint32_t _serviceId, const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
uint16_t id = getId();
std::vector<jus::ActionAsyncClient> asyncActionToDo;
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCallService(asyncActionToDo, id, _serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncActionToDo, _callback);
} else {
jus::Buffer callElem = jus::createBinaryCallService(asyncActionToDo, id, _serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncActionToDo, _callback);
}
}
template<class... _ARGS>
jus::FutureBase callClient(uint32_t _clientId,
const std::string& _functionName,
_ARGS&&... _args) {
return callService(_clientId, _functionName, _args...);
}
template<class... _ARGS>
jus::FutureBase callClientAction(uint32_t _clientId,
const std::string& _functionName,
_ARGS&&... _args,
jus::FutureData::ObserverFinish _callback) {
return callServiceAction(_clientId, _functionName, _args..., _callback);
}
jus::FutureBase callForward(uint32_t _clientId,
jus::Buffer& _Buffer,
uint64_t _singleReferenceId,
jus::FutureData::ObserverFinish _callback);
void callForwardMultiple(uint32_t _clientId,
jus::Buffer& _Buffer,
uint64_t _singleReferenceId);
public: // answers ...
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
template<class JUS_ARG>
void answerValue(uint64_t _clientTransactionId, JUS_ARG _value, uint32_t _clientId=0) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("id", ejson::Number(_clientTransactionId));
if (_clientId != 0) {
answer.add("client-id", ejson::Number(_clientId));
}
std::vector<jus::ActionAsyncClient> asyncAction;
answer.add("return", jus::convertToJson(asyncAction, -1, _value));
if (asyncAction.size() != 0) {
JUS_ERROR("ASYNC datas ... TODO ///");
}
writeJson(answer);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.setClientId(_clientId);
answer.addAnswer(_value);
writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void answerVoid(uint64_t _clientTransactionId, uint32_t _clientId=0);
void answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorComment="", uint32_t _clientId=0);
};
}

View File

View File

@ -1,12 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/debug.h>
int32_t jus::getLogId() {
static int32_t g_val = elog::registerInstance("jus");
return g_val;
}

View File

@ -1,40 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <elog/log.h>
namespace jus {
int32_t getLogId();
};
#define JUS_BASE(info,data) ELOG_BASE(jus::getLogId(),info,data)
#define JUS_PRINT(data) JUS_BASE(-1, data)
#define JUS_CRITICAL(data) JUS_BASE(1, data)
#define JUS_ERROR(data) JUS_BASE(2, data)
#define JUS_WARNING(data) JUS_BASE(3, data)
#ifdef DEBUG
#define JUS_INFO(data) JUS_BASE(4, data)
#define JUS_DEBUG(data) JUS_BASE(5, data)
#define JUS_VERBOSE(data) JUS_BASE(6, data)
#define JUS_TODO(data) JUS_BASE(4, "TODO : " << data)
#else
#define JUS_INFO(data) do { } while(false)
#define JUS_DEBUG(data) do { } while(false)
#define JUS_VERBOSE(data) do { } while(false)
#define JUS_TODO(data) do { } while(false)
#endif
#define JUS_ASSERT(cond,data) \
do { \
if (!(cond)) { \
JUS_CRITICAL(data); \
assert(!#cond); \
} \
} while (0)

View File

@ -1,134 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/mineType.h>
#include <jus/debug.h>
static std::vector<std::pair<std::string, std::string>> mineList = {
/* Video files */
{ "asf", "video/x-ms-asf"},
{ "avc", "video/avi"},
{ "avi", "video/avi"},
{ "dv", "video/x-dv"},
{ "divx", "video/avi"},
{ "wmv", "video/x-ms-wmv"},
{ "mjpg", "video/x-motion-jpeg"},
{ "mjpeg", "video/x-motion-jpeg"},
{ "mpeg", "video/mpeg"},
{ "mpg", "video/mpeg"},
{ "mpe", "video/mpeg"},
{ "mp2p", "video/mp2p"},
{ "vob", "video/mp2p"},
{ "mp2t", "video/mp2t"},
{ "m1v", "video/mpeg"},
{ "m2v", "video/mpeg2"},
{ "mpg2", "video/mpeg2"},
{ "mpeg2", "video/mpeg2"},
{ "m4v", "video/mp4"},
{ "m4p", "video/mp4"},
{ "mp4ps", "video/x-nerodigital-ps"},
{ "ts", "video/mpeg2"},
{ "ogm", "video/mpeg"},
{ "mkv", "video/x-matroska"},
{ "rmvb", "video/mpeg"},
{ "mov", "video/quicktime"},
{ "hdmov", "video/quicktime"},
{ "qt", "video/quicktime"},
{ "bin", "video/mpeg2"},
{ "iso", "video/mpeg2"},
/* Audio files */
{ "3gp", "audio/3gpp"},
{ "aac", "audio/x-aac"},
{ "ac3", "audio/x-ac3"},
{ "aif", "audio/aiff"},
{ "aiff", "audio/aiff"},
{ "at3p", "audio/x-atrac3"},
{ "au", "audio/basic"},
{ "snd", "audio/basic"},
{ "dts", "audio/x-dts"},
{ "rmi", "audio/midi"},
{ "mid", "audio/midi"},
{ "mp1", "audio/mp1"},
{ "mp2", "audio/mp2"},
{ "mp3", "audio/mpeg"},
{ "mp4", "audio/mp4"},
{ "m4a", "audio/mp4"},
{ "mka", "audio/x-matroska"},
{ "ogg", "audio/x-ogg"},
{ "wav", "audio/wav"},
{ "pcm", "audio/l16"},
{ "lpcm", "audio/l16"},
{ "l16", "audio/l16"},
{ "wma", "audio/x-ms-wma"},
{ "mka", "audio/x-matroska"},
{ "ra", "audio/x-pn-realaudio"},
{ "rm", "audio/x-pn-realaudio"},
{ "ram", "audio/x-pn-realaudio"},
{ "flac", "audio/x-flac"},
/* Images files */
{ "bmp", "image/bmp"},
{ "ico", "image/x-icon"},
{ "gif", "image/gif"},
{ "jpg", "image/jpeg"},
{ "jpeg", "image/jpeg"},
{ "jpe", "image/jpeg"},
{ "pcd", "image/x-ms-bmp"},
{ "png", "image/png"},
{ "pnm", "image/x-portable-anymap"},
{ "ppm", "image/x-portable-pixmap"},
{ "qti", "image/x-quicktime"},
{ "qtf", "image/x-quicktime"},
{ "qtif", "image/x-quicktime"},
{ "tif", "image/tiff"},
{ "tiff", "image/tiff"},
/* Playlist files */
{ "pls", "audio/x-scpls"},
{ "m3u", "audio/mpegurl"},
{ "asx", "video/x-ms-asf"},
/* Subtitle Text files */
{ "srt", "text/srt"}, /* SubRip */
{ "ssa", "text/ssa"}, /* SubStation Alpha */
{ "stl", "text/srt"}, /* Spruce */
{ "psb", "text/psb"}, /* PowerDivX */
{ "pjs", "text/pjs"}, /* Phoenix Japanim */
{ "sub", "text/sub"}, /* MicroDVD */
{ "idx", "text/idx"}, /* VOBsub */
{ "dks", "text/dks"}, /* DKS */
{ "scr", "text/scr"}, /* MACsub */
{ "tts", "text/tts"}, /* TurboTitler */
{ "vsf", "text/vsf"}, /* ViPlay */
{ "zeg", "text/zeg"}, /* ZeroG */
{ "mpl", "text/mpl"}, /* MPL */
/* Miscellaneous text files */
{ "bup", "text/bup"}, /* DVD backup */
{ "ifo", "text/ifo"}, /* DVD information */
};
std::string jus::getMineType(const std::string& _extention) {
for (auto &it : mineList) {
if (it.first == _extention) {
return it.second;
}
}
JUS_ERROR(" try to cenvert mine type: " << _extention);
return "";
}
std::string jus::getExtention(const std::string& _mineType) {
for (auto &it : mineList) {
if (it.second == _mineType) {
return it.first;
}
}
JUS_ERROR(" try to cenvert extention: " << _mineType);
return "";
}

View File

@ -1,12 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/types.h>
namespace jus {
std::string getMineType(const std::string& _extention);
std::string getExtention(const std::string& _mineType);
};

1086
lutinMacro_zeus.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,13 @@
tools/system-user
tools/system-gateway
tools/picture
tools/gateway
tools/cli
tools/cli-video
tools/router
tools/service-user
tools/service-picture
tools/service-video
tools/service-server
tools/player-video
tools/package-base
tools/launcher
test/client
test/service1

View File

@ -1,87 +0,0 @@
#!/usr/bin/python
import lutin.module as module
import lutin.tools as tools
def get_type():
return "LIBRARY"
def get_desc():
return "Json micro-service"
def get_licence():
return "APACHE-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def get_version():
return [0,1,"dev"]
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_module_depend(['etk', 'enet', 'ememory', 'eproperty', 'esignal', 'ejson'])
my_module.add_src_file([
'jus/debug.cpp'
])
my_module.add_path(tools.get_current_path(__file__))
my_module.add_src_file([
'jus/AbstractFunction.cpp',
'jus/AbstractFunctionTypeDirect.cpp',
'jus/AbstractFunctionTypeClass.cpp',
'jus/FutureBase.cpp',
'jus/Future.cpp',
'jus/File.cpp',
'jus/Buffer.cpp',
'jus/BufferConvertBinaryToJson.cpp',
'jus/ParamType.cpp',
'jus/Client.cpp',
'jus/GateWay.cpp',
'jus/GateWayService.cpp',
'jus/GateWayClient.cpp',
'jus/RemoteProcessCall.cpp',
'jus/Service.cpp',
'jus/ServiceRemote.cpp',
'jus/TcpString.cpp',
'jus/mineType.cpp',
])
my_module.add_header_file([
'jus/AbstractFunction.h',
'jus/AbstractFunctionTypeDirect.h',
'jus/AbstractFunctionTypeClass.h',
'jus/FutureData.h',
'jus/FutureBase.h',
'jus/Future.h',
'jus/File.h',
'jus/Buffer.h',
'jus/connectionMode.h',
'jus/ParamType.h',
'jus/debug.h',
'jus/Client.h',
'jus/GateWay.h',
'jus/GateWayService.h',
'jus/GateWayClient.h',
'jus/RemoteProcessCall.h',
'jus/Service.h',
'jus/ServiceRemote.h',
'jus/TcpString.h',
'jus/mineType.h',
])
if target.config["compilator"] == "clang":
my_module.add_export_flag('c++', "-Wno-unsequenced")
# build in C++ mode
my_module.compile_version("c++", 2011)
return my_module

144
lutin_zeus.py Normal file
View File

@ -0,0 +1,144 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
import lutin.macro as macro
def get_type():
return "LIBRARY"
def get_desc():
return "Zeus ewol micro-service"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return "authors.txt"
def get_version():
return "version.txt"
def configure(target, my_module):
my_module.add_depend([
'etk',
'enet',
'ememory',
'eproperty',
'echrono'
])
my_module.add_src_file([
'zeus/debug.cpp'
])
my_module.add_path(".")
# Future and promise interface
my_module.add_src_file([
'zeus/FutureBase.cpp',
'zeus/Future.cpp',
'zeus/Promise.cpp',
'zeus/FutureGroup.cpp',
])
my_module.add_header_file([
'zeus/Promise.hpp',
'zeus/FutureBase.hpp',
'zeus/Future.hpp',
'zeus/FutureGroup.hpp',
])
# messaging interface
my_module.add_src_file([
'zeus/message/Message.cpp',
'zeus/message/Parameter.cpp',
'zeus/message/Call.cpp',
'zeus/message/Answer.cpp',
'zeus/message/Data.cpp',
'zeus/message/Event.cpp',
'zeus/message/Flow.cpp',
'zeus/message/Parameter_addParameter.cpp',
'zeus/message/Parameter_getParameter.cpp',
'zeus/message/ParamType.cpp',
'zeus/message/type.cpp',
])
my_module.add_header_file([
'zeus/message/Message.hpp',
'zeus/message/Parameter.hpp',
'zeus/message/Call.hpp',
'zeus/message/Answer.hpp',
'zeus/message/Data.hpp',
'zeus/message/Event.hpp',
'zeus/message/Flow.hpp',
'zeus/message/ParamType.hpp',
'zeus/message/type.hpp',
])
# complexe object interface
my_module.add_src_file([
'zeus/Object.cpp',
'zeus/ObjectIntrospect.cpp',
'zeus/ObjectRemote.cpp',
'zeus/Proxy.cpp',
])
my_module.add_header_file([
'zeus/Object.hpp',
'zeus/ObjectIntrospect.hpp',
'zeus/ObjectRemote.hpp',
'zeus/Proxy.hpp',
])
# other ...
my_module.add_src_file([
'zeus/zeus.cpp',
'zeus/AbstractFunction.cpp',
'zeus/Raw.cpp',
'zeus/Client.cpp',
'zeus/RemoteProcessCall.cpp',
'zeus/WebObj.cpp',
'zeus/WebServer.cpp',
'zeus/mineType.cpp',
])
my_module.add_header_file([
'zeus/Raw.hpp',
'zeus/zeus.hpp',
'zeus/ActionNotification.hpp',
'zeus/AbstractFunction.hpp',
'zeus/AbstractFunctionTypeDirect.hpp',
'zeus/AbstractFunctionTypeClass.hpp',
'zeus/debug.hpp',
'zeus/Client.hpp',
'zeus/RemoteProcessCall.hpp',
'zeus/WebObj.hpp',
'zeus/WebServer.hpp',
'zeus/mineType.hpp',
'zeus/RemoteProperty.hpp',
])
# add basic object:
zeus_macro = macro.load_macro('zeus')
zeus_macro.parse_object_idl(my_module, 'zeus/zeus-File.obj.zeus.idl')
my_module.add_src_file([
'zeus/zeus-File.impl.cpp',
])
my_module.add_header_file([
'zeus/zeus-File.impl.hpp',
])
my_module.add_depend('ejson')
zeus_macro.parse_object_idl(my_module, 'zeus/zeus-Media.obj.zeus.idl')
my_module.add_src_file([
'zeus/zeus-Media.impl.cpp',
])
my_module.add_header_file([
'zeus/zeus-Media.impl.hpp',
])
if target.config["compilator"] == "clang":
my_module.add_flag('c++', "-Wno-unsequenced", export=True)
# build in C++ mode
my_module.compile_version("c++", 2011)
return True

View File

@ -1,12 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.h>
#include <appl/debug.hpp>
int32_t appl::getLogId() {
static int32_t g_val = elog::registerInstance("jus-test-client");
static int32_t g_val = elog::registerInstance("zeus-test-client");
return g_val;
}

View File

@ -1,11 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <elog/log.h>
#include <elog/log.hpp>
namespace appl {
int32_t getLogId();

View File

@ -0,0 +1,142 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <zeus/Client.hpp>
#include <zeus/ObjectRemote.hpp>
#include <zeus/mineType.hpp>
#include <etk/etk.hpp>
#include <zeus/zeus.hpp>
#include <etk/uri/uri.hpp>
#include <elog/elog.hpp>
#include <etk/stdTools.hpp>
#include <zeus/service/test/ProxyService1.hpp>
#include <zeus/ProxyFile.hpp>
#include <zeus/ObjectRemote.hpp>
#include <echrono/Steady.hpp>
#include <zeus/FutureGroup.hpp>
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
zeus::init(_argc, _argv);
zeus::Client client1;
etk::String fromUser = "test1";
etk::String toUser = "test1";
etk::String pass = "coucou";
for (int32_t iii=0; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) {
client1.propertyIp.set(etk::String(&data[5]));
} else if (etk::start_with(data, "--port=") == true) {
client1.propertyPort.set(etk::string_to_uint16_t(etk::String(&data[7])));
} else if (etk::start_with(data, "--from=") == true) {
fromUser = &data[7];
} else if (etk::start_with(data, "--to=") == true) {
toUser = &data[5];
} else if (etk::start_with(data, "--pass=") == true) {
pass = &data[7];
} else if (etk::start_with(data, "--tocken=") == true) {
pass = &data[9];
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)");
APPL_PRINT(" --port=XXX Server connection PORT (default: 1983)");
APPL_PRINT(" --from=XXX user that request connection");
APPL_PRINT(" --to=XXX destination user that we want to connect");
APPL_PRINT(" --pass=XXX pass or tocker to connect to the user");
return -1;
}
}
APPL_INFO("==================================");
APPL_INFO("== ZEUS test client start ==");
APPL_INFO("==================================");
if (fromUser == toUser) {
bool ret = client1.connect(fromUser, pass);
if (ret == false) {
APPL_ERROR(" ==> NOT Authentify with '" << toUser << "'");
return -1;
} else {
APPL_INFO(" ==> Authentify with '" << toUser << "'");
}
} else if (fromUser != "") {
bool ret = client1.connect(fromUser, toUser, pass);
if (ret == false) {
APPL_ERROR(" ==> NOT Connected to '" << toUser << "' with '" << fromUser << "'");
return -1;
} else {
APPL_INFO(" ==> Connected with '" << toUser << "'");
}
} else {
bool ret = client1.connect(toUser);
if (ret == false) {
APPL_ERROR(" ==> NOT Connected with 'anonymous' to '" << toUser << "'");
return -1;
} else {
APPL_INFO(" ==> Connected with 'anonymous' to '" << toUser << "'");
}
}
// Connect to ourself:
//client1.authentificate("coucou");
//bool retAuthentify = client1.call_b("authentify", "coucou");
APPL_INFO(" ----------------------------------");
APPL_INFO(" -- Get service count");
APPL_INFO(" ----------------------------------");
zeus::Future<int32_t> retNbService = client1.getServiceCount();
zeus::Future<etk::Vector<etk::String>> retServiceList = client1.getServiceList();
retNbService.wait();
APPL_INFO("Nb services = " << retNbService.get());
retServiceList.wait();
APPL_INFO("List services:");
for (auto &it: retServiceList.get()) {
APPL_INFO(" - " << it);
}
zeus::service::test::ProxyService1 srv = client1.getService("test-service1");
if (srv.exist() == false) {
APPL_ERROR("can not connect service ... 'test-service1'");
} else {
{
auto retCall = srv.getU32(11);
retCall.wait();
APPL_INFO("value = " << retCall.get());
}
{
int32_t lasNumberSend = 3000;
auto retCall = srv.doSomething(lasNumberSend);
int32_t lastValue=0;
retCall.onSignal(
[&](int32_t _value) {
APPL_DEBUG("getSignal : " << _value);
if (lastValue+1 != _value) {
APPL_ERROR("Send Event Wrong ORDER ... last=" << lastValue << " new=" << _value);
}
lastValue = _value;
});
while (lasNumberSend != lastValue) {
ethread::sleepMilliSeconds((50));
}
retCall.wait();
APPL_INFO("END (receive " << lastValue << " signals");
}
}
int32_t iii=0;
while (iii < 3) {
ethread::sleepMilliSeconds((500));
APPL_INFO("Appl in waiting ... " << iii << "/3");
iii++;
}
APPL_INFO("Request disconnect");
client1.disconnect();
APPL_INFO("==================================");
APPL_INFO("== ZEUS test client stop");
APPL_INFO("==================================");
return 0;
}

View File

@ -1,209 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <appl/debug.h>
#include <jus/Client.h>
#include <jus/ServiceRemote.h>
#include <jus/mineType.h>
#include <etk/etk.h>
#include <etk/os/FSNode.h>
#include <unistd.h>
#include <etk/stdTools.h>
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
jus::Client client1;
for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) {
client1.propertyIp.set(std::string(&data[5]));
} else if (etk::start_with(data, "--port=") == true) {
client1.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7])));
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)");
APPL_PRINT(" --port=XXX Server connection PORT (default: 1983)");
return -1;
}
}
APPL_INFO("==================================");
APPL_INFO("== JUS test client start ==");
APPL_INFO("==================================");
client1.connect("test1#atria-soft.com");
if (false) {
jus::Future<bool> retIdentify = client1.call("identify", "clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968");
retIdentify.wait();
if (retIdentify.get() == false) {
APPL_ERROR(" ==> NOT Connected with 'clientTest1#atria-soft.com'");
return -1;
} else {
APPL_INFO(" ==> Connected with 'clientTest1#atria-soft.com'");
}
} else if (true) {
jus::Future<bool> retIdentify = client1.call("auth", "coucou");
retIdentify.wait();
if (retIdentify.get() == false) {
APPL_ERROR(" ==> NOT Authentify with 'test1#atria-soft.com'");
return -1;
} else {
APPL_INFO(" ==> Authentify with 'test1#atria-soft.com'");
}
} else {
jus::Future<bool> retIdentify = client1.call("anonymous");
retIdentify.wait();
if (retIdentify.get() == false) {
APPL_ERROR(" ==> NOT Connected with 'anonymous'");
return -1;
} else {
APPL_INFO(" ==> Connected with 'anonymous'");
}
}
// Connect to ourself:
//client1.authentificate("coucou");
//bool retAuthentify = client1.call_b("authentify", "coucou");
APPL_INFO(" ----------------------------------");
APPL_INFO(" -- Get service count");
APPL_INFO(" ----------------------------------");
jus::Future<int32_t> retNbService = client1.call("getServiceCount");
retNbService.wait();
APPL_INFO("Nb services = " << retNbService.get());
jus::Future<std::vector<std::string>> retServiceList = client1.call("getServiceList");
retServiceList.wait();
APPL_INFO("List services:");
for (auto &it: retServiceList.get()) {
APPL_INFO(" - " << it);
}
/*
jus::ServiceRemote localService = client1.getService("serviceTest1");
if (localService.exist() == true) {
double retCall = localService.call_d("mul", 13.1, 2.0);
APPL_INFO("serviceTest1.mul = " << retCall);
}
*/
if (true) {
APPL_INFO(" ----------------------------------");
APPL_INFO(" -- Get service system-user");
APPL_INFO(" ----------------------------------");
jus::ServiceRemote remoteServiceUser = client1.getService("system-user");
if (remoteServiceUser.exist() == true) {
jus::Future<std::vector<std::string>> retCall = remoteServiceUser.call("getGroups", "clientTest1#atria-soft.com");
retCall.wait();
APPL_INFO("system-user.getGroups() = " << retCall.get());
jus::Future<std::string> retDesc = remoteServiceUser.call("sys.getDescription");
jus::Future<std::string> retVersion = remoteServiceUser.call("sys.getVersion");
jus::Future<std::string> retType = remoteServiceUser.call("sys.getType");
jus::Future<std::vector<std::string>> retExtention = remoteServiceUser.call("srv.getExtention");
jus::Future<std::vector<std::string>> retMaintainer = remoteServiceUser.call("sys.getAuthors");
retDesc.wait();
retVersion.wait();
retType.wait();
retExtention.wait();
retMaintainer.wait();
APPL_INFO("Service: system-user");
APPL_INFO(" version : " << retVersion.get());
APPL_INFO(" type : " << retType.get());
APPL_INFO(" Extention : " << retExtention.get().size());
for (auto &it : retExtention.get()) {
APPL_INFO(" - " << it);
}
APPL_INFO(" maintainer: " << retMaintainer.get().size());
for (auto &it : retMaintainer.get()) {
APPL_INFO(" - " << it);
}
APPL_INFO(" description:");
APPL_INFO(" " << retDesc.get());
APPL_INFO(" Function List:");
jus::Future<std::vector<std::string>> retFuctions = remoteServiceUser.call("sys.getFunctions").wait();
for (auto it : retFuctions.get()) {
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
jus::Future<std::string> retFunctionPrototype = remoteServiceUser.call("sys.getFunctionPrototype", it);
jus::Future<std::string> retFunctionHelp = remoteServiceUser.call("sys.getFunctionDescription", it);
retFunctionPrototype.wait();
retFunctionHelp.wait();
std::chrono::steady_clock::time_point stop = std::chrono::steady_clock::now();
APPL_INFO(" - " << retFunctionPrototype.get());
APPL_INFO(" " << retFunctionHelp.get());
APPL_INFO(" IO1=" << int64_t(retFunctionPrototype.getTransmitionTime().count()/1000)/1000.0 << " ms");
APPL_INFO(" IO2=" << int64_t(retFunctionHelp.getTransmitionTime().count()/1000)/1000.0 << " ms");
APPL_INFO(" IO*=" << int64_t((stop-start).count()/1000)/1000.0 << " ms");
}
}
}
APPL_INFO(" ----------------------------------");
APPL_INFO(" -- Get service picture");
APPL_INFO(" ----------------------------------");
if (false) {
jus::ServiceRemote remoteServicePicture = client1.getService("picture");
if (remoteServicePicture.exist() == true) {
/*
jus::Future<std::vector<std::string>> retCall = remoteServicePicture.call("getAlbums").wait();
APPL_INFO(" album list: ");
for (auto &it : retCall.get()) {
jus::Future<uint32_t> retCount = remoteServicePicture.call("getAlbumCount", it).wait();
if (retCount.get() != 0) {
APPL_INFO(" - " << it << " / " << retCount.get() << " images");
jus::Future<std::vector<std::string>> retListImage = remoteServicePicture.call("getAlbumListPicture", it).wait();
for (auto &it3 : retListImage.get()) {
APPL_INFO(" - " << it3);
}
} else {
APPL_INFO(" - " << it);
}
jus::Future<std::vector<std::string>> retCall2 = remoteServicePicture.call("getSubAlbums", it).wait();
for (auto &it2 : retCall2.get()) {
jus::Future<uint32_t> retCount2 = remoteServicePicture.call("getAlbumCount", it2).wait();
if (retCount2.get() != 0) {
APPL_INFO(" - " << it2 << " / " << retCount2.get() << " images");
jus::Future<std::vector<std::string>> retListImage = remoteServicePicture.call("getAlbumListPicture", it2).wait();
for (auto &it3 : retListImage.get()) {
APPL_INFO(" - " << it3);
jus::Future<jus::File> retListImage = remoteServicePicture.call("getAlbumPicture", it3).wait();
jus::File tmpFile = retListImage.get();
APPL_INFO(" mine-type: " << tmpFile.getMineType());
APPL_INFO(" size: " << tmpFile.getData().size());
APPL_INFO(" receive in =" << int64_t(retListImage.getTransmitionTime().count()/1000)/1000.0 << " ms");
std::string tmpFileName = std::string("./out/") + it + "_" + it2 + "_" + it3 + "." + jus::getExtention(tmpFile.getMineType());
APPL_INFO(" store in: " << tmpFileName);
etk::FSNode node(tmpFileName);
node.fileOpenWrite();
node.fileWrite(&tmpFile.getData()[0], 1, tmpFile.getData().size());
node.fileClose();
}
} else {
APPL_INFO(" - " << it2);
}
}
}
*/
#if 0
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
jus::File tmp("./photo_2016_33913.bmp");//"image/jpg", {0,5,2,6,7,5,8,4,5,2,1,5,65,5,2,6,85,4,6,6,54,65,88,64,14,6,4,64,51,3,16,4});
int32_t size = tmp.getData().size();
jus::FutureBase retSendImage = remoteServicePicture.call("addFile", tmp).wait();
std::chrono::steady_clock::time_point stop = std::chrono::steady_clock::now();
APPL_WARNING(" IO*=" << int64_t((stop-start).count()/1000)/1000.0 << " ms");
double megaParSec = double(size)/(double((stop-start).count())/1000000000.0);
APPL_WARNING(" speed=" << int64_t(megaParSec/1024.0)/1024.0 << " Mo/s");
#endif
}
}
int32_t iii=0;
while (iii < 3) {
usleep(500000);
APPL_INFO("Appl in waiting ... " << iii << "/3");
iii++;
}
client1.disconnect();
APPL_INFO("==================================");
APPL_INFO("== JUS test client stop");
APPL_INFO("==================================");
return 0;
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import lutin.module as module
import realog.debug as debug
import lutin.tools as tools
@ -10,10 +10,10 @@ def get_sub_type():
return "TOOLS"
def get_desc():
return "JUS test service"
return "ZEUS generic gateway"
def get_licence():
return "APACHE-2"
return "MPL-2"
def get_compagny_type():
return "com"
@ -24,15 +24,17 @@ def get_compagny_name():
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_export_path(tools.get_current_path(__file__))
my_module.add_module_depend(['jus'])
def configure(target, my_module):
my_module.add_path(".")
my_module.add_depend([
'zeus',
'zeus-service-test-service1',
])
my_module.add_src_file([
'appl/debug.cpp',
'appl/main.cpp'
'appl/main-test-client.cpp'
])
return my_module
return True

View File

@ -1,12 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.h>
#include <appl/debug.hpp>
int32_t appl::getLogId() {
static int32_t g_val = elog::registerInstance("jus-test-service1");
static int32_t g_val = elog::registerInstance("test-service1");
return g_val;
}

View File

@ -1,11 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <elog/log.h>
#include <elog/log.hpp>
namespace appl {
int32_t getLogId();
@ -17,13 +17,12 @@ namespace appl {
#define APPL_CRITICAL(data) APPL_BASE(1, data)
#define APPL_ERROR(data) APPL_BASE(2, data)
#define APPL_WARNING(data) APPL_BASE(3, data)
#define APPL_INFO(data) APPL_BASE(4, data)
#ifdef DEBUG
#define APPL_INFO(data) APPL_BASE(4, data)
#define APPL_DEBUG(data) APPL_BASE(5, data)
#define APPL_VERBOSE(data) APPL_BASE(6, data)
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
#else
#define APPL_INFO(data) do { } while(false)
#define APPL_DEBUG(data) do { } while(false)
#define APPL_VERBOSE(data) do { } while(false)
#define APPL_TODO(data) do { } while(false)

View File

@ -0,0 +1,126 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <zeus/Object.hpp>
#include <zeus/File.hpp>
#include <etk/etk.hpp>
#include <zeus/zeus.hpp>
#include <echrono/Time.hpp>
#include <ethread/Mutex.hpp>
#include <ejson/ejson.hpp>
#include <sstream>
#include <etk/stdTools.hpp>
#include <zeus/service/test/Service1.hpp>
#include <zeus/service/test/registerService1.hpp>
#include <zeus/File.hpp>
#include <zeus/ProxyFile.hpp>
#include <zeus/zeus-Media.impl.hpp>
static ethread::Mutex g_mutex;
static etk::Uri g_basePath;
static etk::String g_baseDBName = etk::String(SERVICE_NAME) + "-database.json";
static etk::Vector<ememory::SharedPtr<zeus::MediaImpl>> m_listFile;
static uint64_t m_lastMaxId = 0;
static bool g_needToStore = false;
static uint64_t createUniqueID() {
m_lastMaxId++;
return m_lastMaxId;
}
namespace appl {
class TestService1 : public zeus::service::test::Service1 {
private:
etk::String m_userName;
public:
TestService1(uint16_t _clientId) {
APPL_VERBOSE("New TestService1 ... for user: " << _clientId);
}
~TestService1() {
APPL_VERBOSE("delete TestService1 ...");
}
public:
uint32_t getU32(uint32_t _value) override {
return _value*2;
}
etk::Vector<uint32_t> getVU32(etk::Vector<uint32_t> _value) override {
for (auto &it: _value) {
it *= 2;
}
return _value;
}
etk::String getString(etk::String _value) override {
return "get:'" + _value + "'";
}
void getVoid() override {
// nothing to do ...;
}
void doSomething(zeus::ActionNotification<int32_t>& _notifs, int32_t _value) override {
for (int32_t iii=1; iii<=_value; ++iii) {
//ethread::sleepMilliSeconds((500));
_notifs.emit(iii);
}
}
};
}
static void store_db() {
APPL_INFO("Store database [START]");
ejson::Document database;
ejson::Array listFilesArray;
database.add("baseValue", ejson::String("plop"));
bool retGenerate = database.storeSafe(g_basePath / g_baseDBName);
APPL_INFO("Store database [STOP] : " << (g_basePath / g_baseDBName) << " ret = " << retGenerate);
g_needToStore = false;
}
static void load_db() {
ejson::Document database;
bool ret = database.load(g_basePath / g_baseDBName);
if (ret == false) {
APPL_WARNING(" ==> LOAD error");
}
g_needToStore = false;
}
ETK_EXPORT_API bool SERVICE_IO_init(int _argc, const char *_argv[], etk::Uri _basePath) {
g_basePath = _basePath;
ethread::UniqueLock lock(g_mutex);
APPL_INFO("Load USER: " << g_basePath);
load_db();
APPL_INFO("new USER: [STOP]");
return true;
}
ETK_EXPORT_API bool SERVICE_IO_uninit() {
ethread::UniqueLock lock(g_mutex);
store_db();
APPL_INFO("delete USER [STOP]");
return true;
}
ETK_EXPORT_API void SERVICE_IO_peridic_call() {
if (g_needToStore == false) {
return;
}
// try lock mutex:
if (g_mutex.tryLock() == false) {
return;
}
store_db();
g_mutex.unLock();
}
ZEUS_SERVICE_TEST_SERVICE1_DECLARE(appl::TestService1);

View File

@ -1,110 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <appl/debug.h>
#include <jus/Service.h>
#include <etk/etk.h>
#include <unistd.h>
#include <etk/stdTools.h>
namespace appl {
class User {
public:
User() {
APPL_WARNING("new USER");
}
~User() {
APPL_WARNING("delete USER");
}
};
class UserManager {
private:
std::map<std::string, ememory::SharedPtr<appl::User>> m_listLoaded;
public:
UserManager() {
}
ememory::SharedPtr<appl::User> getUser(const std::string& _userName) {
// TODO : Lock ...
auto it = m_listLoaded.find(_userName);
if (it != m_listLoaded.end()) {
// User already loaded:
return it->second;
}
// load New User:
ememory::SharedPtr<appl::User> tmp(new appl::User);
m_listLoaded.insert(std::make_pair(_userName, tmp));
return tmp;
}
};
class Calculator {
public:
Calculator() {
APPL_WARNING("New Calculator ...");
}
~Calculator() {
APPL_WARNING("delete Calculator ...");
}
private:
ememory::SharedPtr<appl::User> m_user;
public:
double mul(double _val1, double _val2) {
return _val1*_val2;
}
public:
Calculator(ememory::SharedPtr<appl::User> _user) :
m_user(_user) {
//advertise("mul", &appl::Service1::mul, "simple multiplication to test double IO");
}
};
}
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
appl::UserManager userMng;
jus::ServiceType<appl::Calculator, appl::UserManager> serviceInterface(userMng);
serviceInterface.setDescription("Calculator interface");
serviceInterface.setVersion("0.1.1");
serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com");
serviceInterface.advertise("mul", &appl::Calculator::mul);
serviceInterface.setLastFuncDesc("simple multiplication to test double IO");
serviceInterface.addLastFuncParam("val1", "First Parameter To multiply");
serviceInterface.addLastFuncParam("val2", "Second Parameter To multiply");
for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) {
serviceInterface.propertyIp.set(std::string(&data[5]));
} else if (etk::start_with(data, "--port=") == true) {
serviceInterface.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7])));
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)");
APPL_PRINT(" --port=XXX Server connection PORT (default: 1983)");
return -1;
}
}
APPL_INFO("==================================");
APPL_INFO("== JUS test service1 start ==");
APPL_INFO("==================================");
serviceInterface.connect("serviceTest1");
int32_t iii=0;
while (true) {
usleep(1000000);
serviceInterface.pingIsAlive();
APPL_INFO("service in waiting ... " << iii << "/inf");
iii++;
}
serviceInterface.disconnect();
APPL_INFO("==================================");
APPL_INFO("== JUS test service1 stop ==");
APPL_INFO("==================================");
return 0;
}

View File

@ -0,0 +1,24 @@
#elem-brief: picture interface management
#elem-version: 1.0
#elem-type:PICTURE
#elem-author:Heero Yui<yui.heero@gmail.com
#brief:Title of the fucntion
#param:parameterName:description of the parameter
#return:Return description of the function
uint32 getU32(uint32)
vector:uint32 getVU32(vector:uint32)
string getString(string)
void getVoid()
[action int32]void doSomething(int32)

View File

@ -0,0 +1,43 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
def get_type():
return "LIBRARY_DYNAMIC"
#return "BINARY"
def get_sub_type():
return "TOOLS"
def get_desc():
return "ZEUS test service1"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module):
my_module.add_path(".")
my_module.add_depend([
'zeus',
'ejson',
'zeus-service-test-service1'
])
my_module.add_src_file([
'appl/debug.cpp',
'appl/main-service-test-service1.cpp'
])
my_module.add_flag('c++', "-DSERVICE_NAME=\"\\\"test-service1\\\"\"")
return True

View File

@ -0,0 +1,41 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
import lutin.macro as macro
def get_type():
return "LIBRARY"
#return "BINARY"
def get_sub_type():
return "TOOLS"
def get_desc():
return "ZEUS test service1"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module):
my_module.add_depend([
'zeus'
])
zeus_macro = macro.load_macro('zeus')
zeus_macro.parse_object_idl(my_module, 'appl/zeus-service-test-service1.srv.zeus.idl')
my_module.add_flag('c++', "-DSERVICE_NAME=\"\\\"test-service1\\\"\"")
return True

View File

@ -0,0 +1,36 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
def get_type():
return "PACKAGE"
def get_desc():
return "ZEUS package group to set it usable"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module):
my_module.add_depend([
'zeus-router',
'zeus-gateway',
'zeus-service-test-service1-impl',
'zeus-service-user-impl',
'zeus-launcher',
'zeus-test-client',
])
return True

119
tools/architecture.txt Normal file
View File

@ -0,0 +1,119 @@
*----------------------------------------------------------------------------*
| Docker / single binary Single User specific program/environement |
| |
| *-----------------------* |
| +--------->| service-right-manager | |
| *-------------* | *-----------------------* |
| | |<-+ |
+--------------------->|Direct | *-----------------------* | +-------------------+
| | | |<----------->| service-picture | | | |
| +-----------| GATEWAY | *-----------------------* |<===>| USER X data | (ex amazon cloud unlimited)
| | | | |<------+ | | |
| | | | | | *-----------------------* | +-------------------+
| | | | |<--+ +---->| service-video | |
-----------* | | | | | | *-----------------------* |
|------------------+ | | *-------------* | |
| | | | *-----------------------* |
| *-------------* | | +-------->| service-XXX | |
|-----* | | | | *-----------------------* |
| | | | | | |
|-----| | |<---+ *----------------------------------------------------------------------------*
Internet | | | |
|-----*===>|80 ROUTER |
| | | |
|-----| | |<---+ *----------------------------------------------------------------------------*
| | | | | | Docker / single binary Single User specific program/environement |
|-----* | | | | |
| *-------------* | | *-----------------------* |
| || | | +--------->| service-right-manager | |
| *----------* | | *-------------* | *-----------------------* |
-----------* | List | | | | |<-+ | +-------------------+
| of | | | | | *-----------------------* | | |
| user | | | | |<----------->| service-picture | |<===>| USER Y data |
|availlable| +-----------| GATEWAY | *-----------------------* | | |
*----------* | | |<------+ | +-------------------+
| | | | *-----------------------* |
| | |<--+ +---->| service-video | |
| | | | *-----------------------* |
| *-------------* | |
| | *-----------------------* |
| +-------->| service-XXX | |
| *-----------------------* |
| |
*----------------------------------------------------------------------------*
This is the first acces node of the service engine ==> it redirect the user to the correct gateway IP address
-----------*
|
|
| *-------------*
|<----* | |
| | | ZUNS | +-------------------------+
|<----| | | | |
Internet | | | | | List of user |
|<----*===>| zeus |<---->| associated gateway |
| | | user | | address |
|<----| | name | | |
| | | server | +-------------------------+
|<----* | |
| *-------------*
|
|
-----------*
And for the people that want to store their data without managing the routeur and have a parsonal network adresses:
-----------*
|
|
| *-------------*
|<----+ | |
| | | |
|<----+===>| |
Internet | | | |
|<----+ | PROXY |
| | |
| | |
| | |
*------|--------->| |
| | | |
| | ... | |
| | | |
| ...--|--------->| |
| | *-------------*
| |
| |
| | <<================================== Change Machine ==================================>>
| |
| |
| | *----------------------------------------------------------------------------*
| | | Docker / single binary Single User specufic program/environement |
| | | |
| | | *-----------------------* |
| | | +--------->| service-right-manager | |
| | | *-------------* | *-----------------------* |
| | | | |<-+ | +-------------------+
| | | | | *-----------------------* | | |
| | | | |<----------->| service-picture | |<===>| USER Y data |
+------|---------->| GATEWAY | *-----------------------* | | |
| | | |<------+ | +-------------------+
| | | | | *-----------------------* |
| | | |<--+ +---->| service-video | |
| | | | | *-----------------------* |
| | *-------------* | |
| | | *-----------------------* |
| | +-------->| service-XXX | |
| | *-----------------------* |
| | |
| *----------------------------------------------------------------------------*
|
|
-----------*

View File

@ -1,12 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.h>
#include <appl/debug.hpp>
int32_t appl::getLogId() {
static int32_t g_val = elog::registerInstance("jus-system-service");
static int32_t g_val = elog::registerInstance("zeus-client-video");
return g_val;
}

View File

@ -1,11 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <elog/log.h>
#include <elog/log.hpp>
namespace appl {
int32_t getLogId();
@ -17,13 +17,12 @@ namespace appl {
#define APPL_CRITICAL(data) APPL_BASE(1, data)
#define APPL_ERROR(data) APPL_BASE(2, data)
#define APPL_WARNING(data) APPL_BASE(3, data)
#define APPL_INFO(data) APPL_BASE(4, data)
#ifdef DEBUG
#define APPL_INFO(data) APPL_BASE(4, data)
#define APPL_DEBUG(data) APPL_BASE(5, data)
#define APPL_VERBOSE(data) APPL_BASE(6, data)
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
#else
#define APPL_INFO(data) do { } while(false)
#define APPL_DEBUG(data) do { } while(false)
#define APPL_VERBOSE(data) do { } while(false)
#define APPL_TODO(data) do { } while(false)

View File

@ -0,0 +1,628 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <zeus/Client.hpp>
#include <zeus/ObjectRemote.hpp>
#include <zeus/mineType.hpp>
#include <etk/etk.hpp>
#include <zeus/zeus.hpp>
#include <etk/path/fileSystem.hpp>
#include <etk/io/File.hpp>
#include <elog/elog.hpp>
#include <algorithm>
#include <etk/stdTools.hpp>
#include <zeus/service/ProxyVideo.hpp>
#include <zeus/ProxyFile.hpp>
#include <zeus/ProxyMedia.hpp>
#include <zeus/ObjectRemote.hpp>
#include <echrono/Steady.hpp>
#include <zeus/FutureGroup.hpp>
#include <algue/sha512.hpp>
static etk::String extractAndRemove(const etk::String& _inputValue, const char _startMark, const char _stopMark, etk::Vector<etk::String>& _values) {
_values.clear();
etk::String out;
bool inside=false;
etk::String insideData;
for (auto &it : _inputValue) {
if ( inside == false
&& it == _startMark) {
inside = true;
} else if ( inside == true
&& it == _stopMark) {
inside = false;
_values.pushBack(insideData);
insideData.clear();
} else if (inside == true) {
insideData += it;
} else {
out += it;
}
}
return out;
}
bool progressCall(const etk::String& _value) {
return false;
}
void progressCallback(const etk::String& _value) {
APPL_PRINT("plop " << _value);
}
bool pushVideoFile(zeus::service::ProxyVideo& _srv, etk::Path _path, etk::Map<etk::String,etk::String> _basicKey = etk::Map<etk::String,etk::String>()) {
etk::String extention = _path.getExtention().toLower();
etk::String fileName = _path.getFileName();
// internal extention ...
if (extention == "sha512") {
return true;
}
APPL_PRINT("Add media : '" << _path << "'");
if ( extention != "avi"
&& extention != "mkv"
&& extention != "mov"
&& extention != "mp4"
&& extention != "ts"
&& fileName != "cover_1.jpg"
&& fileName != "cover_1.png"
&& fileName != "cover_1.till"
&& fileName != "cover_1.bmp"
&& fileName != "cover_1.tga") {
APPL_ERROR("Sot send file : " << _path << " Not manage extention...");
return false;
}
if ( fileName == "cover_1.jpg"
|| fileName == "cover_1.png"
|| fileName == "cover_1.till"
|| fileName == "cover_1.bmp"
|| fileName == "cover_1.tga") {
// find a cover...
APPL_INFO("Send cover for: " << _basicKey["series-name"] << " " << _basicKey["saison"]);
if (_basicKey["series-name"] == "") {
APPL_ERROR(" ==> can not asociate at a specific seri");
return false;
}
etk::String groupName = _basicKey["series-name"];
if (_basicKey["saison"] != "") {
groupName += ":" + _basicKey["saison"];
}
auto sending = _srv.setGroupCover(zeus::File::create(_path.getString(), ""), groupName);
sending.onSignal(progressCallback);
sending.waitFor(echrono::seconds(20000));
return true;
}
etk::String storedSha512;
if (etk::path::exist(_path + ".sha512") == true) {
APPL_VERBOSE("file sha exist ==> read it");
uint64_t time_sha512 = etk::path::getModifyTime(_path + ".sha512");
uint64_t time_elem = etk::path::getModifyTime(_path);
etk::io::File file(_path + ".sha512");
file.open(etk::io::OpenMode::Read);
etk::String storedSha512_file = file.readAllString();
file.close();
APPL_VERBOSE("file sha == " << storedSha512_file);
if (time_elem > time_sha512) {
APPL_VERBOSE("file time > sha time ==> regenerate new one ...");
// check the current sha512
storedSha512 = algue::stringConvert(algue::sha512::encodeFromFile(_path));
APPL_VERBOSE("calculated new sha'" << storedSha512 << "'");
if (storedSha512_file != storedSha512) {
//need to remove the old sha file
auto idFileToRemove_fut = _srv.getId(storedSha512_file).waitFor(echrono::seconds(2));
if (idFileToRemove_fut.hasError() == true) {
APPL_ERROR("can not remove the remote file with sha " + storedSha512_file);
} else {
APPL_INFO("Remove old deprecated file: " + storedSha512_file);
_srv.remove(idFileToRemove_fut.get());
// note, no need to wait the call is async ... and the user does not interested with the result ...
}
}
// store new sha512 ==> this update tile too ...
file.open(etk::io::OpenMode::Write);
file.writeAll(storedSha512);
file.close();
} else {
// store new sha512
/*
storedSha512 = file.readAllString();
file.open(etk::io::OpenMode::Read);
file.writeAll(storedSha512);
file.close();
*/
storedSha512 = storedSha512_file;
APPL_VERBOSE("read all sha from the file'" << storedSha512 << "'");
}
} else {
storedSha512 = algue::stringConvert(algue::sha512::encodeFromFile(_path));
etk::io::File file(_path + ".sha512");
file.open(etk::io::OpenMode::Write);
file.writeAll(storedSha512);
file.close();
APPL_VERBOSE("calculate and store sha '" << storedSha512 << "'");
}
APPL_VERBOSE("check file existance: sha='" << storedSha512 << "'");
// push only if the file exist
// TODO : Check the metadata updating ...
auto idFile_fut = _srv.getId(storedSha512).waitFor(echrono::seconds(2));
if (idFile_fut.hasError() == false) {
// media already exit ==> stop here ...
return true;
}
// TODO: Do it better ==> add the calback to know the push progression ...
APPL_VERBOSE("Add File : " << _path << " sha='" << storedSha512 << "'");
auto sending = _srv.add(zeus::File::create(_path, storedSha512));
sending.onSignal(progressCallback);
APPL_VERBOSE("Add done ... now waiting ... ");
uint32_t mediaId = sending.waitFor(echrono::seconds(20000)).get();
APPL_VERBOSE("END WAITING ... ");
if (mediaId == 0) {
APPL_ERROR("Get media ID = 0 With no error");
return false;
}
// Get the media
zeus::ProxyMedia media = _srv.get(mediaId).waitFor(echrono::seconds(2000)).get();
if (media.exist() == false) {
APPL_ERROR("get media error");
return false;
}
// TODO: if the media have meta data ==> this mean that the media already added before ...
APPL_INFO("Find fileName : '" << fileName << "'");
// Remove Date (XXXX) or other title
etk::Vector<etk::String> dates;
fileName = extractAndRemove(fileName, '(', ')', dates);
bool haveDate = false;
bool haveTitle = false;
for (auto &it: dates) {
if (it.size() == 0) {
continue;
}
if ( it[0] == '0'
|| it[0] == '1'
|| it[0] == '2'
|| it[0] == '3'
|| it[0] == '4'
|| it[0] == '5'
|| it[0] == '6'
|| it[0] == '7'
|| it[0] == '8'
|| it[0] == '9') {
// find a date ...
if (haveDate == true) {
APPL_INFO(" '" << fileName << "'");
APPL_ERROR("Parse Date error : () : " << it << " ==> multiple date");
continue;
}
haveDate = true;
_basicKey.set("date", it);
} else {
if (haveTitle == true) {
APPL_INFO(" '" << fileName << "'");
APPL_ERROR("Parse Title error : () : " << it << " ==> multiple title");
continue;
}
haveTitle = true;
// Other title
_basicKey.set("title2", it);
}
}
// remove unneeded date
if (haveDate == false) {
_basicKey.set("date", "");
}
// remove unneeded title 2
if (haveTitle == false) {
_basicKey.set("title2", "");
}
// Remove the actors [XXX YYY][EEE TTT]...
etk::Vector<etk::String> acthors;
fileName = extractAndRemove(fileName, '[', ']', acthors);
if (acthors.size() > 0) {
APPL_INFO(" '" << fileName << "'");
etk::String actorList;
for (auto &itActor : acthors) {
if (actorList != "") {
actorList += ";";
}
actorList += itActor;
}
_basicKey.set("acthors", actorList);
}
// remove extention
fileName = etk::String(fileName.begin(), fileName.begin() + fileName.size() - (extention.size()+1));
etk::Vector<etk::String> listElementBase = etk::split(fileName, '-');
etk::Vector<etk::String> listElement;
etk::String tmpStartString;
for (size_t iii=0; iii<listElementBase.size(); ++iii) {
if ( listElementBase[iii][0] != 's'
&& listElementBase[iii][0] != 'e') {
if (tmpStartString != "") {
tmpStartString += '-';
}
tmpStartString += listElementBase[iii];
} else {
listElement.pushBack(tmpStartString);
tmpStartString = "";
for (/* nothing to do */; iii<listElementBase.size(); ++iii) {
listElement.pushBack(listElementBase[iii]);
}
}
}
if (tmpStartString != "") {
listElement.pushBack(tmpStartString);
}
if (listElement.size() == 1) {
// nothing to do , it might be a film ...
_basicKey.set("title", etk::toString(listElement[0]));
} else {
/*
for (auto &itt : listElement) {
APPL_INFO(" " << itt);
}
*/
if ( listElement.size() > 3
&& listElement[1][0] == 's'
&& listElement[2][0] == 'e') {
// internal formalisme ...
int32_t saison = -1;
int32_t episode = -1;
etk::String seriesName = listElement[0];
_basicKey.set("series-name", etk::toString(seriesName));
etk::String fullEpisodeName = listElement[3];
for (int32_t yyy=4; yyy<listElement.size(); ++yyy) {
fullEpisodeName += "-" + listElement[yyy];
}
_basicKey.set("title", etk::toString(fullEpisodeName));
if (etk::String(&listElement[1][1]) == "XX") {
// saison unknow ... ==> nothing to do ...
} else {
saison = etk::string_to_int32_t(&listElement[1][1]);
}
if (etk::String(&listElement[2][1]) == "XX") {
// episode unknow ... ==> nothing to do ...
} else {
episode = etk::string_to_int32_t(&listElement[2][1]);
_basicKey.set("episode", etk::toString(episode));
}
APPL_INFO("Find a internal mode series: :");
APPL_INFO(" origin : '" << fileName << "'");
etk::String saisonPrint = "XX";
etk::String episodePrint = "XX";
if (saison < 0) {
// nothing to do
} else if(saison < 10) {
saisonPrint = "0" + etk::toString(saison);
_basicKey.set("saison", etk::toString(saison));
} else {
saisonPrint = etk::toString(saison);
_basicKey.set("saison", etk::toString(saison));
}
if (episode < 0) {
// nothing to do
} else if(episode < 10) {
episodePrint = "0" + etk::toString(episode);
_basicKey.set("episode", etk::toString(episode));
} else {
episodePrint = etk::toString(episode);
_basicKey.set("episode", etk::toString(episode));
}
APPL_PRINT(" ==> '" << seriesName << "-s" << saisonPrint << "-e" << episodePrint << "-" << fullEpisodeName << "'");
}
}
// send all meta data:
zeus::FutureGroup group;
for (auto &itKey : _basicKey) {
if (itKey.second != "") {
APPL_WARNING("Set metaData: " << itKey.first << " : " << itKey.second);
}
group.add(media.setMetadata(itKey.first, itKey.second));
}
group.wait();
return true;
}
void installVideoPath(zeus::service::ProxyVideo& _srv, etk::Path _path, etk::Map<etk::String,etk::String> _basicKey = etk::Map<etk::String,etk::String>()) {
APPL_INFO("Parse : '" << _path << "'");
etk::Vector<etk::Path> listSubPath = etk::path::list(_path, etk::path::LIST_FOLDER);
for (auto &itPath : listSubPath) {
etk::Map<etk::String,etk::String> basicKeyTmp = _basicKey;
APPL_INFO("Add Sub path: '" << itPath << "'");
etk::String lastPathName = itPath.getFileName();
if (basicKeyTmp.size() == 0) {
APPL_INFO("find A '" << lastPathName << "' " << basicKeyTmp.size());
if (lastPathName == "film") {
basicKeyTmp.set("type", "film");
basicKeyTmp.set("production-methode", "picture");
} else if (lastPathName == "film-annimation") {
basicKeyTmp.set("type", "film");
basicKeyTmp.set("production-methode", "draw");
} else if (lastPathName == "film-short") { // short films
basicKeyTmp.set("type", "film");
basicKeyTmp.set("production-methode", "short");
} else if (lastPathName == "tv-show") {
basicKeyTmp.set("type", "tv-show");
basicKeyTmp.set("production-methode", "picture");
} else if (lastPathName == "tv-show-annimation") {
basicKeyTmp.set("type", "tv-show");
basicKeyTmp.set("production-methode", "draw");
} else if (lastPathName == "theater") {
basicKeyTmp.set("type", "theater");
} else if (lastPathName == "one-man") {
basicKeyTmp.set("type", "one-man");
}
} else {
APPL_INFO("find B '" << lastPathName << "' " << basicKeyTmp.size());
if (lastPathName == "saison_01") {
basicKeyTmp.set("saison", "1");
} else if (lastPathName == "saison_02") {
basicKeyTmp.set("saison", "2");
} else if (lastPathName == "saison_03") {
basicKeyTmp.set("saison", "3");
} else if (lastPathName == "saison_04") {
basicKeyTmp.set("saison", "4");
} else if (lastPathName == "saison_05") {
basicKeyTmp.set("saison", "5");
} else if (lastPathName == "saison_06") {
basicKeyTmp.set("saison", "6");
} else if (lastPathName == "saison_07") {
basicKeyTmp.set("saison", "7");
} else if (lastPathName == "saison_08") {
basicKeyTmp.set("saison", "8");
} else if (lastPathName == "saison_09") {
basicKeyTmp.set("saison", "9");
} else if (lastPathName == "saison_10") {
basicKeyTmp.set("saison", "10");
} else if (lastPathName == "saison_11") {
basicKeyTmp.set("saison", "11");
} else if (lastPathName == "saison_12") {
basicKeyTmp.set("saison", "12");
} else if (lastPathName == "saison_13") {
basicKeyTmp.set("saison", "13");
} else if (lastPathName == "saison_14") {
basicKeyTmp.set("saison", "14");
} else if (lastPathName == "saison_15") {
basicKeyTmp.set("saison", "15");
} else if (lastPathName == "saison_16") {
basicKeyTmp.set("saison", "16");
} else if (lastPathName == "saison_17") {
basicKeyTmp.set("saison", "17");
} else if (lastPathName == "saison_18") {
basicKeyTmp.set("saison", "18");
} else if (lastPathName == "saison_19") {
basicKeyTmp.set("saison", "19");
} else if (lastPathName == "saison_20") {
basicKeyTmp.set("saison", "20");
} else if (lastPathName == "saison_21") {
basicKeyTmp.set("saison", "21");
} else if (lastPathName == "saison_22") {
basicKeyTmp.set("saison", "22");
} else if (lastPathName == "saison_23") {
basicKeyTmp.set("saison", "23");
} else if (lastPathName == "saison_24") {
basicKeyTmp.set("saison", "24");
} else if (lastPathName == "saison_25") {
basicKeyTmp.set("saison", "25");
} else if (lastPathName == "saison_26") {
basicKeyTmp.set("saison", "26");
} else if (lastPathName == "saison_27") {
basicKeyTmp.set("saison", "27");
} else if (lastPathName == "saison_28") {
basicKeyTmp.set("saison", "28");
} else if (lastPathName == "saison_29") {
basicKeyTmp.set("saison", "29");
} else {
basicKeyTmp.set("series-name", lastPathName);
}
}
installVideoPath(_srv, itPath, basicKeyTmp);
}
// Add files :
etk::Vector<etk::Path> listSubFile = etk::path::list(_path, etk::path::LIST_FILE);
for (auto &itFile : listSubFile) {
etk::Map<etk::String,etk::String> basicKeyTmp = _basicKey;
pushVideoFile(_srv, itFile, _basicKey);
}
}
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
zeus::init(_argc, _argv);
zeus::Client client1;
etk::String login = "test1";
etk::String address = "";
uint32_t port = 0;
etk::String pass = "coucou";
etk::String requestAction = "";
etk::Vector<etk::String> args;
for (int32_t iii=1; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
if (etk::start_with(data, "--login=") == true) {
// separate loggin and IP adress ...
etk::Vector<etk::String> listElem = etk::split(&data[8], '~');
if (listElem.size() == 0) {
APPL_ERROR("Not enouth element in the login ... need use a XXX~SERVER.org:zzz");
return -1;
}
login = listElem[0];
if (listElem.size() == 1) {
// connnect on local host ... nothing to do
} else {
etk::Vector<etk::String> listElem2 = etk::split(listElem[1], ':');
if (listElem2.size() >= 1) {
address = listElem2[0];
}
if (listElem2.size() >= 2) {
port = etk::string_to_uint32_t(listElem2[1]);
}
}
} else if (etk::start_with(data, "--pass=") == true) {
pass = &data[7];
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options] ACTION [arguments]");
APPL_PRINT(" --login=XXX user login");
APPL_PRINT(" --pass=XXX pass to connect to the user");
APPL_PRINT(" ACTION action to execute: clear, push, pushPath, list");
APPL_PRINT(" [arguments] argument depending on the action");
return -1;
} else if ( etk::start_with(data, "--elog") == true
|| etk::start_with(data, "--etk") == true
|| etk::start_with(data, "--zeus") == true
|| etk::start_with(data, "--enet") == true) {
// disable option ...
} else {
if (requestAction == "") {
requestAction = data;
} else {
args.pushBack(data);
}
}
}
if (requestAction == "" ) {
requestAction = "list";
}
APPL_INFO("==================================");
APPL_INFO("== ZEUS test client start ==");
APPL_INFO("==================================");
// Generate IP and Port in the client interface
if (address != "") {
client1.propertyIp.set(address);
}
if (port != 0) {
client1.propertyPort.set(port);
}
bool ret = client1.connect(login, pass);
if (ret == false) {
APPL_ERROR(" ==> NOT Authentify with '" << login << "'");
client1.disconnect();
return -1;
}
etk::String serviceName = "video";
APPL_INFO(" ----------------------------------");
APPL_INFO(" -- connect service '" << serviceName << "'");
APPL_INFO(" ----------------------------------");
if (client1.waitForService(serviceName) == false) {
APPL_ERROR("==> Service not availlable '" << serviceName << "'");
client1.disconnect();
return -1;
}
zeus::service::ProxyVideo remoteServiceVideo = client1.getService("video");
// remove all media (for test)
if (remoteServiceVideo.exist() == false) {
APPL_ERROR("==> can not connect to the service proxy '" << serviceName << "'");
client1.disconnect();
return -1;
}
/* ****************************************************************************************
** Clear All the data base ...
****************************************************************************************/
if (requestAction == "clear") {
APPL_PRINT("============================================");
APPL_PRINT("== Clear data base: ");
APPL_PRINT("============================================");
// TODO : Do it :
APPL_ERROR("NEED to add check in cmd line to execute it ...");
return -1;
uint32_t count = remoteServiceVideo.count().wait().get();
APPL_DEBUG("have " << count << " medias");
for (uint32_t iii=0; iii<count ; iii += 1024) {
uint32_t tmpMax = etk::min(iii + 1024, count);
APPL_DEBUG("read section " << iii << " -> " << tmpMax);
etk::Vector<uint32_t> list = remoteServiceVideo.getIds(iii,tmpMax).wait().get();
zeus::FutureGroup groupWait;
for (auto& it : list) {
APPL_PRINT("remove ELEMENT : " << it);
groupWait.add(remoteServiceVideo.remove(it));
}
groupWait.waitFor(echrono::seconds(2000));
}
APPL_PRINT("============================================");
APPL_PRINT("== DONE ==");
APPL_PRINT("============================================");
} else if (requestAction == "list") {
APPL_PRINT("============================================");
APPL_PRINT("== list files: ");
APPL_PRINT("============================================");
uint32_t count = remoteServiceVideo.count().wait().get();
APPL_DEBUG("have " << count << " medias");
for (uint32_t iii=0; iii<count ; iii += 1024) {
uint32_t tmpMax = etk::min(iii + 1024, count);
APPL_DEBUG("read section " << iii << " -> " << tmpMax);
etk::Vector<uint32_t> list = remoteServiceVideo.getIds(iii, tmpMax).wait().get();
for (auto& it : list) {
// Get the media
zeus::ProxyMedia media = remoteServiceVideo.get(it).waitFor(echrono::seconds(2000)).get();
if (media.exist() == false) {
APPL_ERROR("get media error");
return -1;
}
APPL_DEBUG(" Get title ...");
etk::String name = media.getMetadata("title").wait().get();
APPL_DEBUG(" Get series-name ...");
etk::String serie = media.getMetadata("series-name").wait().get();
APPL_DEBUG(" Get episode ...");
etk::String episode = media.getMetadata("episode").wait().get();
APPL_DEBUG(" Get saison ...");
etk::String saison = media.getMetadata("saison").wait().get();
etk::String outputDesc = "";
if (serie != "") {
outputDesc += serie + "-";
}
if (saison != "") {
outputDesc += "s" + saison + "-";
}
if (episode != "") {
outputDesc += "e" + episode + "-";
}
outputDesc += name;
APPL_PRINT("[" << it << "] '" << outputDesc << "'");
}
}
APPL_PRINT("============================================");
APPL_PRINT("== DONE ==");
APPL_PRINT("============================================");
} else if (requestAction == "push") {
APPL_PRINT("============================================");
APPL_PRINT("== push file: ");
APPL_PRINT("============================================");
if (args.size() == 0) {
APPL_ERROR("Need to specify some file to push ...");
}
for (auto &it: args) {
// TODO : Check if already exist ...
pushVideoFile(remoteServiceVideo, it);
}
APPL_PRINT("============================================");
APPL_PRINT("== DONE ==");
APPL_PRINT("============================================");
} else if (requestAction == "pushPath") {
APPL_PRINT("============================================");
APPL_PRINT("== push path: ");
APPL_PRINT("============================================");
// Send a full path:
for (auto &it: args) {
installVideoPath(remoteServiceVideo, it);
}
APPL_PRINT("============================================");
APPL_PRINT("== DONE ==");
APPL_PRINT("============================================");
} else {
APPL_PRINT("============================================");
APPL_ERROR("== Unknow action: '" << requestAction << "'");
APPL_PRINT("============================================");
}
client1.disconnect();
return 0;
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import lutin.module as module
import realog.debug as debug
import lutin.tools as tools
@ -10,10 +10,10 @@ def get_sub_type():
return "TOOLS"
def get_desc():
return "JUS generic gateway"
return "ZEUS generic video client (command line interface)"
def get_licence():
return "APACHE-2"
return "MPL-2"
def get_compagny_type():
return "com"
@ -24,15 +24,17 @@ def get_compagny_name():
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_export_path(tools.get_current_path(__file__))
my_module.add_module_depend(['jus'])
def configure(target, my_module):
my_module.add_path(".")
my_module.add_depend([
'zeus',
'zeus-service-video'
])
my_module.add_src_file([
'appl/debug.cpp',
'appl/main.cpp'
'appl/main-tool-client-video.cpp'
])
return my_module
return True

View File

@ -1,12 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.h>
#include <appl/debug.hpp>
int32_t appl::getLogId() {
static int32_t g_val = elog::registerInstance("jus-picture");
static int32_t g_val = elog::registerInstance("zeus-client");
return g_val;
}

View File

@ -1,11 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <elog/log.h>
#include <elog/log.hpp>
namespace appl {
int32_t getLogId();
@ -17,13 +17,12 @@ namespace appl {
#define APPL_CRITICAL(data) APPL_BASE(1, data)
#define APPL_ERROR(data) APPL_BASE(2, data)
#define APPL_WARNING(data) APPL_BASE(3, data)
#define APPL_INFO(data) APPL_BASE(4, data)
#ifdef DEBUG
#define APPL_INFO(data) APPL_BASE(4, data)
#define APPL_DEBUG(data) APPL_BASE(5, data)
#define APPL_VERBOSE(data) APPL_BASE(6, data)
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
#else
#define APPL_INFO(data) do { } while(false)
#define APPL_DEBUG(data) do { } while(false)
#define APPL_VERBOSE(data) do { } while(false)
#define APPL_TODO(data) do { } while(false)

View File

@ -0,0 +1,551 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <zeus/Client.hpp>
#include <zeus/ObjectRemote.hpp>
#include <zeus/mineType.hpp>
#include <etk/etk.hpp>
#include <zeus/zeus.hpp>
#include <elog/elog.hpp>
#include <etk/stdTools.hpp>
#include <zeus/ProxyFile.hpp>
#include <zeus/ProxyMedia.hpp>
#include <zeus/ObjectRemote.hpp>
#include <echrono/Steady.hpp>
#include <zeus/FutureGroup.hpp>
#include <algue/sha512.hpp>
static etk::String extractAndRemove(const etk::String& _inputValue, const char _startMark, const char _stopMark, etk::Vector<etk::String>& _values) {
_values.clear();
etk::String out;
bool inside=false;
etk::String insideData;
for (auto &it : _inputValue) {
if ( inside == false
&& it == _startMark) {
inside = true;
} else if ( inside == true
&& it == _stopMark) {
inside = false;
_values.pushBack(insideData);
insideData.clear();
} else if (inside == true) {
insideData += it;
} else {
out += it;
}
}
return out;
}
bool progressCall(const etk::String& _value) {
return false;
}
void progressCallback(const etk::String& _value) {
APPL_PRINT("plop " << _value);
}
#if 0
bool pushVideoFile(zeus::service::ProxyVideo& _srv, etk::String _path, etk::Map<etk::String,etk::String> _basicKey = etk::Map<etk::String,etk::String>()) {
etk::String extention;
if ( _path.rfind('.') != etk::String::npos
&& _path.rfind('.') != 0) {
extention = etk::tolower(etk::String(_path.begin()+_path.rfind('.')+1, _path.end()));
}
// internal extention ....
if (extention == "sha512") {
return true;
}
APPL_PRINT("Add media : '" << _path << "'");
if ( extention != "avi"
&& extention != "mkv"
&& extention != "mov"
&& extention != "mp4"
&& extention != "ts") {
APPL_ERROR("Sot send file : " << _path << " Not manage extention...");
return false;
}
etk::String storedSha512;
if (etk::FSNodeExist(_path + ".sha512") == true) {
uint64_t time_sha512 = etk::FSNodeGetTimeModified(_path + ".sha512");
uint64_t time_elem = etk::FSNodeGetTimeModified(_path);
etk::String storedSha512_file = etk::FSNodeReadAllData(_path + ".sha512");
if (time_elem > time_sha512) {
// check the current sha512
storedSha512 = algue::stringConvert(algue::sha512::encodeFromFile(_path));
if (storedSha512_file != storedSha512) {
//need to remove the old sha file
auto idFileToRemove_fut = _srv.getId(storedSha512_file).waitFor(echrono::seconds(2));
if (idFileToRemove_fut.hasError() == true) {
APPL_ERROR("can not remove the remote file with sha " + storedSha512_file);
} else {
APPL_INFO("Remove old deprecated file: " + storedSha512_file);
_srv.remove(idFileToRemove_fut.get());
// note, no need to wait the call is async ... and the user does not interested with the result ...
}
}
// store new sha512 ==> this update tile too ...
etk::FSNodeWriteAllData(_path + ".sha512", storedSha512);
} else {
// store new sha512
storedSha512 = etk::FSNodeReadAllData(_path + ".sha512");
}
} else {
storedSha512 = algue::stringConvert(algue::sha512::encodeFromFile(_path));
etk::FSNodeWriteAllData(_path + ".sha512", storedSha512);
}
// push only if the file exist
// TODO : Check the metadata updating ...
auto idFile_fut = _srv.getId(storedSha512).waitFor(echrono::seconds(2));
if (idFile_fut.hasError() == false) {
// media already exit ==> stop here ...
return true;
}
// TODO: Do it better ==> add the calback to know the push progression ...
auto sending = _srv.add(zeus::File::create(_path, storedSha512));
sending.onSignal(progressCallback);
uint32_t mediaId = sending.waitFor(echrono::seconds(20000)).get();
if (mediaId == 0) {
APPL_ERROR("Get media ID = 0 With no error");
return false;
}
// Get the media
zeus::ProxyMedia media = _srv.get(mediaId).waitFor(echrono::seconds(2000)).get();
if (media.exist() == false) {
APPL_ERROR("get media error");
return false;
}
// TODO: if the media have meta data ==> this mean that the media already added before ...
// Parse file name:
etk::String fileName = etk::split(_path, '/').back();
APPL_INFO("Find fileName : '" << fileName << "'");
// Remove Date (XXXX) or other title
etk::Vector<etk::String> dates;
fileName = extractAndRemove(fileName, '(', ')', dates);
bool haveDate = false;
bool haveTitle = false;
for (auto &it: dates) {
if (it.size() == 0) {
continue;
}
if ( it[0] == '0'
|| it[0] == '1'
|| it[0] == '2'
|| it[0] == '3'
|| it[0] == '4'
|| it[0] == '5'
|| it[0] == '6'
|| it[0] == '7'
|| it[0] == '8'
|| it[0] == '9') {
// find a date ...
if (haveDate == true) {
APPL_INFO(" '" << fileName << "'");
APPL_ERROR("Parse Date error : () : " << it << " ==> multiple date");
continue;
}
haveDate = true;
_basicKey.insert(etk::Pair<etk::String,etk::String>("date", it));
} else {
if (haveTitle == true) {
APPL_INFO(" '" << fileName << "'");
APPL_ERROR("Parse Title error : () : " << it << " ==> multiple title");
continue;
}
haveTitle = true;
// Other title
_basicKey.insert(etk::Pair<etk::String,etk::String>("title2", it));
}
}
// remove unneeded date
if (haveDate == false) {
_basicKey.insert(etk::Pair<etk::String,etk::String>("date", ""));
}
// remove unneeded title 2
if (haveTitle == false) {
_basicKey.insert(etk::Pair<etk::String,etk::String>("title2", ""));
}
// Remove the actors [XXX YYY][EEE TTT]...
etk::Vector<etk::String> acthors;
fileName = extractAndRemove(fileName, '[', ']', acthors);
if (acthors.size() > 0) {
APPL_INFO(" '" << fileName << "'");
etk::String actorList;
for (auto &itActor : acthors) {
if (actorList != "") {
actorList += ";";
}
actorList += itActor;
}
_basicKey.insert(etk::Pair<etk::String,etk::String>("acthors", actorList));
}
// remove extention
fileName = etk::String(fileName.begin(), fileName.begin() + fileName.size() - (extention.size()+1));
etk::Vector<etk::String> listElementBase = etk::split(fileName, '-');
etk::Vector<etk::String> listElement;
etk::String tmpStartString;
for (size_t iii=0; iii<listElementBase.size(); ++iii) {
if ( listElementBase[iii][0] != 's'
&& listElementBase[iii][0] != 'e') {
if (tmpStartString != "") {
tmpStartString += '-';
}
tmpStartString += listElementBase[iii];
} else {
listElement.pushBack(tmpStartString);
tmpStartString = "";
for (/* nothing to do */; iii<listElementBase.size(); ++iii) {
listElement.pushBack(listElementBase[iii]);
}
}
}
if (tmpStartString != "") {
listElement.pushBack(tmpStartString);
}
if (listElement.size() == 1) {
// nothing to do , it might be a film ...
_basicKey.insert(etk::Pair<etk::String,etk::String>("title", etk::toString(listElement[0])));
} else {
/*
for (auto &itt : listElement) {
APPL_INFO(" " << itt);
}
*/
if ( listElement.size() > 3
&& listElement[1][0] == 's'
&& listElement[2][0] == 'e') {
// internal formalisme ...
int32_t saison = -1;
int32_t episode = -1;
etk::String seriesName = listElement[0];
_basicKey.insert(etk::Pair<etk::String,etk::String>("series-name", etk::toString(seriesName)));
etk::String fullEpisodeName = listElement[3];
for (int32_t yyy=4; yyy<listElement.size(); ++yyy) {
fullEpisodeName += "-" + listElement[yyy];
}
_basicKey.insert(etk::Pair<etk::String,etk::String>("title", etk::toString(fullEpisodeName)));
if (etk::String(&listElement[1][1]) == "XX") {
// saison unknow ... ==> nothing to do ...
} else {
saison = etk::string_to_int32_t(&listElement[1][1]);
}
if (etk::String(&listElement[2][1]) == "XX") {
// episode unknow ... ==> nothing to do ...
} else {
episode = etk::string_to_int32_t(&listElement[2][1]);
_basicKey.insert(etk::Pair<etk::String,etk::String>("episode", etk::toString(episode)));
}
APPL_INFO("Find a internal mode series: :");
APPL_INFO(" origin : '" << fileName << "'");
etk::String saisonPrint = "XX";
etk::String episodePrint = "XX";
if (saison < 0) {
// nothing to do
} else if(saison < 10) {
saisonPrint = "0" + etk::toString(saison);
_basicKey.insert(etk::Pair<etk::String,etk::String>("saison", etk::toString(saison)));
} else {
saisonPrint = etk::toString(saison);
_basicKey.insert(etk::Pair<etk::String,etk::String>("saison", etk::toString(saison)));
}
if (episode < 0) {
// nothing to do
} else if(episode < 10) {
episodePrint = "0" + etk::toString(episode);
_basicKey.insert(etk::Pair<etk::String,etk::String>("episode", etk::toString(episode)));
} else {
episodePrint = etk::toString(episode);
_basicKey.insert(etk::Pair<etk::String,etk::String>("episode", etk::toString(episode)));
}
APPL_PRINT(" ==> '" << seriesName << "-s" << saisonPrint << "-e" << episodePrint << "-" << fullEpisodeName << "'");
}
}
// send all meta data:
zeus::FutureGroup group;
for (auto &itKey : _basicKey) {
if (itKey.second != "") {
APPL_WARNING("Set metaData: " << itKey.first << " : " << itKey.second);
}
group.add(media.setMetadata(itKey.first, itKey.second));
}
group.wait();
return true;
}
void installVideoPath(zeus::service::ProxyVideo& _srv, etk::String _path, etk::Map<etk::String,etk::String> _basicKey = etk::Map<etk::String,etk::String>()) {
etk::FSNode node(_path);
APPL_INFO("Parse : '" << _path << "'");
etk::Vector<etk::String> listSubPath = node.folderGetSub(true, false, "*");
for (auto &itPath : listSubPath) {
etk::Map<etk::String,etk::String> basicKeyTmp = _basicKey;
APPL_INFO("Add Sub path: '" << itPath << "'");
etk::String lastPathName = etk::split(itPath, '/').back();
if (basicKeyTmp.size() == 0) {
APPL_INFO("find A '" << lastPathName << "' " << basicKeyTmp.size());
if (lastPathName == "film") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("type", "film"));
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("production-methode", "picture"));
} else if (lastPathName == "film-annimation") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("type", "film"));
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("production-methode", "draw"));
} else if (lastPathName == "film-short") { // short films
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("type", "film"));
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("production-methode", "short"));
} else if (lastPathName == "tv-show") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("type", "tv-show"));
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("production-methode", "picture"));
} else if (lastPathName == "tv-show-annimation") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("type", "tv-show"));
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("production-methode", "draw"));
} else if (lastPathName == "theater") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("type", "theater"));
} else if (lastPathName == "one-man") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("type", "one-man"));
}
} else {
APPL_INFO("find B '" << lastPathName << "' " << basicKeyTmp.size());
if (lastPathName == "saison_01") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "1"));
} else if (lastPathName == "saison_02") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "2"));
} else if (lastPathName == "saison_03") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "3"));
} else if (lastPathName == "saison_04") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "4"));
} else if (lastPathName == "saison_05") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "5"));
} else if (lastPathName == "saison_06") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "6"));
} else if (lastPathName == "saison_07") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "7"));
} else if (lastPathName == "saison_08") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "8"));
} else if (lastPathName == "saison_09") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "9"));
} else if (lastPathName == "saison_10") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "10"));
} else if (lastPathName == "saison_11") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "11"));
} else if (lastPathName == "saison_12") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "12"));
} else if (lastPathName == "saison_13") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "13"));
} else if (lastPathName == "saison_14") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "14"));
} else if (lastPathName == "saison_15") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "15"));
} else if (lastPathName == "saison_16") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "16"));
} else if (lastPathName == "saison_17") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "17"));
} else if (lastPathName == "saison_18") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "18"));
} else if (lastPathName == "saison_19") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "19"));
} else if (lastPathName == "saison_20") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "20"));
} else if (lastPathName == "saison_21") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "21"));
} else if (lastPathName == "saison_22") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "22"));
} else if (lastPathName == "saison_23") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "23"));
} else if (lastPathName == "saison_24") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "24"));
} else if (lastPathName == "saison_25") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "25"));
} else if (lastPathName == "saison_26") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "26"));
} else if (lastPathName == "saison_27") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "27"));
} else if (lastPathName == "saison_28") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "28"));
} else if (lastPathName == "saison_29") {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("saison", "29"));
} else {
basicKeyTmp.insert(etk::Pair<etk::String,etk::String>("series-name", lastPathName));
}
}
installVideoPath(_srv, itPath, basicKeyTmp);
}
// Add files :
etk::Vector<etk::String> listSubFile = node.folderGetSub(false, true, "*");
for (auto &itFile : listSubFile) {
etk::Map<etk::String,etk::String> basicKeyTmp = _basicKey;
pushVideoFile(_srv, itFile, _basicKey);
}
}
#endif
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
zeus::init(_argc, _argv);
zeus::Client client1;
etk::String login = "test1";
etk::String address = "";
uint32_t port = 0;
etk::String pass = "coucou";
etk::String requestAction = "";
etk::Vector<etk::String> args;
for (int32_t iii=1; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
if (etk::start_with(data, "--login=") == true) {
// separate loggin and IP adress ...
etk::Vector<etk::String> listElem = etk::split(&data[8], '~');
if (listElem.size() == 0) {
APPL_ERROR("Not enouth element in the login ... need use a XXX~SERVER.org:zzz");
return -1;
}
login = listElem[0];
if (listElem.size() == 1) {
// connnect on local host ... nothing to do
} else {
etk::Vector<etk::String> listElem2 = etk::split(listElem[1], ':');
if (listElem2.size() >= 1) {
address = listElem2[0];
}
if (listElem2.size() >= 2) {
port = etk::string_to_uint32_t(listElem2[1]);
}
}
} else if (etk::start_with(data, "--pass=") == true) {
pass = &data[7];
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options] ACTION [arguments]");
APPL_PRINT(" --login=XXX user login");
APPL_PRINT(" --pass=XXX pass to connect to the user");
APPL_PRINT(" ACTION action to execute: info / list");
APPL_PRINT(" [arguments] argument depending on the action");
return -1;
} else if ( etk::start_with(data, "--elog") == true
|| etk::start_with(data, "--etk") == true
|| etk::start_with(data, "--zeus") == true
|| etk::start_with(data, "--enet") == true) {
// disable option ...
} else {
if (requestAction == "") {
requestAction = data;
} else {
args.pushBack(data);
}
}
}
if (requestAction == "" ) {
requestAction = "list";
}
APPL_INFO("==================================");
APPL_INFO("== ZEUS test client start ==");
APPL_INFO("==================================");
// Generate IP and Port in the client interface
if (address != "") {
client1.propertyIp.set(address);
}
if (port != 0) {
client1.propertyPort.set(port);
}
bool ret = client1.connect(login, pass);
if (ret == false) {
APPL_ERROR(" ==> NOT Authentify with '" << login << "'");
client1.disconnect();
return -1;
}
if (requestAction == "list") {
APPL_PRINT("============================================");
APPL_PRINT("== List: ");
APPL_PRINT("============================================");
zeus::Future<int32_t> retNbService = client1.getServiceCount();
zeus::Future<etk::Vector<etk::String>> retServiceList = client1.getServiceList();
retNbService.wait();
APPL_INFO("Nb services = " << retNbService.get());
retServiceList.wait();
APPL_INFO("List services:");
for (auto &it: retServiceList.get()) {
APPL_INFO(" - " << it);
}
APPL_PRINT("============================================");
APPL_PRINT("== DONE ==");
APPL_PRINT("============================================");
} else if (requestAction == "info") {
APPL_PRINT("============================================");
APPL_PRINT("== info: ");
APPL_PRINT("============================================");
// Send a full path:
if (args.size() == 0) {
zeus::Future<etk::Vector<etk::String>> retServiceList = client1.getServiceList();
retServiceList.wait();
for (auto &it: retServiceList.get()) {
zeus::Proxy proxy = client1.getService(it);
if (proxy.exist() == false) {
APPL_ERROR("[" << it << "] ==> can not connect ..." );
} else {
etk::String desc = proxy.sys.getDescription().wait().get();
APPL_PRINT("[" << it << "] " << desc);
}
}
} else if (args.size() != 1) {
APPL_PRINT("============================================");
APPL_ERROR("== action: '" << requestAction << "' can have 0 or 1 arguments");
APPL_PRINT("============================================");
} else {
zeus::Future<etk::Vector<etk::String>> retServiceList = client1.getServiceList();
retServiceList.wait();
bool exist = false;
for (auto &it: retServiceList.get()) {
if (it == args[0]) {
exist = true;
}
}
if (exist == true) {
zeus::Proxy proxy = client1.getService(args[0]);
if (proxy.exist() == false) {
APPL_ERROR("[" << args[0] << "] ==> can not connect ..." );
} else {
APPL_PRINT("[" << args[0] << "] " );
APPL_PRINT(" desc=" << proxy.sys.getDescription().wait().get());
APPL_PRINT(" version=" << proxy.sys.getVersion().wait().get());
APPL_PRINT(" type=" << proxy.sys.getType().wait().get());
APPL_PRINT(" authors=" << proxy.sys.getAuthors().wait().get());
auto listFunctions = proxy.sys.getFunctions().wait().get();
APPL_PRINT(" functions: " << listFunctions.size());
for (auto &it: listFunctions) {
#if 0
APPL_PRINT(" " << it);
APPL_PRINT(" prototype=" << proxy.sys.getFunctionPrototype(it).wait().get());
APPL_PRINT(" desc=" << proxy.sys.getFunctionDescription(it).wait().get());
#else
APPL_PRINT(" " << proxy.sys.getFunctionPrototype(it).wait().get());
APPL_PRINT(" " << proxy.sys.getFunctionDescription(it).wait().get());
#endif
}
}
} else {
APPL_PRINT("service does not exist: [" << args[0] << "] " );
}
}
APPL_PRINT("============================================");
APPL_PRINT("== DONE ==");
APPL_PRINT("============================================");
} else {
APPL_PRINT("============================================");
APPL_ERROR("== Unknow action: '" << requestAction << "'");
APPL_PRINT("============================================");
}
client1.disconnect();
return -1;
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import lutin.module as module
import realog.debug as debug
import lutin.tools as tools
@ -10,10 +10,10 @@ def get_sub_type():
return "TOOLS"
def get_desc():
return "JUS generic gateway"
return "ZEUS generic client (command line interface to introspect services)"
def get_licence():
return "APACHE-2"
return "MPL-2"
def get_compagny_type():
return "com"
@ -24,15 +24,16 @@ def get_compagny_name():
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_export_path(tools.get_current_path(__file__))
my_module.add_module_depend(['jus'])
def configure(target, my_module):
my_module.add_path(".")
my_module.add_depend([
'zeus'
])
my_module.add_src_file([
'appl/debug.cpp',
'appl/main.cpp'
'appl/main-tool-client.cpp'
])
return my_module
return True

View File

@ -0,0 +1,135 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <appl/DirectInterface.hpp>
#include <zeus/Future.hpp>
#include <appl/GateWay.hpp>
#include <enet/TcpClient.hpp>
#include <zeus/AbstractFunction.hpp>
static const etk::String protocolError = "PROTOCOL-ERROR";
appl::DirectInterface::DirectInterface(enet::Tcp _connection, bool _serviceAccess) :
m_interfaceWeb(etk::move(_connection), true),
m_serviceAccess(_serviceAccess) {
m_uid = 0;
m_state = appl::clientState::unconnect;
APPL_INFO("------------------------");
if (m_serviceAccess == true) {
APPL_INFO("-- NEW SERVICE Client --");
} else {
APPL_INFO("-- NEW Direct Client --");
}
APPL_INFO("------------------------");
}
appl::DirectInterface::~DirectInterface() {
APPL_INFO("---------------------------");
if (m_serviceAccess == true) {
APPL_INFO("-- DELETE SERVICE Client --");
} else {
APPL_INFO("-- DELETE Direct Client --");
}
APPL_INFO("---------------------------");
m_interfaceWeb.disconnect();
APPL_INFO("---------------------------");
}
/*
void appl::clientSpecificInterface::answerProtocolError(uint32_t _transactionId, const etk::String& _errorHelp) {
m_interfaceWeb->answerError(_transactionId, m_routeurUID, ZEUS_ID_SERVICE_ROOT, protocolError, _errorHelp);
m_interfaceWeb->sendCtrl(m_routeurUID, ZEUS_ID_SERVICE_ROOT, "DISCONNECT");
m_state = appl::clientState::disconnect;
}
*/
etk::String appl::DirectInterface::requestURI(const etk::String& _uri, const etk::Map<etk::String,etk::String>& _options) {
APPL_WARNING("request Direct connection: '" << _uri << "'");
etk::String tmpURI = _uri;
if (tmpURI.size() == 0) {
APPL_ERROR("Empty URI ... not supported ...");
return "CLOSE";
}
if (tmpURI[0] == '/') {
tmpURI = etk::String(tmpURI.begin() + 1, tmpURI.end());
}
etk::Vector<etk::String> listValue = etk::split(tmpURI, '?');
if (listValue.size() == 0) {
APPL_ERROR("can not parse URI ...");
return "CLOSE";
}
tmpURI = listValue[0];
if (tmpURI == m_gateway->propertyUserName.get() ) {
return "OK";
}
if (etk::start_with(tmpURI, "directIO") == false ) {
APPL_ERROR("Missing 'directIO:' at the start of the URI ...");
return "CLOSE";
}
return "OK";
}
bool appl::DirectInterface::start(appl::GateWay* _gateway) {
appl::IOInterface::start(_gateway, 0, m_serviceAccess==false);
m_interfaceWeb.connect(this, &appl::DirectInterface::receive);
m_interfaceWeb.connectUri(this, &appl::DirectInterface::requestURI);
m_interfaceWeb.connect();
m_interfaceWeb.setInterfaceName("DIO-?");
//APPL_WARNING("[" << m_uid << "] New client : " << m_clientName);
return true;
}
void appl::DirectInterface::receive(ememory::SharedPtr<zeus::Message> _value) {
if (_value == null) {
return;
}
// check transaction ID != 0
uint32_t transactionId = _value->getTransactionId();
if (transactionId == 0) {
APPL_ERROR("Protocol error ==>missing id");
answerProtocolError(transactionId, "missing parameter: 'id'");
return;
}
// check correct SourceID
if (_value->getSourceId() != m_uid) {
answerProtocolError(transactionId, "message with the wrong source ID");
return;
}
// Check gateway corectly connected
if (m_gateway == null) {
answerProtocolError(transactionId, "GateWay error");
return;
}
// TODO: Special hook for the first call that we need to get the curretn ID of the connection, think to set this at an other position ...
if (m_uid == 0) {
APPL_INFO("special case, we need to get the ID Of the client:");
if (_value->getType() != zeus::message::type::call) {
answerProtocolError(transactionId, "Must get first the Client ID... call 'getAddress'");
return;
}
ememory::SharedPtr<zeus::message::Call> callObj = ememory::staticPointerCast<zeus::message::Call>(_value);
if (callObj->getCall() != "getAddress") {
answerProtocolError(transactionId, "Must get first the Client ID... call 'getAddress' and not '" + callObj->getCall() + "'");
return;
}
m_uid = m_gateway->getId();
APPL_INFO("clent call getAddress ==> return addresse " << m_uid);
if (m_uid == 0) {
answerProtocolError(transactionId, "Can not get the Client ID...");
return;
}
m_interfaceWeb.setInterfaceName("cli-" + etk::toString(m_uid));
m_interfaceWeb.answerValue(transactionId, _value->getDestination(), _value->getSource(), m_uid);
} else {
appl::IOInterface::receive(_value);
}
}
void appl::DirectInterface::send(ememory::SharedPtr<zeus::Message> _value) {
m_interfaceWeb.writeBinary(_value);
}

View File

@ -0,0 +1,32 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <zeus/WebServer.hpp>
#include <appl/GateWay.hpp>
#include <appl/IOInterface.hpp>
namespace appl {
class GateWay;
class DirectInterface : public appl::IOInterface {
public:
zeus::WebServer m_interfaceWeb;
bool m_serviceAccess;
public:
DirectInterface(enet::Tcp _connection, bool _serviceAccess);
virtual ~DirectInterface();
bool start(appl::GateWay* _gateway);
void receive(ememory::SharedPtr<zeus::Message> _data);
void send(ememory::SharedPtr<zeus::Message> _data);
etk::String requestURI(const etk::String& _uri, const etk::Map<etk::String,etk::String>& _options);
//void answerProtocolError(uint32_t _transactionId, const etk::String& _errorHelp);
zeus::WebServer* getInterface() {
return &m_interfaceWeb;
}
bool isConnected() { return m_interfaceWeb.isActive(); };
};
}

View File

@ -0,0 +1,359 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/GateWay.hpp>
#include <appl/debug.hpp>
#include <enet/TcpServer.hpp>
#include <appl/DirectInterface.hpp>
#include <appl/RouterInterface.hpp>
#include <etk/Exception.hpp>
namespace appl {
class TcpServerInput {
private:
enet::TcpServer m_interface;
ethread::Thread* m_thread;
bool m_threadRunning;
appl::GateWay* m_gateway;
bool m_serviceAccess;
public:
TcpServerInput(appl::GateWay* _gateway, bool _serviceAccess) :
m_thread(null),
m_threadRunning(false),
m_gateway(_gateway),
m_serviceAccess(_serviceAccess) {
}
virtual ~TcpServerInput() {}
void start(const etk::String& _host, uint16_t _port) {
m_interface.setHostNane(_host);
m_interface.setPort(_port);
m_interface.link();
m_threadRunning = true;
APPL_INFO("Start waiting on " << _host << " " << _port);
m_thread = ETK_NEW(ethread::Thread, [&](){ threadCallback();}, "GatewayListening");
if (m_thread == null) {
m_threadRunning = false;
APPL_ERROR("creating callback thread!");
return;
}
}
void stop() {
if (m_thread != null) {
m_threadRunning = false;
}
m_interface.unlink();
if (m_thread != null) {
m_thread->join();
ETK_DELETE(ethread::Thread, m_thread);
m_thread = null;
}
}
void threadCallback() {
// get datas:
while (m_threadRunning == true) {
// READ section data:
enet::Tcp data = etk::move(m_interface.waitNext());
if (data.getConnectionStatus() != enet::Tcp::status::link) {
APPL_CRITICAL("New TCP connection (DEAD ....) ==> gateway is dead ...");
// TODO: Check interaface: if (m_interface.
ethread::sleepMilliSeconds((300));
}
APPL_VERBOSE("New connection");
m_gateway->newDirectInterface(etk::move(data), m_serviceAccess);
}
}
};
}
void appl::GateWay::newDirectInterface(enet::Tcp _connection, bool _serviceAccess) {
APPL_WARNING("New TCP connection (service)");
ememory::SharedPtr<appl::DirectInterface> tmp = ememory::makeShared<appl::DirectInterface>(etk::move(_connection), _serviceAccess);
tmp->start(this);
m_listTemporaryIO.pushBack(tmp);
}
appl::GateWay::GateWay() :
m_idIncrement(10),
propertyUserName(this, "user", "no-name", "User name of the interface"), // must be set befor start ...
propertyRouterNo(this, "no-router", false, "No connection on the router"),
propertyRouterIp(this, "router-ip", "127.0.0.1", "Ip to listen client", &appl::GateWay::onPropertyChangeClientIp),
propertyRouterPort(this, "router-port", 1984, "Port to listen client", &appl::GateWay::onPropertyChangeClientPort),
propertyDirectIp(this, "direct-ip", "127.0.0.1", "Ip to listen client"),
propertyDirectPort(this, "direct-port", 0, "Port to listen direct client", &appl::GateWay::onPropertyChangeDirectClientPort),
propertyServiceExtern(this, "service-extern", true, "enable extern service"),
propertyServiceIp(this, "service-ip", "127.0.0.1", "Ip to listen client", &appl::GateWay::onPropertyChangeServiceIp),
propertyServicePort(this, "service-port", 1985, "Port to listen client", &appl::GateWay::onPropertyChangeServicePort),
propertyServiceMax(this, "service-max", 80, "Maximum of client at the same time", &appl::GateWay::onPropertyChangeServiceMax) {
m_interfaceNewService = ememory::makeShared<appl::TcpServerInput>(this, true);
m_interfaceNewClient = ememory::makeShared<appl::TcpServerInput>(this, false);
}
appl::GateWay::~GateWay() {
}
void appl::GateWay::addIO(const ememory::SharedPtr<appl::IOInterface>& _io) {
m_listIO.pushBack(_io);
// REMOVE of temporary element in the temporary list:
auto it = m_listTemporaryIO.begin();
while (it != m_listTemporaryIO.end()) {
ememory::SharedPtr<appl::IOInterface> tmp = *it;
if (tmp.get() == _io.get()) {
it = m_listTemporaryIO.erase(it);
} else {
++it;
}
}
}
void appl::GateWay::removeIO(const ememory::SharedPtr<appl::IOInterface>& _io) {
auto it = m_listIO.begin();
while (it != m_listIO.end()) {
if (it->get() == _io.get()) {
it = m_listIO.erase(it);
} else {
++it;
}
}
}
uint16_t appl::GateWay::getId() {
return m_idIncrement++;
}
void appl::GateWay::start() {
APPL_WARNING("start [START]");
if (*propertyRouterNo == false) {
m_routerClient = ememory::makeShared<appl::RouterInterface>(propertyRouterIp.get(), propertyRouterPort.get(), propertyUserName.get(), this, propertyDirectPort.get());
if (m_routerClient->isAlive() == false) {
APPL_ERROR("Can not connect the Router (if it is the normal case, use option '--no-router'");
throw etk::exception::RuntimeError("Can not connect router");
}
}
// enable access of service connection (external)
if (propertyServiceExtern.get() == true) {
APPL_WARNING("#################################");
APPL_WARNING("## Open interface for Service : " << *propertyServiceIp << ":" << *propertyServicePort);
APPL_WARNING("#################################");
m_interfaceNewService->start(*propertyServiceIp, *propertyServicePort);
}
// Enable access of direct Client
if (propertyDirectPort.get() != 0) {
APPL_WARNING("#################################");
APPL_WARNING("## Open interface for Direct client : " << *propertyDirectIp << ":" << *propertyDirectPort);
APPL_WARNING("#################################");
m_interfaceNewClient->start(*propertyDirectIp, *propertyDirectPort);
}
APPL_WARNING("start [ END ]");
}
void appl::GateWay::stop() {
m_routerClient.reset();
m_listTemporaryIO.clear();
m_listIO.clear();
}
bool appl::GateWay::serviceExist(const etk::String& _service) {
for (auto &it : m_listIO) {
if (it == null) {
continue;
}
if (it->isConnected() == false) {
continue;
}
for (auto &srvIt : it->getServiceList()) {
if (srvIt == _service) {
return true;
}
}
}
return false;
}
uint16_t appl::GateWay::serviceClientIdGet(const etk::String& _service) {
for (auto &it : m_listIO) {
if (it == null) {
continue;
}
if (it->isConnected() == false) {
continue;
}
for (auto &srvIt : it->getServiceList()) {
if (srvIt == _service) {
return it->getId();
}
}
}
return 0;
}
etk::Vector<etk::String> appl::GateWay::getAllServiceName() {
etk::Vector<etk::String> out;
// TODO : Change this it is old and deprecated ...
for (auto &it : m_listIO) {
if (it == null) {
continue;
}
if (it->isConnected() == false) {
continue;
}
for (auto &srvIt : it->getServiceList()) {
out.pushBack(srvIt);
}
}
return out;
}
bool appl::GateWay::send(ememory::SharedPtr<zeus::Message> _data) {
auto it = m_listIO.begin();
uint16_t id = _data->getDestinationId();
while (it != m_listIO.end()) {
if (*it == null) {
continue;
}
if ((*it)->isConnected() == false) {
continue;
}
if ((*it)->getId() == id) {
(*it)->send(_data);
return true;
}
++it;
}
return false;
}
void appl::GateWay::cleanIO() {
APPL_VERBOSE("Check if something need to be clean ...");
etk::Vector<uint16_t> tmpIDToRemove;
// Clean all IOs...
{
auto it = m_listIO.begin();
while (it != m_listIO.end()) {
if (*it != null) {
if ((*it)->isConnected() == false) {
tmpIDToRemove.pushBack((*it)->getId());
it = m_listIO.erase(it);
continue;
}
} else {
it = m_listIO.erase(it);
continue;
}
++it;
}
}
// Clean all temporary connecting IO
{
auto it = m_listTemporaryIO.begin();
while (it != m_listTemporaryIO.end()) {
if (*it != null) {
if ((*it)->isConnected() == false) {
it = m_listTemporaryIO.erase(it);
continue;
}
} else {
it = m_listTemporaryIO.erase(it);
continue;
}
++it;
}
}
// Clean router IO
if (m_routerClient != null) {
m_routerClient->clean();
}
if (tmpIDToRemove.size() != 0) {
APPL_TODO("Remove Ids ... " << tmpIDToRemove);
for (auto &it : m_listIO) {
if (it == null) {
continue;
}
if (it->isConnected() == false) {
continue;
}
// send the message the interface has been removed
zeus::WebServer* iface = it->getInterface();
uint16_t id = it->getId();
iface->call(ZEUS_ID_GATEWAY, uint32_t(id)<<16, "removeInterface", tmpIDToRemove);
APPL_WARNING("Send it to :" << id << " " << tmpIDToRemove);
}
}
// Simply display All active objkect in all interfaces:
for( auto &it : m_listIO) {
if (it == null) {
continue;
}
zeus::WebServer* tmpp = it->getInterface();
if (tmpp == null) {
continue;
}
tmpp->listObjects();
}
}
void appl::GateWay::onClientConnect(const bool& _value) {
APPL_TODO("Client connection: " << _value);
}
void appl::GateWay::onServiceConnect(const bool& _value) {
APPL_TODO("Service connection: " << _value);
}
void appl::GateWay::onPropertyChangeClientIp() {
}
void appl::GateWay::onPropertyChangeClientPort() {
}
void appl::GateWay::onPropertyChangeClientMax() {
}
void appl::GateWay::onPropertyChangeDirectClientPort() {
}
void appl::GateWay::onPropertyChangeServiceIp() {
}
void appl::GateWay::onPropertyChangeServicePort() {
}
void appl::GateWay::onPropertyChangeServiceMax() {
}
// Check if it take a long time without activity to kill itself ...
bool appl::GateWay::checkIsAlive(const echrono::Duration& _timeout) {
// if no roueter, no delay to check
if (*propertyRouterNo == true) {
return true;
}
// If no router ==> dead
if (m_routerClient == null) {
return false;
}
// check only for smallest time-out : 1 second.
if (_timeout > echrono::seconds(1)) {
echrono::Steady now = echrono::Steady::now();
echrono::Steady lastTransmission = m_routerClient->getLastTransmission();
if ((now - lastTransmission) >= _timeout) {
APPL_INFO("Detect timeout ... last transmission=" << lastTransmission);
return false;
}
}
return true;
}

View File

@ -0,0 +1,66 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <appl/IOInterface.hpp>
#include <eproperty/Value.hpp>
namespace appl {
class TcpServerInput;
class DirectInterface;
class RouterInterface;
class IOInterface;
class GateWay : public eproperty::Interface {
uint16_t m_idIncrement;
private:
ememory::SharedPtr<appl::RouterInterface> m_routerClient; //!< Interface with the Gateway Front End
ememory::SharedPtr<appl::TcpServerInput> m_interfaceNewService;
ememory::SharedPtr<appl::TcpServerInput> m_interfaceNewClient;
public:
eproperty::Value<etk::String> propertyUserName;
eproperty::Value<bool> propertyRouterNo;
eproperty::Value<etk::String> propertyRouterIp;
eproperty::Value<uint16_t> propertyRouterPort;
eproperty::Value<etk::String> propertyDirectIp;
eproperty::Value<uint16_t> propertyDirectPort;
eproperty::Value<bool> propertyServiceExtern;
eproperty::Value<etk::String> propertyServiceIp;
eproperty::Value<uint16_t> propertyServicePort;
eproperty::Value<uint16_t> propertyServiceMax;
public:
etk::Vector<ememory::SharedPtr<appl::DirectInterface>> m_listTemporaryIO; //!< List of all service availlable with their specific connection interface
etk::Vector<ememory::SharedPtr<appl::IOInterface>> m_listIO;
void addIO(const ememory::SharedPtr<appl::IOInterface>& _io);
void removeIO(const ememory::SharedPtr<appl::IOInterface>& _io);
public:
GateWay();
virtual ~GateWay();
void start();
void stop();
//ememory::SharedPtr<appl::ServiceInterface> get(const etk::String& _serviceName);
etk::Vector<etk::String> getAllServiceName();
bool send(ememory::SharedPtr<zeus::Message> _data);
void newDirectInterface(enet::Tcp _connection, bool _serviceAccess);
void cleanIO();
private:
void onPropertyChangeClientIp();
void onPropertyChangeClientPort();
void onPropertyChangeClientMax();
void onPropertyChangeDirectClientPort();
void onPropertyChangeServiceIp();
void onPropertyChangeServicePort();
void onPropertyChangeServiceMax();
void onClientConnect(const bool& _value);
void onServiceConnect(const bool& _value);
public:
uint16_t getId();
bool serviceExist(const etk::String& _service);
uint16_t serviceClientIdGet(const etk::String& _service);
// Check if it take a long time without activity to kill itself ...
bool checkIsAlive(const echrono::Duration& _timeout);
};
}

View File

@ -0,0 +1,328 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <appl/IOInterface.hpp>
#include <zeus/Future.hpp>
#include <appl/GateWay.hpp>
#include <enet/TcpClient.hpp>
#include <zeus/AbstractFunction.hpp>
static const etk::String protocolError = "PROTOCOL-ERROR";
appl::IOInterface::IOInterface() {
m_uid = 0;
m_state = appl::clientState::unconnect;
APPL_INFO("------------");
APPL_INFO("-- NEW IO --");
APPL_INFO("------------");
}
appl::IOInterface::~IOInterface() {
APPL_INFO("---------------");
APPL_INFO("-- DELETE IO --");
APPL_INFO("---------------");
// TODO : ... m_gateway->removeIO(sharedFromThis());
}
void appl::IOInterface::answerProtocolError(uint32_t _transactionId, const etk::String& _errorHelp) {
zeus::WebServer* iface = getInterface();
iface->answerError(_transactionId, 0, ZEUS_ID_SERVICE_ROOT, protocolError, _errorHelp);
//m_interfaceRouterClient->sendCtrl(m_routeurUID, ZEUS_ID_SERVICE_ROOT, "DISCONNECT");
APPL_TODO("Do this error return ... " << _errorHelp);
m_state = appl::clientState::disconnect;
}
bool appl::IOInterface::start(appl::GateWay* _gateway, uint16_t _id, bool _directClientConnection) {
m_gateway = _gateway;
m_uid = _id;
if (m_uid != 0) {
m_state = appl::clientState::connect;
} else {
if (_directClientConnection == true) {
m_state = appl::clientState::connect;
} else {
m_state = appl::clientState::connectDirect;
}
}
//m_interfaceRouterClient->setInterfaceName("cli-" + etk::toString(m_uid));
APPL_WARNING("[" << m_uid << "] New IO interface");
return true;
}
const etk::Vector<etk::String>& appl::IOInterface::getServiceList() {
return m_listService;
}
void appl::IOInterface::receive(ememory::SharedPtr<zeus::Message> _value) {
if (_value == null) {
return;
}
APPL_INFO("RECEIVE message " << _value);
uint32_t transactionId = _value->getTransactionId();
if (transactionId == 0) {
APPL_ERROR("Protocol error ==> missing id");
answerProtocolError(transactionId, "missing parameter: 'id'");
return;
}
// Check if we are the destinated Of this message
if ( _value->getDestinationId() == ZEUS_ID_GATEWAY
&& _value->getDestinationObjectId() == ZEUS_ID_GATEWAY_OBJECT) {
if (_value->getType() != zeus::message::type::call) {
APPL_ERROR("Protocol error ==>missing 'call'");
answerProtocolError(transactionId, "missing parameter: 'call' / wrong type 'call'");
return;
}
ememory::SharedPtr<zeus::message::Call> callObj = ememory::staticPointerCast<zeus::message::Call>(_value);
etk::String callFunction = callObj->getCall();
if (callFunction == "removeRouterClient") {
// TODO : Broadcast that an IO is remoed ...
m_state = appl::clientState::unconnect;
APPL_ERROR("Remote client disconnect ...");
zeus::WebServer* iface = getInterface();
iface->answerVoid(transactionId, _value->getDestination(), _value->getSource());
return;
}
switch (m_state) {
case appl::clientState::disconnect:
case appl::clientState::unconnect:
{
APPL_ERROR("Must never appear");
answerProtocolError(transactionId, "Gateway internal error");
return;
}
case appl::clientState::connectDirect:
{
if (callFunction != "service") {
answerProtocolError(transactionId, "Client must call: service");
return;
}
if (callFunction == "service") {
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), true);
m_gateway->addIO(sharedFromThis());
m_state = appl::clientState::clientIdentify;
return;
}
}
case appl::clientState::connect:
{
/*
m_clientServices.clear();
m_clientgroups.clear();
m_clientName.clear();
*/
if ( callFunction != "identify"
&& callFunction != "auth"
&& callFunction != "anonymous"
&& callFunction != "link") {
answerProtocolError(transactionId, "Client must call: identify/auth/anonymous/link");
return;
}
#if 0
if (callFunction == "identify") {
etk::String clientName = callObj->getParameter<etk::String>(0);
etk::String clientTocken = callObj->getParameter<etk::String>(1);
if (m_userService == null) {
answerProtocolError(transactionId, "gateWay internal error 3");
return;
}
zeus::Future<bool> fut = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "checkTocken", clientName, clientTocken);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceRouterClient->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
m_interfaceRouterClient->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = clientName;
}
if (callFunction == "auth") {
etk::String password = callObj->getParameter<etk::String>(0);
zeus::Future<bool> fut = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "checkAuth", password);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceRouterClient->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
m_interfaceRouterClient->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = m_userConnectionName;
}
if (callFunction == "anonymous") {
m_clientName = "";
}
#endif
#if 0
// --------------------------------
// -- Get groups:
// --------------------------------
zeus::Future<etk::Vector<etk::String>> futGroup = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "clientGroupsGet", m_clientName);
futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceRouterClient->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "grouping error");
return;
}
m_clientgroups = futGroup.get();
// --------------------------------
// -- Get services:
// --------------------------------
etk::Vector<etk::String> currentServices = m_gatewayInterface->getAllServiceName();
zeus::Future<etk::Vector<etk::String>> futServices = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "filterClientServices", m_clientName, currentServices);
futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceRouterClient->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "service filtering error");
return;
}
m_clientServices = futServices.get();
APPL_WARNING("Connection of: '" << m_clientName << "' to '" << m_userConnectionName << "'");
APPL_WARNING(" groups: " << etk::toString(m_clientgroups));
APPL_WARNING(" services: " << etk::toString(m_clientServices));
#endif
m_gateway->addIO(sharedFromThis());
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), true);
m_state = appl::clientState::clientIdentify;
return;
}
if (callFunction == "link") {
// TODO : Filter services access ...
etk::String serviceName = callObj->getParameter<etk::String>(0);
if (m_gateway->serviceExist(serviceName) == false) {
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
return;
}
uint16_t serviceClientId = m_gateway->serviceClientIdGet(serviceName);
if (serviceClientId == 0) {
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
return;
}
// Replace the destination with the real owner ID
_value->setDestinationId(serviceClientId);
// Forward Call
if (m_gateway->send(_value) == false) {
zeus::WebServer* iface = getInterface();
iface->answerError(transactionId, _value->getDestination(), _value->getSource(), "UNEXISTING-CLIENT");
}
// We do not answer, we just transmit the message to the interface that manage the service that might answer ot this call ...
return;
}
break;
case appl::clientState::clientIdentify:
{
if (callFunction == "serviceAdd") {
zeus::WebServer* iface = getInterface();
etk::String serviceName = callObj->getParameter<etk::String>(0);
if (serviceName == "") {
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
return;
}
// Check if service exist or not:
if (m_gateway->serviceExist(serviceName) == true) {
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
return;
}
ZEUS_INFO("Register new service '" << serviceName << "' in " << m_uid);
m_listService.pushBack(serviceName);
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), true);
return;
}
if (callFunction == "serviceRemove") {
zeus::WebServer* iface = getInterface();
etk::String serviceName = callObj->getParameter<etk::String>(0);
if (serviceName == "") {
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
}
auto it = m_listService.begin();
while (it != m_listService.end()) {
if (*it == serviceName) {
it = m_listService.erase(it);
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), true);
ZEUS_INFO("Remove new service " << serviceName << "' in " << m_uid);
return;
}
++it;
}
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
return;
}
// This is 2 default service for the cient interface that manage the authorisation of view:
if (callFunction == "getServiceCount") {
// TODO : Fileter the size of accessible services
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), m_gateway->getAllServiceName().size());
return;
}
if (callFunction == "getServiceList") {
// TODO : Fileter the size of accessible services
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), m_gateway->getAllServiceName());
return;
}
if (callFunction == "link") {
// TODO : Filter services access ...
etk::String serviceName = callObj->getParameter<etk::String>(0);
if (m_gateway->serviceExist(serviceName) == false) {
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
return;
}
uint16_t serviceClientId = m_gateway->serviceClientIdGet(serviceName);
if (serviceClientId == 0) {
zeus::WebServer* iface = getInterface();
iface->answerValue(transactionId, _value->getDestination(), _value->getSource(), false);
return;
}
// Replace the destination with the real owner ID
_value->setDestinationId(serviceClientId);
// Forward Call
if (m_gateway->send(_value) == false) {
zeus::WebServer* iface = getInterface();
iface->answerError(transactionId, _value->getDestination(), _value->getSource(), "UNEXISTING-CLIENT");
}
// We do not answer, we just transmit the message to the interface that manage the service that might answer ot this call ...
return;
}
APPL_ERROR("Function does not exist ... '" << callFunction << "'");
zeus::WebServer* iface = getInterface();
iface->answerError(transactionId, _value->getDestination(), _value->getSource(), "CALL-UNEXISTING");
return;
}
return;
}
{
APPL_ERROR("UNKNOW error ... " << _value);
zeus::WebServer* iface = getInterface();
iface->answerError(transactionId, _value->getDestination(), _value->getSource(), "REQUEST-ERROR");
}
} else {
// TODO: Check here if the user is athorised to send data to a specific client ...
if (m_gateway != null) {
m_gateway->send(_value);
}
}
}

View File

@ -0,0 +1,49 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <zeus/WebServer.hpp>
#include <appl/GateWay.hpp>
namespace appl {
class GateWay;
enum class clientState {
unconnect, // starting sate
connect, // zeus get a TCP connection (through the Router)
connectDirect, // zeus get a TCP connection 5direct connection on the gateway)
clientIdentify, // client defien the mode of the acces (anonymous,client/user)
disconnect // client is dead or loal disconnection
};
class IOInterface : public ememory::EnableSharedFromThis<appl::IOInterface> {
public:
appl::GateWay* m_gateway;
protected:
uint16_t m_uid; //!< Client unique ID (for routing)
etk::Vector<etk::String> m_listService;
public:
const etk::Vector<etk::String>& getServiceList();
public:
enum clientState m_state; // state machine ...
IOInterface();
virtual ~IOInterface();
bool start(appl::GateWay* _gateway, uint16_t _id, bool _directClientConnection = false);
// Data arrive from the IO
virtual void receive(ememory::SharedPtr<zeus::Message> _value);
// Data must be send to the IO
virtual void send(ememory::SharedPtr<zeus::Message> _data) = 0;
// Verify wich ID is provided by the IO
bool checkId(uint16_t _id) const {
return m_uid == _id;
}
uint16_t getId() const {
return m_uid;
}
void answerProtocolError(uint32_t _transactionId, const etk::String& _errorHelp);
virtual zeus::WebServer* getInterface() = 0;
virtual bool isConnected() { return false; };
};
}

View File

@ -0,0 +1,426 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <appl/RouterInterface.hpp>
#include <zeus/Future.hpp>
#include <appl/GateWay.hpp>
#include <enet/TcpClient.hpp>
#include <zeus/AbstractFunction.hpp>
static const etk::String protocolError = "PROTOCOL-ERROR";
appl::clientSpecificInterface::clientSpecificInterface() {
m_uid = 0;
m_state = appl::clientState::unconnect;
APPL_INFO("-------------------------------");
APPL_INFO("-- NEW Client (threw router) --");
APPL_INFO("-------------------------------");
}
appl::clientSpecificInterface::~clientSpecificInterface() {
APPL_INFO("----------------------------------");
APPL_INFO("-- DELETE Client (threw router) --");
APPL_INFO("----------------------------------");
}
zeus::WebServer* appl::clientSpecificInterface::getInterface() {
return m_interfaceWeb;
}
bool appl::clientSpecificInterface::isConnected() {
if (m_interfaceWeb == null) {
return false;
}
if (m_state == appl::clientState::unconnect) {
return false;
}
return m_interfaceWeb->isActive();
};
bool appl::clientSpecificInterface::start(appl::GateWay* _gateway, zeus::WebServer* _interfaceWeb, uint16_t _id) {
appl::IOInterface::start(_gateway, _id);
m_interfaceWeb = _interfaceWeb;
APPL_WARNING("[" << m_uid << "] New client : " << m_clientName);
return true;
}
void appl::clientSpecificInterface::send(ememory::SharedPtr<zeus::Message> _value) {
m_interfaceWeb->writeBinary(_value);
}
#if 0
void appl::clientSpecificInterface::receive(ememory::SharedPtr<zeus::Message> _value) {
if (_value == null) {
return;
}
//APPL_ERROR(" ==> parse DATA ...");
uint32_t transactionId = _value->getTransactionId();
if (transactionId == 0) {
APPL_ERROR("Protocol error ==>missing id");
answerProtocolError(transactionId, "missing parameter: 'id'");
return;
}
if (_value->getType() == zeus::Message::type::data) {
// TRANSMIT DATA ...
if (m_state != appl::clientState::clientIdentify) {
answerProtocolError(transactionId, "Not identify to send 'data' buffer (multiple packet element)");
return;
}
uint32_t serviceId = _value->getServiceId();
if (serviceId == 0) {
answerProtocolError(transactionId, "Can not send multiple data on the gateway");
return;
}
serviceId--;
if (serviceId >= m_listConnectedService.size()) {
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "NOT-CONNECTED-SERVICE");
return;
}
if (m_listConnectedService[serviceId] == null) {
// TODO ...
APPL_ERROR("TODO : Manage this case ...");
return;
}
m_listConnectedService[serviceId]->m_interfaceClient.callForwardMultiple(
m_uid,
_value,
(uint64_t(m_uid) << 32) + uint64_t(transactionId));
return;
}
if (_value->getType() != zeus::Message::type::call) {
APPL_ERROR("Protocol error ==>missing 'call'");
answerProtocolError(transactionId, "missing parameter: 'call' / wrong type 'call'");
return;
}
ememory::SharedPtr<zeus::message::Call> callObj = ememory::staticPointerCast<zeus::message::Call>(_value);
etk::String callFunction = callObj->getCall();
switch (m_state) {
case appl::clientState::disconnect:
case appl::clientState::unconnect:
{
APPL_ERROR("Must never appear");
answerProtocolError(transactionId, "Gateway internal error");
return;
}
case appl::clientState::connect:
{
uint32_t serviceId = callObj->getServiceId();
if (serviceId != 0) {
APPL_ERROR("Call at a service at this state is not allowed serviceID=" << serviceId);
answerProtocolError(transactionId, "MISSING IDENTIFICATION STEP");
return;
}
m_clientServices.clear();
m_clientgroups.clear();
m_clientName.clear();
if ( callFunction != "identify"
&& callFunction != "auth"
&& callFunction != "anonymous") {
answerProtocolError(transactionId, "Client must call: identify/auth/anonymous");
return;
}
if (callFunction == "identify") {
etk::String clientName = callObj->getParameter<etk::String>(0);
etk::String clientTocken = callObj->getParameter<etk::String>(1);
if (m_userService == null) {
answerProtocolError(transactionId, "gateWay internal error 3");
return;
}
zeus::Future<bool> fut = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "checkTocken", clientName, clientTocken);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = clientName;
}
if (callFunction == "auth") {
etk::String password = callObj->getParameter<etk::String>(0);
zeus::Future<bool> fut = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "checkAuth", password);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = m_userConnectionName;
}
if (callFunction == "anonymous") {
m_clientName = "";
}
// --------------------------------
// -- Get groups:
// --------------------------------
zeus::Future<etk::Vector<etk::String>> futGroup = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "clientGroupsGet", m_clientName);
futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "grouping error");
return;
}
m_clientgroups = futGroup.get();
// --------------------------------
// -- Get services:
// --------------------------------
etk::Vector<etk::String> currentServices = m_gatewayInterface->getAllServiceName();
zeus::Future<etk::Vector<etk::String>> futServices = m_userService->m_interfaceClient.call(m_localIdUser, ZEUS_ID_SERVICE_ROOT, "filterClientServices", m_clientName, currentServices);
futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) {
APPL_ERROR("Get error from the service ...");
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), false);
answerProtocolError(transactionId, "service filtering error");
return;
}
m_clientServices = futServices.get();
APPL_WARNING("Connection of: '" << m_clientName << "' to '" << m_userConnectionName << "'");
APPL_WARNING(" groups: " << etk::toString(m_clientgroups));
APPL_WARNING(" services: " << etk::toString(m_clientServices));
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), true);
m_state = appl::clientState::clientIdentify;
return;
}
break;
case appl::clientState::clientIdentify:
{
uint32_t serviceId = callObj->getServiceId();
if (serviceId == 0) {
// This is 2 default service for the cient interface that manage the authorisation of view:
if (callFunction == "getServiceCount") {
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), m_clientServices.size());
return;
}
if (callFunction == "getServiceList") {
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), m_clientServices);
//"ServiceManager/v0.1.0"
return;
}
if (callFunction == "link") {
// first param:
etk::String serviceName = callObj->getParameter<etk::String>(0);
ZEUS_ERROR("Connect to service : " << serviceName << " " << m_uid);
// Check if service already link:
auto it = m_listConnectedService.begin();
while (it != m_listConnectedService.end()) {
if (*it == null) {
++it;
continue;
}
if ((*it)->getName() != serviceName) {
++it;
continue;
}
break;
}
if (it == m_listConnectedService.end()) {
// check if service is connectable ...
if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) {
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "UN-AUTHORIZED-SERVICE");
return;
}
ememory::SharedPtr<appl::ServiceInterface> srv = m_gatewayInterface->get(serviceName);
if (srv != null) {
zeus::Future<bool> futLink = srv->m_interfaceClient.call(m_uid, ZEUS_ID_SERVICE_ROOT, "_new", m_userConnectionName, m_clientName, m_clientgroups);
futLink.wait(); // TODO: Set timeout ...
if (futLink.hasError() == true) {
APPL_ERROR("Get error from the service ... LINK");
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService.pushBack(srv);
ZEUS_ERROR(" ==> get ID : " << m_uid);
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), m_listConnectedService.size());
return;
}
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "CAN-NOT-CONNECT-SERVICE");
return;
}
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "SERVICE-ALREADY-CONNECTED");;
return;
}
if (callFunction == "unlink") {
ZEUS_ERROR("Disconnnect from service : " << m_uid);
// first param: the service we want to unconnect ...
int64_t localServiceID = callObj->getParameter<int64_t>(0)-1;
// Check if service already link:
if (localServiceID >= m_listConnectedService.size()) {
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "NOT-CONNECTED-SERVICE");
return;
}
zeus::Future<bool> futUnLink = m_listConnectedService[localServiceID]->m_interfaceClient.call(m_uid, ZEUS_ID_SERVICE_ROOT, "_delete");
futUnLink.wait(); // TODO: Set timeout ...
if (futUnLink.hasError() == true) {
APPL_ERROR("Get error from the service ... UNLINK");
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService[localServiceID] = null;
m_interfaceWeb->answerValue(transactionId, _value->getClientId(), _value->getServiceId(), true);
return;
}
APPL_ERROR("Function does not exist ... '" << callFunction << "'");
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "CALL-UNEXISTING");
return;
}
// decrease service ID ...
serviceId -= 1;
if (serviceId >= m_listConnectedService.size()) {
m_interfaceWeb->answerError(transactionId, _value->getClientId(), _value->getServiceId(), "NOT-CONNECTED-SERVICE");
return;
} else {
if (m_listConnectedService[serviceId] == null) {
// TODO ...
APPL_ERROR("TODO : Manage this case ...");
return;
}
auto fut = m_listConnectedService[serviceId]->m_interfaceClient.callForward(m_uid, _value, (uint64_t(m_uid) << 32) + uint64_t(transactionId));
fut.andAll([=](zeus::FutureBase _ret) {
ememory::SharedPtr<zeus::Message> tmpp = _ret.getRaw();
if (tmpp == null) {
return true;
}
APPL_DEBUG(" ==> transmit : " << tmpp->getTransactionId() << " -> " << transactionId);
APPL_DEBUG(" msg=" << tmpp);
tmpp->setTransactionId(transactionId);
tmpp->setClientId(m_routeurUID);
tmpp->setServiceId(serviceId+1);
APPL_DEBUG("transmit=" << tmpp);
m_interfaceWeb->writeBinary(tmpp);
// multiple send element ...
return tmpp->getPartFinish();
});
}
}
}
}
#endif
appl::RouterInterface::RouterInterface(const etk::String& _ip, uint16_t _port, etk::String _userName, appl::GateWay* _gateway, uint32_t _directPort) :
m_state(appl::clientState::unconnect),
m_gateway(_gateway),
m_interfaceWeb() {
APPL_INFO("----------------------------------------");
APPL_INFO("-- NEW Connection to the ROUTER --");
APPL_INFO("----------------------------------------");
enet::Tcp connection = etk::move(enet::connectTcpClient(_ip, _port));
if (connection.getConnectionStatus() != enet::Tcp::status::link) {
APPL_ERROR("Can not connect the GateWay-front-end");
return;
}
etk::String uri = _userName;
if (_directPort != 0) {
uri += "?directAccessPort=" + etk::toString(_directPort);
}
m_interfaceWeb.setInterface(etk::move(connection), false, uri);
m_interfaceWeb.connect(this, &appl::RouterInterface::onClientData);
m_interfaceWeb.connect(true);
m_interfaceWeb.setInterfaceName("cli-GW-to-router");
// TODO : Check if user name is accepted ...
}
appl::RouterInterface::~RouterInterface() {
APPL_TODO("Call All unlink ...");
stop();
APPL_INFO("-------------------------------------------");
APPL_INFO("-- DELETE Connection to the ROUTER --");
APPL_INFO("-------------------------------------------");
}
void appl::RouterInterface::stop() {
/* TODO ...
for (auto &it : m_listConnectedService) {
if (it == null) {
continue;
}
it->m_interfaceClient.callClient(m_uid, "_delete");
}
if (m_userService != null) {
m_userService->m_interfaceClient.callClient(m_uid2, "_delete");
m_userService = null;
}
m_listConnectedService.clear();
*/
m_interfaceWeb.disconnect();
}
bool appl::RouterInterface::isAlive() {
return m_interfaceWeb.isActive();
}
void appl::RouterInterface::onClientData(ememory::SharedPtr<zeus::Message> _value) {
if (_value == null) {
return;
}
// Get client ID:
uint16_t sourceId = _value->getSourceId();
//APPL_ERROR("[" << clientId << "] get message from front-end gateWay: " << _value);
for (auto &it : m_listClients) {
if (it->checkId(sourceId) == true) {
it->receive(_value);
return;
}
}
m_listClients.pushBack(ememory::makeShared<clientSpecificInterface>());
size_t localId = m_listClients.size()-1;
bool ret = m_listClients[localId]->start(m_gateway, &m_interfaceWeb, sourceId);
if (ret == false) {
return;
}
m_listClients[localId]->receive(_value);
}
void appl::RouterInterface::send(const ememory::SharedPtr<zeus::Message>& _data) {
m_interfaceWeb.writeBinary(_data);
}
void appl::RouterInterface::clean() {
auto it = m_listClients.begin();
while (it != m_listClients.end()) {
if ((*it)->m_state == appl::clientState::disconnect) {
it = m_listClients.erase(it);
continue;
}
++it;
}
}
echrono::Steady appl::RouterInterface::getLastTransmission() {
auto receive = m_interfaceWeb.getLastTimeReceive();
auto send = m_interfaceWeb.getLastTimeSend();
if (receive >= send) {
if (receive == 0) {
return echrono::Steady::now();
}
return receive;
}
if (send == 0) {
return echrono::Steady::now();
}
return send;
}

View File

@ -0,0 +1,46 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <zeus/WebServer.hpp>
#include <appl/GateWay.hpp>
#include <appl/IOInterface.hpp>
namespace appl {
class GateWay;
class clientSpecificInterface : public appl::IOInterface {
public:
zeus::WebServer* m_interfaceWeb;
public:
etk::String m_clientName;
clientSpecificInterface();
~clientSpecificInterface();
bool start(appl::GateWay* _gateway, zeus::WebServer* _interfaceWeb, uint16_t _id);
void send(ememory::SharedPtr<zeus::Message> _data);
//void answerProtocolError(uint32_t _transactionId, const etk::String& _errorHelp);
zeus::WebServer* getInterface();
bool isConnected();
};
class RouterInterface {
private:
enum clientState m_state; // state machine ..
etk::Vector<ememory::SharedPtr<clientSpecificInterface>> m_listClients; // TODO : Maybe remove this ...
private:
appl::GateWay* m_gateway;
zeus::WebServer m_interfaceWeb;
public:
RouterInterface(const etk::String& _ip, uint16_t _port, etk::String _userName, appl::GateWay* _gateway, uint32_t _directPort);
virtual ~RouterInterface();
void stop();
void onClientData(ememory::SharedPtr<zeus::Message> _value);
bool isAlive();
void send(const ememory::SharedPtr<zeus::Message>& _data);
void clean();
echrono::Steady getLastTransmission();
};
}

View File

@ -1,12 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.h>
#include <appl/debug.hpp>
int32_t appl::getLogId() {
static int32_t g_val = elog::registerInstance("jus-gateway");
static int32_t g_val = elog::registerInstance("zeus-gateway");
return g_val;
}

View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <elog/log.hpp>
namespace appl {
int32_t getLogId();
};
#define APPL_BASE(info,data) ELOG_BASE(appl::getLogId(),info,data)
#define APPL_PRINT(data) APPL_BASE(-1, data)
#define APPL_CRITICAL(data) APPL_BASE(1, data)
#define APPL_ERROR(data) APPL_BASE(2, data)
#define APPL_WARNING(data) APPL_BASE(3, data)
#define APPL_INFO(data) APPL_BASE(4, data)
#ifdef DEBUG
#define APPL_DEBUG(data) APPL_BASE(5, data)
#define APPL_VERBOSE(data) APPL_BASE(6, data)
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
#else
#define APPL_DEBUG(data) do { } while(false)
#define APPL_VERBOSE(data) do { } while(false)
#define APPL_TODO(data) do { } while(false)
#endif
#define APPL_ASSERT(cond,data) \
do { \
if (!(cond)) { \
APPL_CRITICAL(data); \
assert(!#cond); \
} \
} while (0)

View File

@ -0,0 +1,362 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <appl/GateWay.hpp>
#include <etk/etk.hpp>
#include <etk/path/fileSystem.hpp>
#include <zeus/zeus.hpp>
#include <etk/Allocator.hpp>
#include <etk/uri/uri.hpp>
#include <etk/stdTools.hpp>
#define GATEWAY_ENABLE_LAUNCHER
#ifdef GATEWAY_ENABLE_LAUNCHER
#include <ethread/Mutex.hpp>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <ethread/Thread.hpp>
#include <etk/stdTools.hpp>
#include <zeus/Object.hpp>
#include <zeus/Client.hpp>
#include <zeus/zeus.hpp>
typedef bool (*SERVICE_IO_init_t)(int _argc, const char *_argv[], etk::Uri _basePath);
typedef bool (*SERVICE_IO_uninit_t)();
typedef void (*SERVICE_IO_peridic_call_t)();
typedef zeus::Object* (*SERVICE_IO_instanciate_t)(uint32_t, ememory::SharedPtr<zeus::WebServer>&, uint32_t);
class PlugginAccess {
private:
etk::String m_name;
etk::String m_fullName;
void* m_handle;
SERVICE_IO_init_t m_SERVICE_IO_init;
SERVICE_IO_uninit_t m_SERVICE_IO_uninit;
SERVICE_IO_peridic_call_t m_SERVICE_IO_peridic_call;
SERVICE_IO_instanciate_t m_SERVICE_IO_instanciate;
public:
PlugginAccess(const etk::String& _name, const etk::String& _fullName) :
m_name(_name),
m_fullName(_fullName),
m_handle(null),
m_SERVICE_IO_init(null),
m_SERVICE_IO_uninit(null),
m_SERVICE_IO_instanciate(null) {
etk::Path srv = etk::path::getBinaryDirectory() / ".." / "lib" / "lib" + m_fullName + "-impl.so";
APPL_PRINT("++++++++++++++++++++++++++++++++");
APPL_PRINT("++ srv: '" << m_name << "' ");
APPL_PRINT("++++++++++++++++++++++++++++++++");
APPL_PRINT("At position: '" << srv << "'");
APPL_PRINT("with full name=" << m_fullName);
m_handle = dlopen(srv.getNative().c_str(), RTLD_LAZY);
if (!m_handle) {
APPL_ERROR("Can not load Lbrary:" << dlerror());
return;
}
char *error = null;
m_SERVICE_IO_init = (SERVICE_IO_init_t)dlsym(m_handle, "SERVICE_IO_init");
error = dlerror();
if (error != null) {
m_SERVICE_IO_init = null;
APPL_WARNING("Can not function SERVICE_IO_init :" << error);
}
m_SERVICE_IO_uninit = (SERVICE_IO_uninit_t)dlsym(m_handle, "SERVICE_IO_uninit");
error = dlerror();
if (error != null) {
m_SERVICE_IO_uninit = null;
APPL_WARNING("Can not function SERVICE_IO_uninit :" << error);
}
m_SERVICE_IO_peridic_call = (SERVICE_IO_peridic_call_t)dlsym(m_handle, "SERVICE_IO_peridic_call");
error = dlerror();
if (error != null) {
m_SERVICE_IO_uninit = null;
APPL_WARNING("Can not function SERVICE_IO_uninit :" << error);
}
m_SERVICE_IO_instanciate = (SERVICE_IO_instanciate_t)dlsym(m_handle, "SERVICE_IO_instanciate");
error = dlerror();
if (error != null) {
m_SERVICE_IO_instanciate = null;
APPL_WARNING("Can not function SERVICE_IO_instanciate:" << error);
}
}
~PlugginAccess() {
}
bool init(int _argc, const char *_argv[], etk::Uri _basePath) {
if (m_SERVICE_IO_init == null) {
return false;
}
if (_basePath.isEmpty() == true) {
_basePath = "USER_DATA:///" + m_name;
APPL_PRINT("Use base path: " << _basePath);
} else {
_basePath /= m_name;
}
return (*m_SERVICE_IO_init)(_argc, _argv, _basePath);
}
bool publish(zeus::Client& _client) {
if (m_SERVICE_IO_instanciate == null) {
return false;
}
_client.serviceAdd(m_name, [=](uint32_t _transactionId, ememory::SharedPtr<zeus::WebServer>& _iface, uint32_t _destination) {
(*m_SERVICE_IO_instanciate)(_transactionId, _iface, _destination);
});
return true;
}
bool disconnect(zeus::Client& _client) {
_client.serviceRemove(m_name);
return true;
}
bool uninit() {
if (m_SERVICE_IO_uninit == null) {
return false;
}
return (*m_SERVICE_IO_uninit)();
}
void peridic_call() {
if (m_SERVICE_IO_peridic_call == null) {
return;
}
(*m_SERVICE_IO_peridic_call)();
}
const etk::String getName() const {
return m_name;
}
};
#endif
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
zeus::init(_argc, _argv);
appl::GateWay basicGateway;
#ifdef GATEWAY_ENABLE_LAUNCHER
etk::Uri basePath;
etk::Vector<etk::String> services;
zeus::Client m_client;
// The default service port is 1985
m_client.propertyPort.set(1985);
#endif
// default delay to disconnect is 30 seconds:
uint32_t routerDisconnectionDelay = 30;
for (int32_t iii=0; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
APPL_PRINT("parameter: [" << iii << "] '" << data << "'");
if (etk::start_with(data, "--user=") == true) {
basicGateway.propertyUserName.set(etk::String(&data[7]));
} else if (data == "--no-router") {
basicGateway.propertyRouterNo.set(true);
} else if (etk::start_with(data, "--router-ip=") == true) {
basicGateway.propertyRouterIp.set(etk::String(&data[12]));
} else if (etk::start_with(data, "--router-port=") == true) {
basicGateway.propertyRouterPort.set(etk::string_to_uint16_t(etk::String(&data[14])));
} else if (etk::start_with(data, "--direct-ip=") == true) {
basicGateway.propertyDirectIp.set(etk::String(&data[12]));
} else if (etk::start_with(data, "--direct-port=") == true) {
basicGateway.propertyDirectPort.set(etk::string_to_uint16_t(etk::String(&data[14])));
} else if (etk::start_with(data, "--router-delay=") == true) {
int32_t value = etk::string_to_int32_t(etk::String(&data[15]));
if (value == -1) {
routerDisconnectionDelay = 999999999;
} else if (value == 0) {
// do nothing
} else {
routerDisconnectionDelay = value;
}
} else if (etk::start_with(data, "--service-extern=") == true) {
bool value = false;
if (data == "--service-extern=true") {
value = true;
}
basicGateway.propertyServiceExtern.set(value);
} else if (etk::start_with(data, "--service-ip=") == true) {
basicGateway.propertyServiceIp.set(etk::String(&data[13]));
#ifdef GATEWAY_ENABLE_LAUNCHER
m_client.propertyIp.set(etk::String(&data[13]));
#endif
} else if (etk::start_with(data, "--service-port=") == true) {
basicGateway.propertyServicePort.set(etk::string_to_uint16_t(etk::String(&data[15])));
#ifdef GATEWAY_ENABLE_LAUNCHER
m_client.propertyPort.set(etk::string_to_uint16_t(etk::String(&data[15])));
#endif
} else if (etk::start_with(data, "--service-max=") == true) {
basicGateway.propertyServiceMax.set(etk::string_to_uint16_t(etk::String(&data[14])));
#ifdef GATEWAY_ENABLE_LAUNCHER
} else if (etk::start_with(data, "--base-path=") == true) {
basePath = etk::Path(etk::String(&data[12]));
} else if (etk::start_with(data, "--srv=") == true) {
services.pushBack(etk::String(&data[6]));
#endif
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --user=XXX Name of the user that we are connected.");
APPL_PRINT(" --no-router Router connection disable ==> this enable the direct donnection of external client like on the router");
APPL_PRINT(" --router-ip=XXX Router connection IP (default: " << basicGateway.propertyRouterIp.get() << ")");
APPL_PRINT(" --router-port=XXX Router connection PORT (default: " << basicGateway.propertyRouterPort.get() << ")");
APPL_PRINT(" --direct-ip=XXX Direct connection IP (default: " << basicGateway.propertyDirectIp.get() << ")");
APPL_PRINT(" --direct-port=XXX Direct connection PORT (default: " << basicGateway.propertyDirectPort.get() << " if 0 ==> not availlable)");
APPL_PRINT(" --service-extern=frue/false Disable the external service connection ==> remove open port ...(default: " << basicGateway.propertyServiceExtern.get() << ")");
APPL_PRINT(" --service-ip=XXX Service connection IP (default: " << basicGateway.propertyServiceIp.get() << ")");
APPL_PRINT(" --service-port=XXX Service connection PORT (default: " << basicGateway.propertyServicePort.get() << ")");
APPL_PRINT(" --service-max=XXX Service Maximum IO (default: " << basicGateway.propertyServiceMax.get() << ")");
APPL_PRINT(" --router-delay=XXX Delay before disconnect from the router (default: " << routerDisconnectionDelay << "; 0=automatic set by the gateway; -1=never disconnect; other the time)");
#ifdef GATEWAY_ENABLE_LAUNCHER
APPL_PRINT(" specific for internal launcher:");
APPL_PRINT(" --base-path=XXX base path to search data (default: 'USERDATA:')");
APPL_PRINT(" --srv=XXX service path (N)");
#endif
return -1;
}
}
#ifdef GATEWAY_ENABLE_LAUNCHER
etk::Vector<etk::Pair<etk::String,etk::String>> listAvaillableServices;
if (services.size() != 0) {
// find all services:
etk::Path dataPath(etk::path::getBinaryDirectory() / ".." / "share");
etk::Vector<etk::Path> listSubPath = etk::path::list(dataPath, etk::path::LIST_FOLDER);
APPL_DEBUG(" Base data path: " << dataPath);
APPL_DEBUG(" SubPath: " << listSubPath);
for (auto &it: listSubPath) {
if (etk::path::exist(it / "zeus") == true) {
etk::Path dataPath(it / "zeus");
etk::Vector<etk::Path> listServices = etk::path::list(dataPath, etk::path::LIST_FILE);
for (auto &it2: listServices) {
if (it2.getExtention() != "srv") {
continue;
}
etk::String nameFileSrv = it2.getFileName();
etk::Vector<etk::String> spl = etk::String(nameFileSrv.begin(), nameFileSrv.end()-4).split("-service-");
if (spl.size() != 2) {
APPL_ERROR("reject service, wrong format ... '" << it2 << "' missing XXX-service-SERVICE-NAME.srv");
continue;
}
APPL_INFO("find service : " << it2);
listAvaillableServices.pushBack(etk::makePair(spl[1], etk::String(nameFileSrv.begin(), nameFileSrv.end()-4)));
}
} else {
// not check the second path ==> no service availlable
}
}
}
#endif
int32_t countMemeCheck = 0;
APPL_INFO("==================================");
APPL_INFO("== ZEUS gateway start ==");
APPL_INFO("==================================");
basicGateway.start();
#ifdef GATEWAY_ENABLE_LAUNCHER
if (services.size() == 0) {
bool routerAlive = true;
#endif
while (routerAlive == true) {
ethread::sleepMilliSeconds((100));
basicGateway.cleanIO();
if (countMemeCheck++ >= 200) {
countMemeCheck = 0;
ETK_MEM_SHOW_LOG(true);
}
routerAlive = basicGateway.checkIsAlive(echrono::seconds(routerDisconnectionDelay));
if (routerAlive == false) {
APPL_WARNING("Router is Dead or Timeout");
}
}
#ifdef GATEWAY_ENABLE_LAUNCHER
} else {
bool routerAlive = true;
etk::Vector<ememory::SharedPtr<PlugginAccess>> listElements;
if ( services.size() == 1
&& services[0] == "all") {
for (auto &it: listAvaillableServices) {
ememory::SharedPtr<PlugginAccess> tmp = ememory::makeShared<PlugginAccess>(it.first, it.second);
listElements.pushBack(tmp);
}
} else {
for (auto &it: services) {
// find the real service name:
bool find = false;
for (auto &it2: listAvaillableServices) {
if (it2.first == it) {
ememory::SharedPtr<PlugginAccess> tmp = ememory::makeShared<PlugginAccess>(it2.first, it2.second);
listElements.pushBack(tmp);
find = true;
break;
}
}
if (find == false) {
APPL_ERROR("Can not find the service: " << it);
}
}
}
APPL_WARNING("=================================================");
APPL_WARNING("== INIT All service");
APPL_WARNING("=================================================");
for (auto &it: listElements) {
APPL_WARNING(" init: " << it->getName());
it->init(_argc, _argv, basePath);
}
APPL_WARNING("=================================================");
APPL_WARNING("== check client connected:");
APPL_WARNING("=================================================");
if (m_client.connect() == false) {
APPL_WARNING(" ==> not connected");
return -1;
}
APPL_WARNING("=================================================");
APPL_WARNING("== Publish all service");
APPL_WARNING("=================================================");
for (auto &it: listElements) {
APPL_WARNING(" publish: " << it->getName());
it->publish(m_client);
}
uint32_t iii = 0;
while ( m_client.isAlive() == true
&& routerAlive == true) {
m_client.pingIsAlive();
m_client.displayConnectedObject();
m_client.cleanDeadObject();
for (auto &it: listElements) {
it->peridic_call();
}
basicGateway.cleanIO();
routerAlive = basicGateway.checkIsAlive(echrono::seconds(routerDisconnectionDelay));
if (routerAlive == false) {
APPL_WARNING("Router is Dead or Timeout");
} else {
elog::flush();
ethread::sleepMilliSeconds(1000);
if (countMemeCheck++ >= 20) {
countMemeCheck = 0;
ETK_MEM_SHOW_LOG(true);
}
APPL_INFO("gateway in waiting ... " << iii << "/inf");
}
iii++;
}
for (auto &it: listElements) {
it->disconnect(m_client);
}
m_client.disconnect();
APPL_INFO("Stop service*** ==> flush internal datas ...");
for (auto &it: listElements) {
it->uninit();
}
}
#endif
basicGateway.stop();
APPL_INFO("==================================");
APPL_INFO("== ZEUS gateway stop ==");
APPL_INFO("==================================");
elog::flush();
return 0;
}

View File

@ -0,0 +1,42 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
def get_type():
return "BINARY"
def get_sub_type():
return "TOOLS"
def get_desc():
return "ZEUS generic gateway"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module):
my_module.add_path(".")
my_module.add_depend(['zeus'])
my_module.add_src_file([
'appl/debug.cpp',
'appl/IOInterface.cpp',
'appl/RouterInterface.cpp',
#'appl/ServiceInterface.cpp',
'appl/DirectInterface.cpp',
'appl/GateWay.cpp',
'appl/main-gateway.cpp'
])
return True

View File

@ -0,0 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
int32_t appl::getLogId() {
static int32_t g_val = elog::registerInstance("zeus-launcher");
return g_val;
}

View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <elog/log.hpp>
namespace appl {
int32_t getLogId();
};
#define APPL_BASE(info,data) ELOG_BASE(appl::getLogId(),info,data)
#define APPL_PRINT(data) APPL_BASE(-1, data)
#define APPL_CRITICAL(data) APPL_BASE(1, data)
#define APPL_ERROR(data) APPL_BASE(2, data)
#define APPL_WARNING(data) APPL_BASE(3, data)
#define APPL_INFO(data) APPL_BASE(4, data)
#ifdef DEBUG
#define APPL_DEBUG(data) APPL_BASE(5, data)
#define APPL_VERBOSE(data) APPL_BASE(6, data)
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
#else
#define APPL_DEBUG(data) do { } while(false)
#define APPL_VERBOSE(data) do { } while(false)
#define APPL_TODO(data) do { } while(false)
#endif
#define APPL_ASSERT(cond,data) \
do { \
if (!(cond)) { \
APPL_CRITICAL(data); \
assert(!#cond); \
} \
} while (0)

View File

@ -0,0 +1,205 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <etk/Allocator.hpp>
#include <etk/etk.hpp>
#include <ethread/Mutex.hpp>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <ethread/Thread.hpp>
#include <etk/stdTools.hpp>
#include <zeus/Object.hpp>
#include <zeus/Client.hpp>
#include <zeus/zeus.hpp>
#include <etk/uri/uri.hpp>
#include <etk/path/fileSystem.hpp>
typedef bool (*SERVICE_IO_init_t)(int _argc, const char *_argv[], etk::Uri _basePath);
typedef bool (*SERVICE_IO_uninit_t)();
typedef void (*SERVICE_IO_peridic_call_t)();
typedef zeus::Object* (*SERVICE_IO_instanciate_t)(uint32_t, ememory::SharedPtr<zeus::WebServer>&, uint32_t);
class PlugginAccess {
private:
etk::String m_name;
void* m_handle;
SERVICE_IO_init_t m_SERVICE_IO_init;
SERVICE_IO_uninit_t m_SERVICE_IO_uninit;
SERVICE_IO_peridic_call_t m_SERVICE_IO_peridic_call;
SERVICE_IO_instanciate_t m_SERVICE_IO_instanciate;
public:
PlugginAccess(const etk::String& _name) :
m_name(_name),
m_handle(null),
m_SERVICE_IO_init(null),
m_SERVICE_IO_uninit(null),
m_SERVICE_IO_peridic_call(null),
m_SERVICE_IO_instanciate(null) {
etk::Path srv = etk::path::getBinaryPath() / ".." / "lib" / "libzeus-service-" + m_name + "-impl.so";
APPL_PRINT("Try to open service with name: '" << m_name << "' at position: '" << srv << "'");
m_handle = dlopen(srv.getNative().c_str(), RTLD_LAZY);
if (!m_handle) {
APPL_ERROR("Can not load Lbrary:" << dlerror());
return;
}
char *error = null;
m_SERVICE_IO_init = (SERVICE_IO_init_t)dlsym(m_handle, "SERVICE_IO_init");
error = dlerror();
if (error != null) {
m_SERVICE_IO_init = null;
APPL_WARNING("Can not function SERVICE_IO_init :" << error);
}
m_SERVICE_IO_uninit = (SERVICE_IO_uninit_t)dlsym(m_handle, "SERVICE_IO_uninit");
error = dlerror();
if (error != null) {
m_SERVICE_IO_uninit = null;
APPL_WARNING("Can not function SERVICE_IO_uninit :" << error);
}
m_SERVICE_IO_peridic_call = (SERVICE_IO_peridic_call_t)dlsym(m_handle, "SERVICE_IO_peridic_call");
error = dlerror();
if (error != null) {
m_SERVICE_IO_uninit = null;
APPL_WARNING("Can not function SERVICE_IO_uninit :" << error);
}
m_SERVICE_IO_instanciate = (SERVICE_IO_instanciate_t)dlsym(m_handle, "SERVICE_IO_instanciate");
error = dlerror();
if (error != null) {
m_SERVICE_IO_instanciate = null;
APPL_WARNING("Can not function SERVICE_IO_instanciate:" << error);
}
}
~PlugginAccess() {
}
bool init(int _argc, const char *_argv[], etk::Uri _basePath) {
if (m_SERVICE_IO_init == null) {
return false;
}
if (_basePath.isEmpty() == true) {
_basePath = "USER_DATA:///" + m_name + "/";
APPL_PRINT("Use base path: " << _basePath);
} else {
_basePath.setPath(_basePath.getPath() / m_name);
}
return (*m_SERVICE_IO_init)(_argc, _argv, _basePath);
}
bool publish(zeus::Client& _client) {
if (m_SERVICE_IO_instanciate == null) {
return false;
}
_client.serviceAdd(m_name, [=](uint32_t _transactionId, ememory::SharedPtr<zeus::WebServer>& _iface, uint32_t _destination) {
(*m_SERVICE_IO_instanciate)(_transactionId, _iface, _destination);
});
return true;
}
bool disconnect(zeus::Client& _client) {
_client.serviceRemove(m_name);
return true;
}
bool uninit() {
if (m_SERVICE_IO_uninit == null) {
return false;
}
return (*m_SERVICE_IO_uninit)();
}
void peridic_call() {
if (m_SERVICE_IO_peridic_call == null) {
return;
}
(*m_SERVICE_IO_peridic_call)();
}
};
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
zeus::init(_argc, _argv);
etk::String ip;
uint16_t port = 1985;
etk::String basePath;
etk::Vector<etk::String> services;
for (int32_t iii=0; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) {
ip = etk::String(&data[5]);
} else if (etk::start_with(data, "--port=") == true) {
port = etk::string_to_uint16_t(etk::String(&data[7]));
} else if (etk::start_with(data, "--base-path=") == true) {
basePath = etk::String(&data[12]);
if ( basePath.size() != 0
&& basePath[basePath.size()-1] != '/') {
basePath += '/';
}
} else if (etk::start_with(data, "--srv=") == true) {
services.pushBack(etk::String(&data[6]));
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --base-path=XXX base path to search data (default: 'USERDATA:')");
APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)");
APPL_PRINT(" --port=XXX Server connection PORT (default: 1985)");
APPL_PRINT(" --srv=XXX service path (N)");
return -1;
}
}
zeus::Client m_client;
etk::Vector<ememory::SharedPtr<PlugginAccess>> listElements;
for (auto &it: services) {
ememory::SharedPtr<PlugginAccess> tmp = ememory::makeShared<PlugginAccess>(it);
listElements.pushBack(tmp);
}
for (auto &it: listElements) {
it->init(_argc, _argv, basePath);
}
if (ip != "") {
m_client.propertyIp.set(ip);
}
if (port != 0) {
m_client.propertyPort.set(port);
}
if (m_client.connect() == false) {
return -1;
}
for (auto &it: listElements) {
it->publish(m_client);
}
uint32_t iii = 0;
int32_t countMemeCheck = 0;
while(m_client.isAlive() == true) {
m_client.pingIsAlive();
m_client.displayConnectedObject();
m_client.cleanDeadObject();
for (auto &it: listElements) {
it->peridic_call();
}
ethread::sleepMilliSeconds(1000);
if (countMemeCheck++ >= 20) {
countMemeCheck = 0;
ETK_MEM_SHOW_LOG(true);
}
APPL_INFO("service in waiting ... " << iii << "/inf");
iii++;
}
for (auto &it: listElements) {
it->disconnect(m_client);
}
m_client.disconnect();
APPL_INFO("Stop service*** ==> flush internal datas ...");
for (auto &it: listElements) {
it->uninit();
}
elog::flush();
return 0;
}

View File

@ -0,0 +1,41 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
def get_type():
return "BINARY"
def get_sub_type():
return "TOOLS"
def get_desc():
return "ZEUS launcher of service module"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module):
my_module.add_path(".")
my_module.add_depend([
'etk',
'zeus',
'elog'
])
my_module.add_src_file([
'appl/debug.cpp',
'appl/main-launcher.cpp'
])
return True

View File

@ -0,0 +1,40 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
def get_type():
return "PACKAGE"
def get_desc():
return "ZEUS package group to set it usable"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module):
my_module.add_depend([
'zeus-router',
'zeus-gateway',
'zeus-service-user-impl',
'zeus-service-picture-impl',
'zeus-service-video-impl',
'zeus-service-server-impl',
'zeus-service-server-impl',
'zeus-launcher',
'zeus-cli-video',
'zeus-player-video',
])
return True

View File

@ -1,447 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <appl/debug.h>
#include <jus/Service.h>
#include <jus/File.h>
#include <etk/etk.h>
#include <unistd.h>
#include <mutex>
#include <ejson/ejson.h>
#include <etk/os/FSNode.h>
#include <sstream>
#include <etk/stdTools.h>
namespace appl {
class User {
private:
std::mutex m_mutex;
std::string m_userName;
std::string m_basePath;
ejson::Document m_database;
std::map<uint64_t,std::string> m_listFile;
uint64_t m_lastMaxId;
public:
User(const std::string& _userName) :
m_userName(_userName),
m_lastMaxId(1024) {
std::unique_lock<std::mutex> lock(m_mutex);
APPL_WARNING("new USER: " << m_userName << " [START]");
m_basePath = std::string("USERDATA:") + m_userName + "/";
APPL_WARNING("new USER: " << m_userName);
bool ret = m_database.load(m_basePath + "database.json");
if (ret == false) {
APPL_WARNING(" ==> LOAD error");
}
// Load all files (image and video ...)
etk::FSNode node(m_basePath);
std::vector<etk::FSNode*> tmpList = node.folderGetSubList(false, false, true, false);
APPL_WARNING("Find " << tmpList.size() << " files");
for (auto &it : tmpList) {
if (it == nullptr) {
continue;
}
if ( etk::end_with(it->getNameFile(), ".svg", false) == true
|| etk::end_with(it->getNameFile(), ".bmp", false) == true
|| etk::end_with(it->getNameFile(), ".png", false) == true
|| etk::end_with(it->getNameFile(), ".jpg", false) == true
|| etk::end_with(it->getNameFile(), ".tga", false) == true
|| etk::end_with(it->getNameFile(), ".mp4", false) == true
|| etk::end_with(it->getNameFile(), ".avi", false) == true
|| etk::end_with(it->getNameFile(), ".mov", false) == true
|| etk::end_with(it->getNameFile(), ".mkv", false) == true) {
// TODO : Do it better (proto ..)
std::string idString = it->getNameFile();
idString.resize(idString.size()-4);
uint64_t id = 0;
std::stringstream ss;
ss << std::hex << idString;
ss >> id;
if (id <= 1024) {
APPL_WARNING(" ==> REJECTED file " << it->getNameFile() << " with ID = " << id);
} else {
m_listFile.insert(std::make_pair(id, it->getNameFile()));
m_lastMaxId = std::max(m_lastMaxId,id);
APPL_WARNING(" ==> load file " << it->getNameFile() << " with ID = " << id);
}
} else {
APPL_WARNING(" ==> REJECT file " << it->getNameFile());
}
}
APPL_WARNING("new USER: " << m_userName << " [STOP]");
}
~User() {
std::unique_lock<std::mutex> lock(m_mutex);
APPL_WARNING("delete USER [START]");
APPL_DEBUG("Store User Info:");
bool ret = m_database.storeSafe(m_basePath + "database.json");
if (ret == false) {
APPL_WARNING(" ==> Store error");
}
APPL_WARNING("delete USER [STOP]");
}
// Return the list of root albums
std::vector<std::string> getAlbums() {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
ejson::Array globalGroups = m_database["group-global"].toArray();
if (globalGroups.exist() == false) {
return out;
}
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
return out;
}
for (auto it: globalGroups) {
std::string tmpString = it.toString().get();
if (tmpString == "") {
continue;
}
out.push_back(tmpString);
}
return out;
/*
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
return std::vector<std::string>();
}
groups
return getSubAlbums("");
*/
}
// Get the list of sub album
std::vector<std::string> getSubAlbums(const std::string& _album) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
return out;
}
// find parrentAlbum ==> to get sub group
/*
for (size_t iii=0; iii<groups.size(); ++iii) {
//ejson::Object group = groups[iii].toObject()["sub"];
if (groups.getKey(iii) != _parrentAlbum) {
continue;
}
}
*/
ejson::Object group = groups[_album].toObject();
if (group.exist() == false) {
return out;
}
ejson::Array groupSubs = group["sub"].toArray();
for (auto it: groupSubs) {
std::string tmpString = it.toString().get();
if (tmpString == "") {
continue;
}
out.push_back(tmpString);
}
// TODO: Check right
return out;
}
uint32_t getAlbumCount(const std::string& _album) {
std::unique_lock<std::mutex> lock(m_mutex);
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
// TODO : Throw an error ...
return 0;
}
ejson::Object group = groups[_album].toObject();
if (group.exist() == false) {
// TODO : Throw an error ...
return 0;
}
ejson::Array groupSubs = group["files"].toArray();
// TODO: Check right
return groupSubs.size();
/*
for (auto it: groupSubs) {
uint64_t id = it.toNumber().getU64();
if (id == 0) {
continue;
}
out.push_back(id);
}
*/
}
// Return the list of the album files
std::vector<std::string> getAlbumListPicture(const std::string& _album) {//, uint32_t _startId, uint32_t _stopId) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
// TODO : Throw an error ...
return out;
}
ejson::Object group = groups[_album].toObject();
if (group.exist() == false) {
// TODO : Throw an error ...
return out;
}
ejson::Array groupSubs = group["files"].toArray();
for (auto it: groupSubs) {
uint64_t id = it.toNumber().getU64();
/*
auto itImage = m_listFile.find(id);
if (itImage == m_listFile.end()) {
}*/
if (id == 0) {
continue;
}
out.push_back(etk::to_string(id));
}
return out;
}
// Return a File Data (might be a picture .tiff/.png/.jpg)
jus::FileServer getAlbumPicture(const std::string& _pictureName) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
uint64_t id = etk::string_to_uint64_t(_pictureName);
APPL_WARNING("try to get file : " << _pictureName << " with id=" << id);
{
auto it = m_listFile.find(id);
if (it != m_listFile.end()) {
return jus::FileServer(m_basePath + it->second);
}
}
for (auto &it : m_listFile) {
APPL_WARNING("compare: " << it.first << " with " << id << " " << it.second);
if (it.first == id) {
return jus::FileServer(m_basePath + it.second);
}
}
APPL_ERROR(" ==> Not find ...");
return jus::FileServer();
}
std::string addFile(const jus::File& _dataFile) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
APPL_ERROR(" ==> Receive FILE " << _dataFile.getMineType() << " size=" << _dataFile.getData().size());
uint64_t id = createFileID();
std::stringstream val;
val << std::hex << std::setw(16) << std::setfill('0') << id;
std::string filename = val.str();
filename += ".";
filename += jus::getExtention(_dataFile.getMineType());
_dataFile.storeIn(m_basePath + filename);
m_listFile.insert(std::make_pair(id, filename));
return etk::to_string(id);//jus::FileServer();
}
bool removeFile(const std::string& _file) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return false;
}
std::string createAlbum(const std::string& _name) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return "";
}
bool removeAlbum(const std::string& _name) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return false;
}
bool setAlbumDescription(const std::string& _name, const std::string& _desc) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return false;
}
std::string getAlbumDescription(const std::string& _name) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return "";
}
bool addInAlbum(const std::string& _nameAlbum, const std::string& _nameElement) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return false;
}
bool removeFromAlbum(const std::string& _nameAlbum, const std::string& _nameElement) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return false;
}
/*
// Return a global UTC time
jus::Time getAlbumPictureTime(const std::string& _pictureName) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return jus::Time();
}
// Return a Geolocalization information (latitude, longitude)
jus::Geo getAlbumPictureGeoLocalization(const std::string& _pictureName) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Check right ...
return jus::Geo();
}
*/
private:
uint64_t createFileID() {
m_lastMaxId++;
return m_lastMaxId;
}
};
class UserManager {
private:
std::mutex m_mutex;
std::map<std::string, ememory::SharedPtr<appl::User>> m_listLoaded;
public:
UserManager() {
}
ememory::SharedPtr<appl::User> getUser(const std::string& _userName) {
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_listLoaded.find(_userName);
if (it != m_listLoaded.end()) {
// User already loaded:
return it->second;
}
// load New User:
ememory::SharedPtr<appl::User> tmp(new appl::User(_userName));
m_listLoaded.insert(std::make_pair(_userName, tmp));
return tmp;
}
};
class PictureService {
private:
ememory::SharedPtr<appl::User> m_user;
private:
ememory::SharedPtr<jus::ClientProperty> m_client;
public:
PictureService() {
APPL_WARNING("New PictureService ...");
}
PictureService(ememory::SharedPtr<appl::User> _user, ememory::SharedPtr<jus::ClientProperty> _client) :
m_user(_user),
m_client(_client) {
APPL_WARNING("New PictureService ... for user: ");
}
~PictureService() {
APPL_WARNING("delete PictureService ...");
}
public:
std::vector<std::string> getAlbums() {
return m_user->getAlbums();
}
// Get the list of sub album
std::vector<std::string> getSubAlbums(std::string _parrentAlbum) {
return m_user->getSubAlbums(_parrentAlbum);
}
uint32_t getAlbumCount(std::string _album) {
return m_user->getAlbumCount(_album);
}
// Return the list of the album files
std::vector<std::string> getAlbumListPicture(std::string _album) {//, uint32_t _startId, uint32_t _stopId) {
return m_user->getAlbumListPicture(_album);//, _startId, _stopId);
}
// Return a File Data (might be a picture .tiff/.png/.jpg)
jus::FileServer getAlbumPicture(std::string _pictureName) {
return m_user->getAlbumPicture(_pictureName);
}
std::string addFile(jus::File _dataFile) {
return m_user->addFile(_dataFile);
}
/*
// Return a global UTC time
jus::Time getAlbumPictureTime(std::string _pictureName) {
return m_user->getAlbumPictureTime(_pictureName);
}
// Return a Geolocalization information (latitude, longitude)
jus::Geo getAlbumPictureGeoLocalization(std::string _pictureName) {
return m_user->getAlbumPictureGeoLocalization(_pictureName);
}
*/
};
}
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
std::string ip;
uint16_t port = 0;
for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) {
ip = std::string(&data[5]);
} else if (etk::start_with(data, "--port=") == true) {
port = etk::string_to_uint16_t(std::string(&data[7]));
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)");
APPL_PRINT(" --port=XXX Server connection PORT (default: 1983)");
return -1;
}
}
while (true) {
APPL_INFO("===========================================================");
APPL_INFO("== JUS instanciate service: " << SERVICE_NAME << " [START]");
APPL_INFO("===========================================================");
appl::UserManager userMng;
jus::ServiceType<appl::PictureService, appl::UserManager> serviceInterface(userMng);
if (ip != "") {
serviceInterface.propertyIp.set(ip);
}
if (port != 0) {
serviceInterface.propertyPort.set(port);
}
serviceInterface.setDescription("Picture Private Interface");
serviceInterface.setVersion("0.1.0");
serviceInterface.setType("PICTURE", 1);
serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com");
serviceInterface.advertise("getAlbums", &appl::PictureService::getAlbums);
serviceInterface.advertise("getSubAlbums", &appl::PictureService::getSubAlbums);
serviceInterface.advertise("getAlbumCount", &appl::PictureService::getAlbumCount);
serviceInterface.advertise("getAlbumListPicture", &appl::PictureService::getAlbumListPicture);
serviceInterface.advertise("getAlbumPicture", &appl::PictureService::getAlbumPicture);
serviceInterface.advertise("addFile", &appl::PictureService::addFile);
/*
serviceInterface.advertise("getAlbumPicture", &appl::PictureService::getAlbumPicture);
serviceInterface.advertise("getAlbumPictureTime", &appl::PictureService::getAlbumPictureTime);
serviceInterface.advertise("getAlbumPictureGeoLocalization", &appl::PictureService::getAlbumPictureGeoLocalization);
*/
APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [service instanciate]");
APPL_INFO("===========================================================");
serviceInterface.connect(SERVICE_NAME);
if (serviceInterface.GateWayAlive() == false) {
APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [STOP] Can not connect to the GateWay");
APPL_INFO("===========================================================");
APPL_INFO("wait 5 second ...");
usleep(5000000);
continue;
}
int32_t iii=0;
while (serviceInterface.GateWayAlive() == true) {
usleep(1000000);
serviceInterface.pingIsAlive();
/*
serviceInterface.store();
serviceInterface.clean();
*/
APPL_INFO("service in waiting ... " << iii << "/inf");
iii++;
}
serviceInterface.disconnect();
APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [STOP] GateWay Stop");
APPL_INFO("===========================================================");
}
return 0;
}

View File

@ -1,39 +0,0 @@
#!/usr/bin/python
import lutin.module as module
import lutin.tools as tools
def get_type():
return "BINARY"
def get_sub_type():
return "TOOLS"
def get_desc():
return "JUS picture service"
def get_licence():
return "APACHE-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_export_path(tools.get_current_path(__file__))
my_module.add_module_depend(['jus'])
my_module.add_src_file([
'appl/debug.cpp',
'appl/main.cpp'
])
my_module.add_export_flag('c++', "-DSERVICE_NAME=\"\\\"" + module_name[4:] + "\\\"\"")
return my_module

View File

@ -0,0 +1,161 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#include <appl/debug.hpp>
#include <ewol/widget/Widget.hpp>
#include <appl/ClientProperty.hpp>
#include <appl/debug.hpp>
#include <appl/widget/ListViewer.hpp>
#include <ewol/object/Manager.hpp>
#include <etk/tool.hpp>
#include <egami/egami.hpp>
#include <zeus/zeus.hpp>
#include <zeus/Client.hpp>
#include <zeus/service/ProxyVideo.hpp>
#include <zeus/ProxyFile.hpp>
#include <zeus/ObjectRemote.hpp>
#include <echrono/Steady.hpp>
#include <zeus/FutureGroup.hpp>
#include <etk/stdTools.hpp>
#include <ejson/ejson.hpp>
appl::ClientProperty::ClientProperty() {
m_address = "127.0.0.1";
m_port = 1983;
}
ejson::Object appl::ClientProperty::toJson() {
ejson::Object out;
out.add("user", ejson::String(m_fromUser));
out.add("pass", ejson::String(m_pass));
out.add("address", ejson::String(m_address));
out.add("port", ejson::Number(m_port));
return out;
}
void appl::ClientProperty::fromJson(ejson::Object _obj) {
m_fromUser = _obj["user"].toString().get();
m_toUser = m_fromUser;
m_pass = _obj["pass"].toString().get();
m_address = _obj["address"].toString().get();
m_port = _obj["port"].toNumber().getU64();
}
void appl::ClientProperty::disconnect() {
m_connection.disconnect();
}
void appl::ClientProperty::connect() {
if (m_connection.isAlive() == true) {
m_connection.pingIsAlive();
if (m_connection.isAlive() == true) {
return;
}
}
// Generate IP and Port in the client interface
if (m_address == "") {
m_connection.propertyIp.set("127.0.0.1");
} else {
m_connection.propertyIp.set(m_address);
}
if (m_port == 0) {
m_connection.propertyPort.set(1983);
} else {
m_connection.propertyPort.set(m_port);
}
APPL_INFO("Connection on : " << m_connection.propertyIp.get() << ":" << m_connection.propertyPort.get() << " '" << m_fromUser << "' ==> '" << m_toUser << "'");
// Connection depending on the mode requested
if (m_fromUser == m_toUser) {
bool ret = m_connection.connect(m_fromUser, m_pass);
if (ret == false) {
APPL_ERROR(" ==> NOT Authentify with '" << m_toUser << "'");
return;
} else {
APPL_INFO(" ==> Authentify with '" << m_toUser << "'");
}
} else if (m_fromUser != "") {
bool ret = m_connection.connect(m_fromUser, m_toUser, m_pass);
if (ret == false) {
APPL_ERROR(" ==> NOT Connected to '" << m_toUser << "' with '" << m_fromUser << "'");
return;
} else {
APPL_INFO(" ==> Connected with '" << m_toUser << "' with '" << m_fromUser << "'");
}
} else {
bool ret = m_connection.connect(m_toUser);
if (ret == false) {
APPL_ERROR(" ==> NOT Connected with 'anonymous' to '" << m_toUser << "'");
return;
} else {
APPL_INFO(" ==> Connected with 'anonymous' to '" << m_toUser << "'");
}
}
APPL_INFO("Done");
}
void appl::ClientProperty::setLogin(etk::String _login) {
m_fromUser = "";
m_toUser = "";
m_address = "";
m_port = 0;
// separate loggin and IP adress ...
etk::String login;
etk::Vector<etk::String> listElem = etk::split(_login, '~');
if (listElem.size() == 0) {
APPL_ERROR("Not enouth element in the login ...");
return;
}
m_fromUser = listElem[0];
m_toUser = m_fromUser;
if (listElem.size() == 1) {
// connnect on local host ... nothing to do
} else {
etk::Vector<etk::String> listElem2 = etk::split(listElem[1], ':');
if (listElem2.size() >= 1) {
m_address = listElem2[0];
}
if (listElem2.size() >= 2) {
m_port = etk::string_to_uint32_t(listElem2[1]);
}
}
}
etk::String appl::ClientProperty::getLogin() {
etk::String out = m_fromUser;
bool hasTild = false;
if (m_address != "") {
if (hasTild == false) {
out += "~" ;
hasTild = true;
}
out += m_address;
}
if ( m_port != 1983
&& m_port != 0) {
if (hasTild == false) {
out += "~" ;
hasTild = true;
}
out += ":" + etk::toString(m_port);
}
return out;
}
void appl::ClientProperty::setPassword(etk::String _password) {
m_pass = _password;
}
etk::String appl::ClientProperty::getPassword() {
return m_pass;
}
#include <esignal/details/Signal.hxx>
ESIGNAL_DECLARE_SIGNAL(ememory::SharedPtr<appl::ClientProperty>);

View File

@ -0,0 +1,44 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#pragma once
#include <ewol/widget/WidgetScrolled.hpp>
#include <ewol/compositing/Image.hpp>
#include <ewol/compositing/Text.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/widget/Manager.hpp>
#include <esignal/Signal.hpp>
#include <zeus/Client.hpp>
#include <ejson/ejson.hpp>
namespace appl {
class ClientProperty {
protected:
etk::String m_fromUser;
etk::String m_toUser;
etk::String m_pass;
etk::String m_address;
uint16_t m_port;
zeus::Client m_connection;
public:
ClientProperty();
zeus::Client& getConnection() {
return m_connection;
};
void connect();
void disconnect();
ejson::Object toJson();
void fromJson(ejson::Object _obj);
void setLogin(etk::String _login);
etk::String getLogin();
void setPassword(etk::String _password);
etk::String getPassword();
};
}

View File

@ -0,0 +1,113 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#include <etk/types.hpp>
#include <ewol/ewol.hpp>
#include <gale/context/commandLine.hpp>
#include <appl/debug.hpp>
#include <appl/Windows.hpp>
#include <ewol/object/Object.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <appl/widget/VideoPlayer.hpp>
#include <appl/widget/ListViewer.hpp>
#include <appl/widget/Player.hpp>
#include <appl/widget/ProgressBar.hpp>
#include <appl/widget/VolumeBar.hpp>
#include <appl/widget/UpBar.hpp>
#include <zeus/zeus.hpp>
#include <etk/etk.hpp>
namespace appl {
class MainApplication : public ewol::context::Application {
public:
void onCreate(ewol::Context& _context) override {
APPL_INFO("==> CREATE ... " PROJECT_NAME " (BEGIN)");
localCreate(_context);
APPL_INFO("==> CREATE ... " PROJECT_NAME " (END)");
}
void onStart(ewol::Context& _context) override {
APPL_INFO("==> START ... " PROJECT_NAME " (BEGIN)");
// nothing to do ...
APPL_INFO("==> START ... " PROJECT_NAME " (END)");
}
void onResume(ewol::Context& _context) override {
APPL_INFO("==> RESUME ... " PROJECT_NAME " (BEGIN)");
// nothing to do ...
APPL_INFO("==> RESUME ... " PROJECT_NAME " (END)");
}
void onPause(ewol::Context& _context) override {
APPL_INFO("==> PAUSE ... " PROJECT_NAME " (BEGIN)");
// nothing to do ...
APPL_INFO("==> PAUSE ... " PROJECT_NAME " (END)");
}
void onStop(ewol::Context& _context) override {
APPL_INFO("==> STOP ... " PROJECT_NAME " (START)");
// nothing to do ...
APPL_INFO("==> STOP ... " PROJECT_NAME " (END)");
}
void onDestroy(ewol::Context& _context) override {
APPL_INFO("==> DESTROY ... " PROJECT_NAME " (START)");
// nothing to do ...
APPL_INFO("==> DESTROY ... " PROJECT_NAME " (END)");
}
void localCreate(ewol::Context& _context) {
// parse all the argument of the application
for (int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
etk::String tmpppp = _context.getCmd().get(iii);
if ( tmpppp == "-h"
|| tmpppp == "--help") {
APPL_INFO(" -h/--help display this help" );
exit(0);
}
}
// TODO : Remove this: Move if in the windows properties
_context.setSize(vec2(400, 300));
// eneble the search of the font in the system font path
_context.getFontDefault().setUseExternal(true);
// select font preference of der with a basic application size
#ifdef __TARGET_OS__Android
_context.getFontDefault().set("FreeSerif;DroidSans", 20);
#else
_context.getFontDefault().set("FreeSerif;DejaVuSerif;FreeSerif;DejaVuSansMono;DroidSans",12);
#endif
// set application widget:
appl::widget::VideoDisplay::createManagerWidget(_context.getWidgetManager());
appl::widget::ListViewer::createManagerWidget(_context.getWidgetManager());
appl::widget::Player::createManagerWidget(_context.getWidgetManager());
appl::widget::ProgressBar::createManagerWidget(_context.getWidgetManager());
appl::widget::VolumeBar::createManagerWidget(_context.getWidgetManager());
appl::widget::UpBar::createManagerWidget(_context.getWidgetManager());
// Create the windows
ememory::SharedPtr<appl::Windows> basicWindows = appl::Windows::create();
// configure the ewol context to use the new windows
_context.setWindows(basicWindows);
for (int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
etk::String tmpppp = _context.getCmd().get(iii);
if (etk::start_with(tmpppp, "-") == true) {
continue;
}
basicWindows->addFile(tmpppp);
}
}
};
}
/**
* @brief Main of the program (This can be set in every case, but it is not used in Andoid...).
* @param std IO
* @return std IO
*/
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
audio::river::init();
zeus::init(_argc, _argv);
return ewol::run(ETK_NEW(appl::MainApplication), _argc, _argv);
}

View File

@ -0,0 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#pragma once

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,207 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#pragma once
#include <gale/Thread.hpp>
#include <audio/channel.hpp>
#include <audio/format.hpp>
#include <appl/debug.hpp>
#include <appl/ClientProperty.hpp>
#include <zeus/ProxyFile.hpp>
extern "C" {
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libswscale/swscale.h>
}
namespace appl {
class MessageElement {
public:
uint64_t m_id; //!< Id of the current image (must be unique)
echrono::Duration m_time; //!< Current time of the Message Element
echrono::Duration m_duration; //!< if the FPS is static ==> the duration can be set otherwise (0)
bool m_isUsed; //!< This buffer is used
MessageElement():
m_id(0),
m_isUsed(false) {
}
virtual ~MessageElement() = default;
};
// class that contain all the element needed for a buffer image transfert:
class MessageElementVideo : public appl::MessageElement {
public:
egami::Image m_image; //!< Image to manage internal data
ivec2 m_imageRealSize; //!< Real size of the image, in OpenGL we need power of 2 border size.
int32_t m_lineSize; //!< Size of a single line (in byte)
void setSize(const ivec2& _newSize);
MessageElementVideo():
m_image(ivec2(32,32), egami::colorType::RGB8),
m_imageRealSize(32,32) {
}
};
class MessageElementAudio : public appl::MessageElement {
public:
etk::Vector<uint8_t> m_buffer; //!< raw audio data
audio::format m_format; //!< Audio format buffer
uint32_t m_sampleRate; //!< sample rate of the buffer
etk::Vector<audio::channel> m_map; //!< Channel map of the buffer
void configure(audio::format _format, uint32_t _sampleRate, int32_t _nbChannel, int32_t _nbSample);
};
class StreamBuffering : public ememory::EnableSharedFromThis<StreamBuffering> {
public:
StreamBuffering();
ethread::Mutex m_mutex; //!< local Lock Data protection
ememory::SharedPtr<appl::ClientProperty> m_property; //!< Remote interface that must get data
uint32_t m_mediaId; //!< remote media ID that need to get data
zeus::ProxyFile m_fileHandle; //!< Reference on the remote file
etk::Vector<uint8_t> m_buffer; //!< preallocated with all needed data
int32_t m_bufferReadPosition; //!< Current position that is read
etk::Vector<etk::Pair<uint32_t,uint32_t>> m_bufferFillSection; //!< List of <start-stop> position that contain data
bool m_callInProgress;
bool m_stopRequested;
public:
bool addDataCallback(const zeus::Raw& _data, int64_t _positionRequest);
void checkIfWeNeedMoreDataFromNetwork();
uint64_t getSize() {
ethread::UniqueLock lock(m_mutex);
return m_buffer.size();
}
etk::Vector<etk::Pair<uint32_t,uint32_t>> getDownloadPart() {
ethread::UniqueLock lock(m_mutex);
return m_bufferFillSection;
}
int32_t sizeReadable();
void stopStream();
void startStream();
};
class MediaDecoder : public gale::Thread {
bool m_stopRequested;
public:
bool m_fistFrameSended;
echrono::Duration m_seekApply;
private:
echrono::Duration m_seek;
void applySeek(echrono::Duration _time);
echrono::Duration m_duration;
public:
echrono::Duration getDuration() {
return m_duration;
}
public:
etk::Vector<MessageElementAudio> m_audioPool;
echrono::Duration m_currentAudioTime;
etk::Vector<MessageElementVideo> m_videoPool;
echrono::Duration m_currentVideoTime;
bool m_updateVideoTimeStampAfterSeek;
bool getSeekDone() {
return m_updateVideoTimeStampAfterSeek;
}
int32_t audioGetOlderSlot();
int32_t videoGetOlderSlot();
private:
int32_t videoGetEmptySlot();
int32_t audioGetEmptySlot();
private:
AVIOContext* m_IOContext;
AVFormatContext* m_formatContext;
AVCodecContext* m_videoDecoderContext;
AVCodecContext* m_audioDecoderContext;
ivec2 m_size;
public:
ivec2 getSize() {
return m_size;
}
private:
enum AVPixelFormat m_pixelFormat;
AVStream *m_videoStream;
AVStream *m_audioStream;
etk::String m_sourceFilename;
int32_t m_videoStream_idx;
int32_t m_audioStream_idx;
AVFrame *m_frame;
AVPacket m_packet;
int32_t m_videoFrameCount;
int32_t m_audioFrameCount;
// output format convertion:
SwsContext* m_convertContext;
bool m_isInit;
public:
MediaDecoder();
~MediaDecoder();
int decode_packet(int *_gotFrame, int _cached);
int open_codec_context(int *_streamId, AVFormatContext *_formatContext, enum AVMediaType _type);
double getFps(AVCodecContext *_avctx);
protected:
void init();
public:
void init(ememory::SharedPtr<appl::ClientProperty> _property, uint32_t _mediaId);
bool onThreadCall() override;
void uninit();
bool m_audioPresent;
audio::format m_audioFormat; //!< Audio format buffer
uint32_t m_audioSampleRate; //!< sample rate of the buffer
etk::Vector<audio::channel> m_audioMap; //!< Channel map of the buffer
bool haveAudio() {
return m_audioPresent;
}
uint32_t audioGetSampleRate() {
return m_audioSampleRate;
}
etk::Vector<audio::channel> audioGetChannelMap() {
return m_audioMap;
}
audio::format audioGetFormat() {
return m_audioFormat;
}
void seek(const echrono::Duration& _time) {
m_seek = _time;
}
void flushMessage();
void stop() override;
/* ***********************************************
** Section temporary buffer
***********************************************/
ememory::SharedPtr<appl::StreamBuffering> m_remote;
public:
// @brief INTERNAL read callback
int readFunc(uint8_t* _buf, int _bufSize);
// @brief INTERNAL write callback
int writeFunc(uint8_t* _buf, int _bufSize);
// @brief INTERNAL seek callback
int64_t seekFunc(int64_t _offset, int _whence);
etk::Vector<etk::Pair<float,float>> getDownloadPart() {
etk::Vector<etk::Pair<float,float>> out;
if (m_remote == null) {
return out;
}
etk::Vector<etk::Pair<uint32_t,uint32_t>> vals = m_remote->getDownloadPart();
echrono::Duration totalTime = getDuration();
float size = totalTime.toSeconds()/float(m_remote->getSize());
//APPL_ERROR(" duration in sec : " << totalTime << " => " << totalTime.toSeconds());
for (auto &it : vals) {
out.pushBack(etk::Pair<float,float>(float(it.first)*size, float(it.second)*size));
}
return out;
}
};
}

View File

@ -0,0 +1,330 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#include <ewol/ewol.hpp>
#include <appl/debug.hpp>
#include <appl/Windows.hpp>
#include <ewol/widget/Label.hpp>
#include <ewol/widget/Button.hpp>
#include <ewol/widget/Entry.hpp>
#include <ewol/widget/Slider.hpp>
#include <ewol/widget/Menu.hpp>
#include <appl/widget/VideoPlayer.hpp>
#include <ewol/tools/message.hpp>
#include <zeus/zeus.hpp>
#include <zeus/Client.hpp>
#include <zeus/service/ProxyVideo.hpp>
#include <zeus/ProxyFile.hpp>
#include <zeus/ObjectRemote.hpp>
#include <echrono/Steady.hpp>
#include <zeus/FutureGroup.hpp>
#include <etk/stdTools.hpp>
#include <ejson/ejson.hpp>
#include <appl/widget/Connection.hpp>
#include <ewol/context/Context.hpp>
#include <appl/widget/Player.hpp>
static etk::Uri g_baseDBName = "CONFIG:///config.json";
void appl::Windows::store_db() {
APPL_DEBUG("Store database [START]");
ejson::Document database;
if (m_clientProp != null) {
database.add("access", m_clientProp->toJson());
}
bool retGenerate = database.storeSafe(g_baseDBName);
APPL_ERROR("Store database [STOP] : " << (g_baseDBName) << " ret = " << retGenerate);
}
void appl::Windows::load_db() {
ejson::Document database;
bool ret = database.load(g_baseDBName);
if (ret == false) {
APPL_WARNING(" ==> LOAD error");
}
if (m_clientProp == null) {
m_clientProp = ememory::makeShared<appl::ClientProperty>();
if (m_clientProp == null) {
APPL_ERROR(" can not allocate the pointer of data ==> must auto kill");
autoDestroy();
return;
}
}
if (m_clientProp != null) {
m_clientProp->fromJson(database["access"].toObject());
}
}
appl::Windows::Windows():
m_id(0),
m_fullScreen(false) {
addObjectType("appl::Windows");
propertyTitle.setDirectCheck(etk::String("sample ") + PROJECT_NAME);
}
void appl::Windows::init() {
ewol::widget::Windows::init();
load_db();
m_composer = ewol::widget::Composer::create();
if (m_composer == null) {
APPL_CRITICAL(" An error occured ... in the windows creatrion ...");
return;
}
m_composer->loadFromFile("DATA:///gui.xml");
setSubWidget(m_composer);
drawWidgetTree();
m_listViewer = ememory::dynamicPointerCast<appl::widget::ListViewer>(m_composer->getSubObjectNamed("ws-name-list-viewer"));
if (m_listViewer != null) {
m_listViewer->signalSelect.connect(sharedFromThis(), &appl::Windows::onCallbackSelectMedia);
}
subBind(ewol::widget::Button, "access-fast-back", signalPressed, sharedFromThis(), &appl::Windows::onCallbackSelectBack);
subBind(ewol::widget::Button, "access-fast-home", signalPressed, sharedFromThis(), &appl::Windows::onCallbackSelectHome);
subBind(ewol::widget::Button, "access-fast-group", signalPressed, sharedFromThis(), &appl::Windows::onCallbackSelectGroup);
// Direct display list:
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
subBind(ewol::widget::Menu, "menu-bar", signalSelect, sharedFromThis(), &appl::Windows::onCallbackMenuEvent);
shortCutAdd("alt+F4", "menu:exit");
shortCutAdd("F12", "menu:reload-shader");
shortCutAdd("F9", "menu:connect");
shortCutAdd("F11", "menu:full-screen");
signalShortcut.connect(sharedFromThis(), &appl::Windows::onCallbackShortCut);
// TODO: try to connect the last connection availlable ...
if (m_clientProp == null) {
onCallbackMenuEvent("menu:connect");
} else {
m_clientProp->connect();
if (m_clientProp->getConnection().isAlive() == false) {
onCallbackMenuEvent("menu:connect");
} else {
if (m_listViewer != null) {
m_listViewer->setClientProperty(m_clientProp);
m_listViewer->searchElements();
}
}
}
m_player = ememory::dynamicPointerCast<appl::widget::Player>(m_composer->getSubObjectNamed("ws-name-player"));
if (m_player != null) {
m_player->signalPrevious.connect(sharedFromThis(), &appl::Windows::onCallbackPlayerPrevious);
m_player->signalNext.connect(sharedFromThis(), &appl::Windows::onCallbackPlayerNext);
m_player->signalFinished.connect(sharedFromThis(), &appl::Windows::onCallbackPlayerFinished);
}
}
void appl::Windows::onCallbackShortCut(const etk::String& _value) {
APPL_WARNING("Event from ShortCut : " << _value);
onCallbackMenuEvent(_value);
}
void appl::Windows::onCallbackMenuEvent(const etk::String& _value) {
APPL_WARNING("Event from Menu : " << _value);
if (m_player != null) {
m_player->stop();
}
if (_value == "menu:connect") {
appl::widget::ConnectionShared tmpWidget = appl::widget::Connection::create();
if (tmpWidget == null) {
APPL_ERROR("Can not open File chooser !!! ");
return;
}
tmpWidget->setProperty(m_clientProp);
// register on the Validate event:
tmpWidget->signalValidate.connect(sharedFromThis(), &appl::Windows::onCallbackConnectionValidate);
tmpWidget->signalConnectionError.connect(sharedFromThis(), &appl::Windows::onCallbackConnectionError);
// no need of this event watching ...
tmpWidget->signalCancel.connect(sharedFromThis(), &appl::Windows::onCallbackConnectionCancel);
// add the widget as windows pop-up ...
popUpWidgetPush(tmpWidget);
} else if (_value == "menu:full-screen") {
if (m_fullScreen == false) {
m_fullScreen = true;
} else {
m_fullScreen = false;
}
gale::getContext().setFullScreen(m_fullScreen);
} else if (_value == "menu:exit") {
gale::getContext().stop();
} else if (_value == "menu:back") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->backHistory();
} else if (_value == "menu:home") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("");
} else if (_value == "menu:group") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("group");
} else if (_value == "menu:tv") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-tv");
} else if (_value == "menu:films") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("film");
} else if (_value == "menu:animation-films") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("annimation");
} else if (_value == "menu:tv-show") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("tv-show");
} else if (_value == "menu:animation-tv-show") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("tv-annimation");
} else if (_value == "menu:teather") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("teather");
} else if (_value == "menu:one-man-show") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("one-man");
} else if (_value == "menu:courses") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("courses");
} else if (_value == "menu:TV-child") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("");
// TODO: ...
} else if (_value == "menu:TV-adult") {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
m_listViewer->searchElements("");
// TODO: ...
} else if (_value == "menu:reload-shader") {
ewol::getContext().getResourcesManager().reLoadResources();
ewol::getContext().forceRedrawAll();
} else {
APPL_ERROR("Event from Menu UNKNOW : '" << _value << "'");
}
}
void appl::Windows::onCallbackConnectionValidate(const ememory::SharedPtr<ClientProperty>& _prop) {
m_clientProp = _prop;
if (m_clientProp == null) {
// TODO: set back in public mode ...
return;
}
store_db();
// Update viewer to show all ...
if (m_listViewer != null) {
m_listViewer->setClientProperty(m_clientProp);
m_listViewer->searchElements();
}
}
void appl::Windows::onCallbackConnectionError(const ememory::SharedPtr<ClientProperty>& _prop) {
m_clientProp = _prop;
if (m_clientProp == null) {
// TODO: set back in public mode ...
return;
}
store_db();
}
void appl::Windows::onCallbackConnectionCancel() {
// TODO: set back in public mode ...
}
void appl::Windows::onCallbackPrevious() {
m_id--;
if (m_id < 0) {
m_id = m_list.size()-1;
}
ememory::SharedPtr<appl::widget::VideoDisplay> tmpDisp = ememory::dynamicPointerCast<appl::widget::VideoDisplay>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
// stop previous (if needed)
tmpDisp->stop();
// Set new file:
tmpDisp->setFile(m_list[m_id]);
tmpDisp->play();
echrono::Duration time = tmpDisp->getDuration();
APPL_DEBUG("duration = " << time << " " << etk::toString(time.toSeconds()));
propertySetOnWidgetNamed("progress-bar", "value", "0");
propertySetOnWidgetNamed("progress-bar", "max", etk::toString(time.toSeconds()));
}
}
void appl::Windows::onCallbackBack() {
}
void appl::Windows::onCallbackNext() {
m_id++;
if (m_id >= m_list.size()) {
m_id = 0;
}
ememory::SharedPtr<appl::widget::VideoDisplay> tmpDisp = ememory::dynamicPointerCast<appl::widget::VideoDisplay>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
// stop previous (if needed)
tmpDisp->stop();
// Set new file:
tmpDisp->setFile(m_list[m_id]);
tmpDisp->play();
echrono::Duration time = tmpDisp->getDuration();
APPL_DEBUG("duration = " << time << " " << etk::toString(time.toSeconds()));
propertySetOnWidgetNamed("progress-bar", "value", "0");
propertySetOnWidgetNamed("progress-bar", "max", etk::toString(time.toSeconds()));
}
}
void appl::Windows::addFile(const etk::String& _file) {
APPL_DEBUG("Add file : " << _file);
m_list.pushBack(_file);
if (m_list.size() == 1) {
m_id = 0;
ememory::SharedPtr<appl::widget::VideoDisplay> tmpDisp = ememory::dynamicPointerCast<appl::widget::VideoDisplay>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
tmpDisp->setFile(m_list[m_id]);
echrono::Duration time = tmpDisp->getDuration();
APPL_DEBUG("duration = " << time << " " << etk::toString(time.toSeconds()));
propertySetOnWidgetNamed("progress-bar", "value", "0");
propertySetOnWidgetNamed("progress-bar", "max", etk::toString(time.toSeconds()));
}
}
}
void appl::Windows::onCallbackSelectMedia(const uint32_t& _value) {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-player");
if (m_player != null) {
m_player->playStream(m_clientProp, _value);
}
}
void appl::Windows::onCallbackPlayerPrevious() {
if (m_player != null) {
m_player->stop();
}
if (m_listViewer != null) {
if (m_listViewer->previous() == false) {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
}
}
}
void appl::Windows::onCallbackPlayerNext() {
if (m_player != null) {
m_player->stop();
}
if (m_listViewer != null) {
if (m_listViewer->next() == false) {
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
}
}
}
void appl::Windows::onCallbackPlayerFinished() {
if (m_player != null) {
m_player->stop();
}
ewol::propertySetOnObjectNamed("view-selection", "select", "ws-name-list-viewer");
}

View File

@ -0,0 +1,71 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#pragma once
#include <ewol/widget/Windows.hpp>
#include <ewol/widget/Composer.hpp>
#include <appl/widget/ListViewer.hpp>
#include <appl/widget/Player.hpp>
namespace appl {
class Windows;
using WindowsShared = ememory::SharedPtr<appl::Windows>;
using WindowsWeak = ememory::WeakPtr<appl::Windows>;
class Windows : public ewol::widget::Windows {
protected:
Windows();
void init();
ewol::widget::ComposerShared m_composer;
ememory::SharedPtr<ClientProperty> m_clientProp;
appl::widget::ListViewerShared m_listViewer;
appl::widget::PlayerShared m_player;
etk::Vector<etk::String> m_list;
int32_t m_id;
public:
DECLARE_FACTORY(Windows);
public: // callback functions
void onCallbackBack();
void onCallbackPrevious();
void onCallbackPlay(const bool& _isPressed);
void onCallbackNext();
void addFile(const etk::String& _file);
void onCallbackSeekRequest(const float& _value);
void onCallbackConnectionValidate(const ememory::SharedPtr<ClientProperty>& _prop);
void onCallbackConnectionError(const ememory::SharedPtr<ClientProperty>& _prop);
void onCallbackConnectionCancel();
void onCallbackShortCut(const etk::String& _value);
void onCallbackMenuEvent(const etk::String& _value);
protected:
void load_db();
void store_db();
void onCallbackSelectFilms();
void onCallbackSelectAnnimation();
void onCallbackSelectTVShow();
void onCallbackSelectTvAnnimation();
void onCallbackSelectTeather();
void onCallbackSelectOneManShow();
void onCallbackSelectSourses();
void onCallbackSelectMedia(const uint32_t& _value);
void onCallbackSelectBack() {
onCallbackMenuEvent("menu:back");
}
void onCallbackSelectGroup() {
onCallbackMenuEvent("menu:group");
}
void onCallbackSelectHome() {
onCallbackMenuEvent("menu:home");
}
void onCallbackPlayerPrevious();
void onCallbackPlayerNext();
void onCallbackPlayerFinished();
protected:
bool m_fullScreen;
};
}

Some files were not shown because too many files have changed in this diff Show More