From ac7a95223a6314cca6250495ea59c3cf7e46e89e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Mon, 26 Feb 2018 18:09:49 +0100 Subject: [PATCH] supervisor: Make it a HTTP server MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The supervisor now run as an HTTP server by default. Change-Id: Ia0a654cd97c941f15b212c5364d739e2196662e4 Signed-off-by: José Bollo --- memo-supervisor.txt | 1180 ++++++++----------------------------------------- src/CMakeLists.txt | 2 +- src/afb-supervision.c | 5 +- src/afs-config.c | 429 ++++++++++++++++++ src/afs-config.h | 40 ++ src/afs-discover.h | 21 + src/afs-main.c | 196 ++++++++ src/afs-supervision.h | 3 +- src/afs-supervisor.c | 192 +++----- src/afs-supervisor.h | 23 + 10 files changed, 964 insertions(+), 1127 deletions(-) create mode 100644 src/afs-config.c create mode 100644 src/afs-config.h create mode 100644 src/afs-discover.h create mode 100644 src/afs-main.c create mode 100644 src/afs-supervisor.h diff --git a/memo-supervisor.txt b/memo-supervisor.txt index 6d901003..9f996b78 100644 --- a/memo-supervisor.txt +++ b/memo-supervisor.txt @@ -2,29 +2,16 @@ Run the supervisor on the target for the public IP: --------------------------------------------------- - # ip address show + # afs-supervisor --port 1712 --token HELLO - 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 - link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 - inet 127.0.0.1/8 scope host lo - valid_lft forever preferred_lft forever - 2: eth0: mtu 1500 qdisc mq state UP group default qlen 1000 - link/ether ee:85:bb:23:a2:26 brd ff:ff:ff:ff:ff:ff - inet 192.168.0.34/24 brd 192.168.0.255 scope global eth0 - valid_lft forever preferred_lft forever +Run the client +-------------- - # afs-supervisor 192.168.0.34:5555/supervisor + # afb-client-demo -H host:1712/api?token=HELLO -Run the direct client ---------------------- - # afb-client-demo -H -d 192.168.0.34:5555/ - -It is an issue that supervisor provides a direct client. -This may change in some future to include HTTP websocket negociation and token exchange. - -Commands that can be run: -------------------------- +verbs that can be run, all are of the API 'supervisor': +------------------------------------------------------- - discover @@ -73,10 +60,6 @@ Commands that can be run: allows to trace specific session or any session - actually events generated by tracing are named with the prefix - "$/" (that is the internal prefix of supervision in binders) - could change in future - the pid isn't returned in the event (not sure to want it but open...) use "name" and "tag" feature of "trace" to discrimate events on the client side. @@ -84,1019 +67,218 @@ Commands that can be run: Examples of dialog: ------------------- -discover -ON-REPLY-SUCCESS 1:discover: -null - - -list -ON-REPLY-SUCCESS 2:list: +supervisor discover +ON-REPLY 1:supervisor/discover: OK { - "4123":{ - "pid":4123, - "uid":0, - "gid":0, - "id":"nfc-binding", - "label":"User::App::nfc-binding", - "user":"0" - }, - "4120":{ - "pid":4120, - "uid":0, - "gid":0, - "id":"homescreen-service-2017", - "label":"User::App::homescreen-service-2017", - "user":"0" - }, - "4119":{ - "pid":4119, - "uid":0, - "gid":0, - "id":"homescreen-2017", - "label":"User::App::homescreen-2017", - "user":"0" - }, - "4118":{ - "pid":4118, - "uid":0, - "gid":0, - "id":"agl-service-wifi", - "label":"User::App::agl-service-wifi", - "user":"0" - }, - "4117":{ - "pid":4117, - "uid":0, - "gid":0, - "id":"windowmanager-service-2017", - "label":"User::App::windowmanager-service-2017", - "user":"0" - }, - "4116":{ - "pid":4116, - "uid":0, - "gid":0, - "id":"agl-service-geoclue", - "label":"User::App::agl-service-geoclue", - "user":"0" - }, - "4115":{ - "pid":4115, - "uid":0, - "gid":0, - "id":"persistence-binding", - "label":"User::App::persistence-binding", - "user":"0" - }, - "4113":{ - "pid":4113, - "uid":0, - "gid":0, - "id":"agl-service-bluetooth", - "label":"User::App::agl-service-bluetooth", - "user":"0" - }, - "4114":{ - "pid":4114, - "uid":0, - "gid":0, - "id":"agl-identity-service", - "label":"User::App::agl-identity-service", - "user":"0" - }, - "4112":{ - "pid":4112, - "uid":0, - "gid":0, - "id":"agl-service-unicens", - "label":"User::App::agl-service-unicens", - "user":"0" - }, - "3734":{ - "pid":3734, - "uid":0, - "gid":0, - "id":"System", - "label":"System", - "user":"0" + "jtype":"afb-reply", + "request":{ + "status":"success", + "uuid":"22563ce6-e07f-4284-91f8-e7eb7ec4ef21" } } -config {"pid":4117} -ON-REPLY-SUCCESS 4:config: +supervisor list +ON-REPLY 2:supervisor/list: OK { - "console":".\/AFB-console.out", - "rootdir":"\/var\/local\/lib\/afm\/applications\/windowmanager-service-2017\/0.1", - "roothttp":".", - "rootbase":"\/opa", - "rootapi":"\/api", - "workdir":"\/home\/0\/app-data\/windowmanager-service-2017", - "uploaddir":".", - "token":"HELLO", - "name":"afbd-windowmanager-service-2017@0.1", - "aliases":[ - "\/monitoring" - ], - "dbus_clients":[ - ], - "dbus_servers":[ - ], - "ws_clients":[ - ], - "ws_servers":[ - "sd:windowmanager" - ], - "so_bindings":[ - "\/var\/local\/lib\/afm\/applications\/windowmanager-service-2017\/0.1\/lib\/windowmanager-service.so" - ], - "ldpaths":[ - "\/usr\/lib\/afb" - ], - "weak_ldpaths":[ - ], - "calls":[ - ], - "exec":[ - ], - "httpdPort":1039, - "cacheTimeout":100000, - "apiTimeout":20, - "cntxTimeout":32000000, - "nbSessionMax":10, - "mode":"local", - "tracereq":"no", - "traceditf":"no", - "tracesvc":"no", - "traceevt":"no", - "no_ldpaths":false, - "noHttpd":false, - "background":false, - "monitoring":true, - "random_token":false + "response":{ + "7054":{ + "pid":7054, + "uid":1001, + "gid":1001, + "id":"NoLabel", + "label":"NoLabel", + "user":"1001" + } + }, + "jtype":"afb-reply", + "request":{ + "status":"success" + } } -sessions {"pid":4117} -ON-REPLY-SUCCESS 5:sessions: + +supervisor config {"pid":7054} +ON-REPLY 3:supervisor/config: OK { - "afb-client-demo":{ - "token":"HELLO" + "response":{ + "console":".\/AFB-console.out", + "rootdir":".", + "roothttp":"..\/test", + "rootbase":"\/opa", + "rootapi":"\/api", + "workdir":".", + "uploaddir":".", + "token":"", + "name":null, + "aliases":[ + "\/monitoring" + ], + "dbus_clients":[ + ], + "dbus_servers":[ + ], + "ws_clients":[ + ], + "ws_servers":[ + ], + "so_bindings":[ + ], + "ldpaths":[ + "\/opt\/jobol\/lib64\/afb" + ], + "weak_ldpaths":[ + ], + "calls":[ + ], + "exec":[ + ], + "httpdPort":5555, + "cacheTimeout":100000, + "apiTimeout":20, + "cntxTimeout":32000000, + "nbSessionMax":10, + "mode":"local", + "tracereq":"no", + "traceditf":"no", + "tracesvc":"no", + "traceevt":"no", + "traceses":"no", + "no_ldpaths":false, + "noHttpd":false, + "background":false, + "monitoring":true, + "random_token":false }, - "fa050ca1-80b4-41af-bf72-4a1a8e7ee5b6":{ - "token":"HELLO" + "jtype":"afb-reply", + "request":{ + "status":"success" } } -do {"pid":4117,"api":"monitor","verb":"get","args":{"apis":true}} -ON-REPLY-SUCCESS 6:do: + + + +supervisor sessions {"pid":7054} +ON-REPLY 4:supervisor/sessions: OK { - "apis":{ - "monitor":{ - "openapi":"3.0.0", - "info":{ - "description":"monitoring of bindings and internals", - "title":"monitor", - "version":"1.0", - "x-binding-c-generator":{ - "api":"monitor", - "version":2, - "prefix":"f_", - "postfix":"", - "preinit":null, - "init":null, - "onevent":null, - "scope":"static", - "private":true - } - }, - "servers":[ - { - "url":"ws:\/\/{host}:{port}\/api\/monitor", - "description":"The API server.", - "variables":{ - "host":{ - "default":"localhost" - }, - "port":{ - "default":"1234" - } - }, - "x-afb-events":[ - { - "$ref":"#\/components\/schemas\/afb-event" - } - ] - } - ], - "components":{ - "schemas":{ - "afb-reply":{ - "$ref":"#\/components\/schemas\/afb-reply-v1" - }, - "afb-event":{ - "$ref":"#\/components\/schemas\/afb-event-v1" - }, - "afb-reply-v1":{ - "title":"Generic response.", - "type":"object", - "required":[ - "jtype", - "request" - ], - "properties":{ - "jtype":{ - "type":"string", - "const":"afb-reply" - }, - "request":{ - "type":"object", - "required":[ - "status" - ], - "properties":{ - "status":{ - "type":"string" - }, - "info":{ - "type":"string" - }, - "token":{ - "type":"string" - }, - "uuid":{ - "type":"string" - }, - "reqid":{ - "type":"string" - } - } - }, - "response":{ - "type":"object" - } - } - }, - "afb-event-v1":{ - "type":"object", - "required":[ - "jtype", - "event" - ], - "properties":{ - "jtype":{ - "type":"string", - "const":"afb-event" - }, - "event":{ - "type":"string" - }, - "data":{ - "type":"object" - } - } - }, - "set-verbosity":{ - "anyOf":[ - { - "$ref":"#\/components\/schemas\/verbosity-map" - }, - { - "$ref":"#\/components\/schemas\/verbosity-level" - } - ] - }, - "get-request":{ - "type":"object", - "properties":{ - "verbosity":{ - "$ref":"#\/components\/schemas\/get-verbosity" - }, - "apis":{ - "$ref":"#\/components\/schemas\/get-apis" - } - } - }, - "get-response":{ - "type":"object", - "properties":{ - "verbosity":{ - "$ref":"#\/components\/schemas\/verbosity-map" - }, - "apis":{ - "type":"object" - } - } - }, - "get-verbosity":{ - "anyOf":[ - { - "type":"boolean" - }, - { - "type":"array", - "items":{ - "type":"string" - } - }, - { - "type":"object" - } - ] - }, - "get-apis":{ - "anyOf":[ - { - "type":"boolean" - }, - { - "type":"array", - "items":{ - "type":"string" - } - }, - { - "type":"object" - } - ] - }, - "verbosity-map":{ - "type":"object", - "patternProperties":{ - "^.*$":{ - "$ref":"#\/components\/schemas\/verbosity-level" - } - } - }, - "verbosity-level":{ - "enum":[ - "debug", - 3, - "info", - 2, - "notice", - "warning", - 1, - "error", - 0 - ] - }, - "trace-add":{ - "anyOf":[ - { - "type":"array", - "items":{ - "$ref":"#\/components\/schemas\/trace-add-object" - } - }, - { - "$ref":"#\/components\/schemas\/trace-add-any" - } - ] - }, - "trace-add-any":{ - "anyOf":[ - { - "$ref":"#\/components\/schemas\/trace-add-request" - }, - { - "$ref":"#\/components\/schemas\/trace-add-object" - } - ] - }, - "trace-add-object":{ - "type":"object", - "properties":{ - "name":{ - "type":"string", - "description":"name of the generated event", - "default":"trace" - }, - "tag":{ - "type":"string", - "description":"tag for grouping traces", - "default":"trace" - }, - "api":{ - "type":"string", - "description":"api for requests, daemons and services" - }, - "verb":{ - "type":"string", - "description":"verb for requests" - }, - "uuid":{ - "type":"string", - "description":"uuid of session for requests" - }, - "pattern":{ - "type":"string", - "description":"pattern for events" - }, - "request":{ - "$ref":"#\/components\/schemas\/trace-add-request" - }, - "daemon":{ - "$ref":"#\/components\/schemas\/trace-add-daemon" - }, - "service":{ - "$ref":"#\/components\/schemas\/trace-add-service" - }, - "event":{ - "$ref":"#\/components\/schemas\/trace-add-event" - }, - "session":{ - "$ref":"#\/components\/schemas\/trace-add-session" - }, - "for":{ - "$ref":"#\/components\/schemas\/trace-add" - } - }, - "examples":[ - { - "tag":"1", - "for":[ - "common", - { - "api":"xxx", - "request":"*", - "daemon":"*", - "service":"*" - } - ] - } - ] - }, - "trace-add-request":{ - "anyOf":[ - { - "type":"array", - "items":{ - "$ref":"#\/components\/schemas\/trace-request-names" - } - }, - { - "$ref":"#\/components\/schemas\/trace-request-names" - } - ] - }, - "trace-request-names":{ - "title":"name of traceable items of requests", - "enum":[ - "*", - "addref", - "all", - "args", - "begin", - "common", - "context", - "context_get", - "context_set", - "end", - "event", - "extra", - "fail", - "get", - "json", - "life", - "ref", - "result", - "session", - "session_close", - "session_set_LOA", - "simple", - "store", - "stores", - "subcall", - "subcall_result", - "subcalls", - "subcallsync", - "subcallsync_result", - "subscribe", - "success", - "unref", - "unstore", - "unsubscribe", - "vverbose" - ] - }, - "trace-add-daemon":{ - "anyOf":[ - { - "type":"array", - "items":{ - "$ref":"#\/components\/schemas\/trace-daemon-names" - } - }, - { - "$ref":"#\/components\/schemas\/trace-daemon-names" - } - ] - }, - "trace-daemon-names":{ - "title":"name of traceable items of daemons", - "enum":[ - "*", - "all", - "common", - "event_broadcast_after", - "event_broadcast_before", - "event_make", - "extra", - "get_event_loop", - "get_system_bus", - "get_user_bus", - "queue_job", - "require_api", - "require_api_result", - "rootdir_get_fd", - "rootdir_open_locale", - "unstore_req", - "vverbose" - ] - }, - "trace-add-service":{ - "anyOf":[ - { - "type":"array", - "items":{ - "$ref":"#\/components\/schemas\/trace-service-names" - } - }, - { - "$ref":"#\/components\/schemas\/trace-service-names" - } - ] - }, - "trace-service-names":{ - "title":"name of traceable items of services", - "enum":[ - "*", - "all", - "call", - "call_result", - "callsync", - "callsync_result", - "on_event_after", - "on_event_before", - "start_after", - "start_before" - ] - }, - "trace-add-event":{ - "anyOf":[ - { - "type":"array", - "items":{ - "$ref":"#\/components\/schemas\/trace-event-names" - } - }, - { - "$ref":"#\/components\/schemas\/trace-event-names" - } - ] - }, - "trace-event-names":{ - "title":"name of traceable items of events", - "enum":[ - "*", - "all", - "broadcast_after", - "broadcast_before", - "common", - "create", - "drop", - "extra", - "name", - "push_after", - "push_before" - ] - }, - "trace-add-session":{ - "anyOf":[ - { - "type":"array", - "items":{ - "$ref":"#\/components\/schemas\/trace-session-names" - } - }, - { - "$ref":"#\/components\/schemas\/trace-session-names" - } - ] - }, - "trace-session-names":{ - "title":"name of traceable items for sessions", - "enum":[ - "*", - "addref", - "all", - "close", - "common", - "create", - "destroy", - "renew", - "unref" - ] - }, - "trace-drop":{ - "anyOf":[ - { - "type":"boolean" - }, - { - "type":"object", - "properties":{ - "event":{ - "anyOf":[ - { - "type":"string" - }, - { - "type":"array", - "items":"string" - } - ] - }, - "tag":{ - "anyOf":[ - { - "type":"string" - }, - { - "type":"array", - "items":"string" - } - ] - }, - "uuid":{ - "anyOf":[ - { - "type":"string" - }, - { - "type":"array", - "items":"string" - } - ] - } - } - } - ] - } - } - }, - "paths":{ - "\/get":{ - "description":"Get monitoring data.", - "get":{ - "x-permissions":{ - "session":"check" - }, - "parameters":[ - { - "in":"query", - "name":"verbosity", - "required":false, - "schema":{ - "$ref":"#\/components\/schemas\/get-verbosity" - } - }, - { - "in":"query", - "name":"apis", - "required":false, - "schema":{ - "$ref":"#\/components\/schemas\/get-apis" - } - } - ], - "responses":{ - "200":{ - "description":"A complex object array response", - "content":{ - "application\/json":{ - "schema":{ - "$ref":"#\/components\/schemas\/afb-reply" - } - } - } - } - } - } - }, - "\/set":{ - "description":"Set monitoring actions.", - "get":{ - "x-permissions":{ - "session":"check" - }, - "parameters":[ - { - "in":"query", - "name":"verbosity", - "required":false, - "schema":{ - "$ref":"#\/components\/schemas\/set-verbosity" - } - } - ], - "responses":{ - "200":{ - "description":"A complex object array response", - "content":{ - "application\/json":{ - "schema":{ - "$ref":"#\/components\/schemas\/afb-reply" - } - } - } - } - } - } - }, - "\/trace":{ - "description":"Set monitoring actions.", - "get":{ - "x-permissions":{ - "session":"check" - }, - "parameters":[ - { - "in":"query", - "name":"add", - "required":false, - "schema":{ - "$ref":"#\/components\/schemas\/trace-add" - } - }, - { - "in":"query", - "name":"drop", - "required":false, - "schema":{ - "$ref":"#\/components\/schemas\/trace-drop" - } - } - ], - "responses":{ - "200":{ - "description":"A complex object array response", - "content":{ - "application\/json":{ - "schema":{ - "$ref":"#\/components\/schemas\/afb-reply" - } - } - } - } - } - } - }, - "\/session":{ - "description":"describes the session.", - "get":{ - "x-permissions":{ - "session":"check" - }, - "parameters":[ - { - "in":"query", - "name":"refresh-token", - "required":false, - "schema":{ - "type":"boolean" - } - } - ], - "responses":{ - "200":{ - "description":"A complex object array response", - "content":{ - "application\/json":{ - "schema":{ - "$ref":"#\/components\/schemas\/afb-reply" - } - } - } - } - } - } - } - } + "response":{ + "2273ff8d-ee46-4059-959b-0f90fa90f25e":{ + "token":"" }, - "windowmanager":{ - "openapi":"3.0.0", - "info":{ - "title":"windowmanager", - "version":"0.0.0", - "description":"windowmanager" - }, - "paths":{ - "\/requestsurface":{ - "get":{ - "responses":{ - "200":{ - "description":"requestsurface" - } - } - } - }, - "\/requestsurfacexdg":{ - "get":{ - "responses":{ - "200":{ - "description":"requestsurfacexdg" - } - } - } - }, - "\/activatesurface":{ - "get":{ - "responses":{ - "200":{ - "description":"activatesurface" - } - } - } - }, - "\/deactivatesurface":{ - "get":{ - "responses":{ - "200":{ - "description":"deactivatesurface" - } - } - } - }, - "\/enddraw":{ - "get":{ - "responses":{ - "200":{ - "description":"enddraw" - } - } - } - }, - "\/getdisplayinfo":{ - "get":{ - "responses":{ - "200":{ - "description":"getdisplayinfo" - } - } - } - }, - "\/getareainfo":{ - "get":{ - "responses":{ - "200":{ - "description":"getareainfo" - } - } - } - }, - "\/wm_subscribe":{ - "get":{ - "responses":{ - "200":{ - "description":"wm_subscribe" - } - } - } - }, - "\/list_drawing_names":{ - "get":{ - "responses":{ - "200":{ - "description":"list_drawing_names" - } - } - } - }, - "\/ping":{ - "get":{ - "responses":{ - "200":{ - "description":"ping" - } - } - } - }, - "\/debug_status":{ - "get":{ - "responses":{ - "200":{ - "description":"debug_status" - } - } - } - }, - "\/debug_layers":{ - "get":{ - "responses":{ - "200":{ - "description":"debug_layers" - } - } - } - }, - "\/debug_surfaces":{ - "get":{ - "responses":{ - "200":{ - "description":"debug_surfaces" - } - } - } - }, - "\/debug_terminate":{ - "get":{ - "responses":{ - "200":{ - "description":"debug_terminate" - } - } - } - } - } + "22563ce6-e07f-4284-91f8-e7eb7ec4ef21":{ + "token":"" } + }, + "jtype":"afb-reply", + "request":{ + "status":"success" } } -trace { "pid": 4117, "add": { "request": "common" } } -ON-EVENT-CREATE: [4:$/trace] -ON-EVENT-SUBSCRIBE 15:trace: [4:$/trace] -ON-REPLY-SUCCESS 15:trace: -null -ON-EVENT-PUSH: [4:$/trace] + +supervisor do {"pid":7054,"api":"monitor","verb":"get","args":{"apis":true}} +.....VERY LONG RESPONSE..... + + + + +supervisor trace { "pid": 7054, "add": { "request": "common" } } +ON-REPLY 6:supervisor/trace: OK { - "time":"30862.255651", - "tag":"trace", - "type":"request", - "id":51, + "jtype":"afb-reply", "request":{ - "index":5, - "api":"hello", - "verb":"ping", - "action":"begin", - "session":"fa050ca1-80b4-41af-bf72-4a1a8e7ee5b6" + "status":"success" } } -ON-EVENT-PUSH: [4:$/trace] + + + + + +ON-EVENT supervisor/trace: { - "time":"30862.255788", - "tag":"trace", - "type":"request", - "id":52, - "request":{ - "index":5, - "api":"hello", - "verb":"ping", - "action":"json", - "session":"fa050ca1-80b4-41af-bf72-4a1a8e7ee5b6" - }, + "event":"supervisor\/trace", "data":{ - "result":{ - "toto":"1" + "time":"34353.598120", + "tag":"trace", + "type":"request", + "id":34, + "request":{ + "index":1, + "api":"ave", + "verb":"ping", + "action":"begin", + "session":"be67cfb8-a346-47c1-ac63-65aaff3599bf" } - } + }, + "jtype":"afb-event" } -ON-EVENT-PUSH: [4:$/trace] +ON-EVENT supervisor/trace: { - "time":"30862.255871", - "tag":"trace", - "type":"request", - "id":53, - "request":{ - "index":5, - "api":"hello", - "verb":"ping", - "action":"success", - "session":"fa050ca1-80b4-41af-bf72-4a1a8e7ee5b6" + "event":"supervisor\/trace", + "data":{ + "time":"34353.598182", + "tag":"trace", + "type":"request", + "id":35, + "request":{ + "index":1, + "api":"ave", + "verb":"ping", + "action":"json", + "session":"be67cfb8-a346-47c1-ac63-65aaff3599bf" + }, + "data":{ + "result":"true" + } }, + "jtype":"afb-event" +} +ON-EVENT supervisor/trace: +{ + "event":"supervisor\/trace", "data":{ - "result":"Some String", - "info":"Ping Binder Daemon tag=pingSample count=1 query={ \"toto\": \"1\" }" - } + "time":"34353.598214", + "tag":"trace", + "type":"request", + "id":36, + "request":{ + "index":1, + "api":"ave", + "verb":"ping", + "action":"success", + "session":"be67cfb8-a346-47c1-ac63-65aaff3599bf" + }, + "data":{ + "result":"Some String", + "info":"Ping Binder Daemon tag=pingSample count=1 query=\"true\"" + } + }, + "jtype":"afb-event" } -ON-EVENT-PUSH: [4:$/trace] +ON-EVENT supervisor/trace: { - "time":"30862.255980", - "tag":"trace", - "type":"request", - "id":54, - "request":{ - "index":5, - "api":"hello", - "verb":"ping", - "action":"end", - "session":"fa050ca1-80b4-41af-bf72-4a1a8e7ee5b6" - } + "event":"supervisor\/trace", + "data":{ + "time":"34353.598292", + "tag":"trace", + "type":"request", + "id":37, + "request":{ + "index":1, + "api":"ave", + "verb":"ping", + "action":"end", + "session":"be67cfb8-a346-47c1-ac63-65aaff3599bf" + } + }, + "jtype":"afb-event" } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f72d312e..bfe187f5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -89,7 +89,7 @@ INSTALL(TARGETS afb-daemon ########################################### # build and install afb-daemon ########################################### -ADD_EXECUTABLE(afs-supervisor afs-supervisor.c afs-discover.c) +ADD_EXECUTABLE(afs-supervisor afs-main.c afs-supervisor.c afs-discover.c afs-config.c) TARGET_LINK_LIBRARIES(afs-supervisor afb-lib ${link_libraries} diff --git a/src/afb-supervision.c b/src/afb-supervision.c index 1ff8f8b5..97595245 100644 --- a/src/afb-supervision.c +++ b/src/afb-supervision.c @@ -51,7 +51,8 @@ extern struct afb_config *main_config; /* api and apiset name */ -static const char supervision_apiname[] = AFS_SURPERVISION_APINAME_INTERNAL; +static const char supervision_apiname[] = AFS_SURPERVISION_APINAME; +static const char supervisor_apiname[] = AFS_SURPERVISOR_APINAME; /* path of the supervision socket */ static const char supervisor_socket_path[] = AFS_SURPERVISION_SOCKET; @@ -346,7 +347,7 @@ static void on_supervision_call(void *closure, struct afb_xreq *xreq) break; case Trace: if (!trace) - trace = afb_trace_create(supervision_apiname, NULL /* not bound to any session */); + trace = afb_trace_create(supervisor_apiname, NULL /* not bound to any session */); req = xreq_to_req(xreq); add = drop = NULL; diff --git a/src/afs-config.c b/src/afs-config.c new file mode 100644 index 00000000..80504d05 --- /dev/null +++ b/src/afs-config.c @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2015, 2016, 2017 "IoT.bzh" + * Author José Bollo + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-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. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include "verbose.h" +#include "afs-config.h" + +#if !defined(AFB_VERSION) +#error "you should define AFB_VERSION" +#endif + +// default +#define DEFLT_CNTX_TIMEOUT 32000000 // default Client Connection + // Timeout: few more than one year +#define DEFLT_API_TIMEOUT 20 // default Plugin API Timeout [0=NoLimit + // for Debug Only] +#define DEFLT_CACHE_TIMEOUT 100000 // default Static File Chache + // [Client Side Cache + // 100000~=1day] +#define CTX_NBCLIENTS 10 // allow a default of 10 authenticated + // clients + + +// Define command line option +#define SET_ROOT_DIR 6 +#define SET_ROOT_BASE 7 +#define SET_ROOT_API 8 + +#define SET_CACHE_TIMEOUT 10 +#define SET_SESSION_DIR 11 + +#define SET_APITIMEOUT 14 +#define SET_CNTXTIMEOUT 15 + +#define SET_SESSIONMAX 23 + +#define SET_ROOT_HTTP 26 + +#define DISPLAY_HELP 'h' +#define SET_NAME 'n' +#define SET_TCP_PORT 'p' +#define SET_QUIET 'q' +#define SET_AUTH_TOKEN 't' +#define SET_UPLOAD_DIR 'u' +#define DISPLAY_VERSION 'V' +#define SET_VERBOSE 'v' +#define SET_WORK_DIR 'w' + +const char shortopts[] = + "hn:p:qrt:u:Vvw:" +; + +// Command line structure hold cli --command + help text +typedef struct { + int val; // command number within application + int has_arg; // command number within application + char *name; // command as used in --xxxx cli + char *help; // help text +} AFB_options; + +// Supported option +static AFB_options cliOptions[] = { +/* *INDENT-OFF* */ + {SET_VERBOSE, 0, "verbose", "Verbose Mode, repeat to increase verbosity"}, + {SET_QUIET, 0, "quiet", "Quiet Mode, repeat to decrease verbosity"}, + + {SET_NAME, 1, "name", "Set the visible name"}, + + {SET_TCP_PORT, 1, "port", "HTTP listening TCP port [default 1234]"}, + {SET_ROOT_HTTP, 1, "roothttp", "HTTP Root Directory [default no root http (files not served but apis still available)]"}, + {SET_ROOT_BASE, 1, "rootbase", "Angular Base Root URL [default /opa]"}, + {SET_ROOT_API, 1, "rootapi", "HTML Root API URL [default /api]"}, + + {SET_APITIMEOUT, 1, "apitimeout", "Binding API timeout in seconds [default 10]"}, + {SET_CNTXTIMEOUT, 1, "cntxtimeout", "Client Session Context Timeout [default 900]"}, + {SET_CACHE_TIMEOUT, 1, "cache-eol", "Client cache end of live [default 3600]"}, + + {SET_WORK_DIR, 1, "workdir", "Set the working directory [default: $PWD or current working directory]"}, + {SET_UPLOAD_DIR, 1, "uploaddir", "Directory for uploading files [default: workdir]"}, + {SET_ROOT_DIR, 1, "rootdir", "Root Directory of the application [default: workdir]"}, + {SET_SESSION_DIR, 1, "sessiondir", "OBSOLETE (was: Sessions file path)"}, + + {SET_AUTH_TOKEN, 1, "token", "Initial Secret [default=random, use --token="" to allow any token]"}, + + {DISPLAY_VERSION, 0, "version", "Display version and copyright"}, + {DISPLAY_HELP, 0, "help", "Display this help"}, + + {SET_SESSIONMAX, 1, "session-max", "Max count of session simultaneously [default 10]"}, + + {0, 0, NULL, NULL} +/* *INDENT-ON* */ +}; + + +struct enumdesc +{ + const char *name; + int value; +}; + +/*---------------------------------------------------------- + | printversion + | print version and copyright + +--------------------------------------------------------- */ +static void printVersion(FILE * file) +{ + static const char version[] = + "\n" + " afs-supervisor [Application Framework Supervisor] version="AFB_VERSION"\n" + "\n" + " Copyright (C) 2015-2018 \"IoT.bzh\"\n" + " afs-supervisor comes with ABSOLUTELY NO WARRANTY.\n" + " Licence Apache 2\n" + "\n"; + + fprintf(file, "%s", version); +} + +/*---------------------------------------------------------- + | printHelp + | print information from long option array + +--------------------------------------------------------- */ + +static void printHelp(FILE * file, const char *name) +{ + int ind; + char command[50]; + + fprintf(file, "%s:\nallowed options\n", name); + for (ind = 0; cliOptions[ind].name != NULL; ind++) { + strcpy(command, cliOptions[ind].name); + if (cliOptions[ind].has_arg) + strcat(command, "=xxxx"); + fprintf(file, " --%-15s %s\n", command, cliOptions[ind].help); + } + fprintf(file, + "Example:\n %s --verbose --port=1234 --token='azerty'\n", + name); +} + + +/*--------------------------------------------------------- + | helpers for argument scanning + +--------------------------------------------------------- */ + +static const char *name_of_option(int optc) +{ + AFB_options *o = cliOptions; + while (o->name && o->val != optc) + o++; + return o->name ? : ""; +} + +static const char *current_argument(int optc) +{ + if (optarg == 0) { + ERROR("option [--%s] needs a value i.e. --%s=xxx", + name_of_option(optc), name_of_option(optc)); + exit(1); + } + return optarg; +} + +static char *argvalstr(int optc) +{ + char *result = strdup(current_argument(optc)); + if (result == NULL) { + ERROR("can't alloc memory"); + exit(1); + } + return result; +} + +static int argvalint(int optc, int mini, int maxi, int base) +{ + const char *beg, *end; + long int val; + beg = current_argument(optc); + val = strtol(beg, (char**)&end, base); + if (*end || end == beg) { + ERROR("option [--%s] requires a valid integer (found %s)", + name_of_option(optc), beg); + exit(1); + } + if (val < (long int)mini || val > (long int)maxi) { + ERROR("option [--%s] value out of bounds (not %d<=%ld<=%d)", + name_of_option(optc), mini, val, maxi); + exit(1); + } + return (int)val; +} + +static int argvalintdec(int optc, int mini, int maxi) +{ + return argvalint(optc, mini, maxi, 10); +} + +static void noarg(int optc) +{ + if (optarg != 0) { + ERROR("option [--%s] need no value (found %s)", name_of_option(optc), optarg); + exit(1); + } +} + +/*--------------------------------------------------------- + | Parse option and launch action + +--------------------------------------------------------- */ + +static void parse_arguments(int argc, char **argv, struct afs_config *config) +{ + char *programName = argv[0]; + int optc, ind; + int nbcmd; + struct option *gnuOptions; + + // ------------------ Process Command Line ----------------------- + + // build GNU getopt info from cliOptions + nbcmd = sizeof(cliOptions) / sizeof(AFB_options); + gnuOptions = malloc(sizeof(*gnuOptions) * (unsigned)nbcmd); + for (ind = 0; ind < nbcmd; ind++) { + gnuOptions[ind].name = cliOptions[ind].name; + gnuOptions[ind].has_arg = cliOptions[ind].has_arg; + gnuOptions[ind].flag = 0; + gnuOptions[ind].val = cliOptions[ind].val; + } + + // get all options from command line + while ((optc = getopt_long(argc, argv, shortopts, gnuOptions, NULL)) != EOF) { + switch (optc) { + case SET_VERBOSE: + verbosity++; + break; + + case SET_QUIET: + verbosity--; + break; + + case SET_TCP_PORT: + config->httpdPort = argvalintdec(optc, 1024, 32767); + break; + + case SET_APITIMEOUT: + config->apiTimeout = argvalintdec(optc, 0, INT_MAX); + break; + + case SET_CNTXTIMEOUT: + config->cntxTimeout = argvalintdec(optc, 0, INT_MAX); + break; + + case SET_ROOT_DIR: + config->rootdir = argvalstr(optc); + INFO("Forcing Rootdir=%s", config->rootdir); + break; + + case SET_ROOT_HTTP: + config->roothttp = argvalstr(optc); + INFO("Forcing Root HTTP=%s", config->roothttp); + break; + + case SET_ROOT_BASE: + config->rootbase = argvalstr(optc); + INFO("Forcing Rootbase=%s", config->rootbase); + break; + + case SET_ROOT_API: + config->rootapi = argvalstr(optc); + INFO("Forcing Rootapi=%s", config->rootapi); + break; + + case SET_AUTH_TOKEN: + config->token = argvalstr(optc); + break; + + case SET_UPLOAD_DIR: + config->uploaddir = argvalstr(optc); + break; + + case SET_WORK_DIR: + config->workdir = argvalstr(optc); + break; + + case SET_CACHE_TIMEOUT: + config->cacheTimeout = argvalintdec(optc, 0, INT_MAX); + break; + + case SET_SESSIONMAX: + config->nbSessionMax = argvalintdec(optc, 1, INT_MAX); + break; + + case SET_NAME: + config->name = argvalstr(optc); + break; + + case DISPLAY_VERSION: + noarg(optc); + printVersion(stdout); + exit(0); + + case DISPLAY_HELP: + printHelp(stdout, programName); + exit(0); + + default: + exit(1); + } + } + free(gnuOptions); +} + +static void fulfill_config(struct afs_config *config) +{ + // default HTTP port + if (config->httpdPort == 0) + config->httpdPort = 1234; + + // default binding API timeout + if (config->apiTimeout == 0) + config->apiTimeout = DEFLT_API_TIMEOUT; + + // cache timeout default one hour + if (config->cacheTimeout == 0) + config->cacheTimeout = DEFLT_CACHE_TIMEOUT; + + // cache timeout default one hour + if (config->cntxTimeout == 0) + config->cntxTimeout = DEFLT_CNTX_TIMEOUT; + + // max count of sessions + if (config->nbSessionMax == 0) + config->nbSessionMax = CTX_NBCLIENTS; + + /* set directories */ + if (config->workdir == NULL) + config->workdir = "."; + + if (config->rootdir == NULL) + config->rootdir = "."; + + if (config->uploaddir == NULL) + config->uploaddir = "."; + + // if no Angular/HTML5 rootbase let's try '/' as default + if (config->rootbase == NULL) + config->rootbase = "/opa"; + + if (config->rootapi == NULL) + config->rootapi = "/api"; +} + +void afs_config_dump(struct afs_config *config) +{ +#define NN(x) (x)?:"" +#define P(...) fprintf(stderr, __VA_ARGS__) +#define PF(x) P("-- %15s: ", #x) +#define PE P("\n") +#define S(x) PF(x);P("%s",NN(config->x));PE; +#define D(x) PF(x);P("%d",config->x);PE; + + P("---BEGIN-OF-CONFIG---\n"); + S(rootdir) + S(roothttp) + S(rootbase) + S(rootapi) + S(workdir) + S(uploaddir) + S(token) + S(name) + + D(httpdPort) + D(cacheTimeout) + D(apiTimeout) + D(cntxTimeout) + D(nbSessionMax) + P("---END-OF-CONFIG---\n"); + +#undef V +#undef E +#undef L +#undef B +#undef D +#undef S +#undef PE +#undef PF +#undef P +#undef NN +} + +static void parse_environment(struct afs_config *config) +{ +} + +struct afs_config *afs_config_parse_arguments(int argc, char **argv) +{ + struct afs_config *result; + + result = calloc(1, sizeof *result); + + parse_environment(result); + parse_arguments(argc, argv, result); + fulfill_config(result); + if (verbosity >= 3) + afs_config_dump(result); + return result; +} + diff --git a/src/afs-config.h b/src/afs-config.h new file mode 100644 index 00000000..826f6a25 --- /dev/null +++ b/src/afs-config.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015, 2016, 2017 "IoT.bzh" + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-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. + */ + +#pragma once + +// main config structure +struct afs_config { + char *rootdir; // base dir for files + char *roothttp; // directory for http files + char *rootbase; // Angular HTML5 base URL + char *rootapi; // Base URL for REST APIs + char *workdir; // where to run the program + char *uploaddir; // where to store transient files + char *token; // initial authentication token [default NULL no session] + char *name; /* name to set to the daemon */ + + /* integers */ + int httpdPort; + int cacheTimeout; + int apiTimeout; + int cntxTimeout; // Client Session Context timeout + int nbSessionMax; // max count of sessions +}; + +extern struct afs_config *afs_config_parse_arguments(int argc, char **argv); +extern void afs_config_dump(struct afs_config *config); + diff --git a/src/afs-discover.h b/src/afs-discover.h new file mode 100644 index 00000000..7a27a5df --- /dev/null +++ b/src/afs-discover.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author: José Bollo + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-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. + */ + +#pragma once + +extern void afs_discover(const char *pattern, void (*callback)(void *closure, pid_t pid), void *closure); + diff --git a/src/afs-main.c b/src/afs-main.c new file mode 100644 index 00000000..99689e90 --- /dev/null +++ b/src/afs-main.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2016, 2017 "IoT.bzh" + * Author José Bollo + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-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. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include + +#include "afb-common.h" +#include "afb-hsrv.h" +#include "afb-hswitch.h" +#include "afb-hreq.h" +#include "afb-apiset.h" +#include "afb-session.h" + +#include "afs-supervisor.h" +#include "afs-config.h" + +#include "verbose.h" +#include "jobs.h" +#include "process-name.h" + +/* the main config */ +struct afs_config *main_config; + +/* the main apiset */ +struct afb_apiset *main_apiset; + +/*************************************************************************************/ + +static int init_http_server(struct afb_hsrv *hsrv) +{ + if (!afb_hsrv_add_handler + (hsrv, main_config->rootapi, afb_hswitch_websocket_switch, main_apiset, 20)) + return 0; + + if (!afb_hsrv_add_handler + (hsrv, main_config->rootapi, afb_hswitch_apis, main_apiset, 10)) + return 0; + + if (main_config->roothttp != NULL) { + if (!afb_hsrv_add_alias + (hsrv, "", afb_common_rootdir_get_fd(), main_config->roothttp, + -10, 1)) + return 0; + } + + if (!afb_hsrv_add_handler + (hsrv, main_config->rootbase, afb_hswitch_one_page_api_redirect, NULL, + -20)) + return 0; + + return 1; +} + +static struct afb_hsrv *start_http_server() +{ + int rc; + struct afb_hsrv *hsrv; + + if (afb_hreq_init_download_path(main_config->uploaddir)) { + ERROR("unable to set the upload directory %s", main_config->uploaddir); + return NULL; + } + + hsrv = afb_hsrv_create(); + if (hsrv == NULL) { + ERROR("memory allocation failure"); + return NULL; + } + + if (!afb_hsrv_set_cache_timeout(hsrv, main_config->cacheTimeout) + || !init_http_server(hsrv)) { + ERROR("initialisation of httpd failed"); + afb_hsrv_put(hsrv); + return NULL; + } + + NOTICE("Waiting port=%d rootdir=%s", main_config->httpdPort, main_config->rootdir); + NOTICE("Browser URL= http://localhost:%d", main_config->httpdPort); + + rc = afb_hsrv_start(hsrv, (uint16_t) main_config->httpdPort, 15); + if (!rc) { + ERROR("starting of httpd failed"); + afb_hsrv_put(hsrv); + return NULL; + } + + return hsrv; +} + +static void start(int signum, void *arg) +{ + struct afb_hsrv *hsrv; + int rc; + + /* check illness */ + if (signum) { + ERROR("start aborted: received signal %s", strsignal(signum)); + exit(1); + } + + /* set the directories */ + mkdir(main_config->workdir, S_IRWXU | S_IRGRP | S_IXGRP); + if (chdir(main_config->workdir) < 0) { + ERROR("Can't enter working dir %s", main_config->workdir); + goto error; + } + if (afb_common_rootdir_set(main_config->rootdir) < 0) { + ERROR("failed to set common root directory"); + goto error; + } + + /* configure the daemon */ + if (afb_session_init(main_config->nbSessionMax, main_config->cntxTimeout, main_config->token)) { + ERROR("initialisation of session manager failed"); + goto error; + } + + main_apiset = afb_apiset_create("main", main_config->apiTimeout); + if (!main_apiset) { + ERROR("can't create main apiset"); + goto error; + } + + /* init the main apiset */ + rc = afs_supervisor_add(main_apiset); + if (rc < 0) { + ERROR("Can't create supervision's apiset: %m"); + goto error; + } + + /* start the services */ + if (afb_apiset_start_all_services(main_apiset, 1) < 0) + goto error; + + /* start the HTTP server */ + if (main_config->httpdPort <= 0) { + ERROR("no port is defined"); + goto error; + } + + if (!afb_hreq_init_cookie(main_config->httpdPort, main_config->rootapi, main_config->cntxTimeout)) { + ERROR("initialisation of HTTP cookies failed"); + goto error; + } + + hsrv = start_http_server(); + if (hsrv == NULL) + goto error; + + /* ready */ + sd_notify(1, "READY=1"); + afs_supervisor_discover(); + return; +error: + exit(1); +} + +/** + * initalize the supervision + */ +int main(int ac, char **av) +{ + /* scan arguments */ + main_config = afs_config_parse_arguments(ac, av); + if (main_config->name) { + verbose_set_name(main_config->name, 0); + process_name_set_name(main_config->name); + process_name_replace_cmdline(av, main_config->name); + } + /* enter job processing */ + jobs_start(3, 0, 10, start, av[1]); + WARNING("hoops returned from jobs_enter! [report bug]"); + return 1; +} + diff --git a/src/afs-supervision.h b/src/afs-supervision.h index 6fc2023b..edfa6a1b 100644 --- a/src/afs-supervision.h +++ b/src/afs-supervision.h @@ -45,4 +45,5 @@ struct afs_supervision_initiator char extra[27]; /**< zero terminated extra computed here to be 64-37 */ }; -#define AFS_SURPERVISION_APINAME_INTERNAL "$" +#define AFS_SURPERVISION_APINAME "$" +#define AFS_SURPERVISOR_APINAME "supervisor" diff --git a/src/afs-supervisor.c b/src/afs-supervisor.c index 1e92b9f3..71a00369 100644 --- a/src/afs-supervisor.c +++ b/src/afs-supervisor.c @@ -35,7 +35,6 @@ #include #include -#include "afs-supervision.h" #include "afb-systemd.h" #include "afb-session.h" #include "afb-cred.h" @@ -49,8 +48,11 @@ #include "jobs.h" #include "verbose.h" #include "wrap-json.h" +#include "process-name.h" -extern void afs_discover(const char *pattern, void (*callback)(void *closure, pid_t pid), void *closure); +#include "afs-supervision.h" +#include "afs-supervisor.h" +#include "afs-discover.h" /* supervised items */ struct supervised @@ -66,11 +68,8 @@ struct supervised }; /* api and apiset name */ -static const char supervision_apiname[] = AFS_SURPERVISION_APINAME_INTERNAL; -static const char supervisor_apiname[] = "supervisor"; - -/* the main apiset */ -struct afb_apiset *main_apiset; +static const char supervision_apiname[] = AFS_SURPERVISION_APINAME; +static const char supervisor_apiname[] = AFS_SURPERVISOR_APINAME; /* the empty apiset */ static struct afb_apiset *empty_apiset; @@ -86,7 +85,6 @@ static struct supervised *superviseds; /*************************************************************************************/ -static int afb_init_supervision_api(); /*************************************************************************************/ @@ -291,110 +289,14 @@ static void discovered_cb(void *closure, pid_t pid) } } -static int discover_supervised() +int afs_supervisor_discover() { int n = 0; afs_discover("afb-daemon", discovered_cb, &n); return n; } -/** - * initalize the supervision - */ -static int init(const char *spec) -{ - int rc, fd; - - /* check argument */ - if (!spec) { - ERROR("invalid socket spec"); - return -1; - } - - rc = afb_session_init(100, 600, ""); - /* TODO check that value */ - - /* create the apisets */ - main_apiset = afb_apiset_create(supervisor_apiname, 0); - if (!main_apiset) { - ERROR("Can't create supervisor's apiset"); - return -1; - } - empty_apiset = afb_apiset_create(supervision_apiname, 0); - if (!empty_apiset) { - ERROR("Can't create supervision apiset"); - return -1; - } - - - /* init the main apiset */ - rc = afb_init_supervision_api(); - if (rc < 0) { - ERROR("Can't create supervision's apiset: %m"); - return -1; - } - - /* create the supervision socket */ - fd = create_supervision_socket(supervision_socket_path); - if (fd < 0) - return fd; - - /* listen the socket */ - rc = listen(fd, 5); - if (rc < 0) { - ERROR("refused to listen on socket"); - return rc; - } - - /* integrate the socket to the loop */ - rc = sd_event_add_io(afb_systemd_get_event_loop(), - NULL, fd, EPOLLIN, - listening, NULL); - if (rc < 0) { - ERROR("handling socket event isn't possible"); - return rc; - } - - /* adds the server socket */ - rc = afb_api_ws_add_server(spec, main_apiset); - if (rc < 0) { - ERROR("can't start the server socket"); - return -1; - } - return 0; -} - -/* start should not be null but */ -static void start(int signum, void *arg) -{ - char *xpath = arg; - int rc; - - if (signum) - exit(1); - - rc = init(xpath); - if (rc) - exit(1); - - sd_notify(1, "READY=1"); - - discover_supervised(); -} - -/** - * initalize the supervision - */ -int main(int ac, char **av) -{ - verbosity = Verbosity_Level_Debug; - /* enter job processing */ - jobs_start(3, 0, 10, start, av[1]); - WARNING("hoops returned from jobs_enter! [report bug]"); - return 1; -} - -/*********************************************************************************************************/ +/*************************************************************************************/ static struct afb_binding_data_v2 datav2; @@ -425,7 +327,7 @@ static void f_list(struct afb_req req) static void f_discover(struct afb_req req) { - discover_supervised(); + afs_supervisor_discover(); afb_req_success(req, NULL, NULL); } @@ -501,7 +403,49 @@ static void f_debug_break(struct afb_req req) propagate(req, "break"); } -static const struct afb_auth _afb_auths_v2_supervision[] = { +/*************************************************************************************/ + +/** + * initalize the supervisor + */ +static int init_supervisor() +{ + int rc, fd; + + /* create an empty set for superviseds */ + empty_apiset = afb_apiset_create(supervision_apiname, 0); + if (!empty_apiset) { + ERROR("Can't create supervision apiset"); + return -1; + } + + /* create the supervision socket */ + fd = create_supervision_socket(supervision_socket_path); + if (fd < 0) + return fd; + + /* listen the socket */ + rc = listen(fd, 5); + if (rc < 0) { + ERROR("refused to listen on socket"); + return rc; + } + + /* integrate the socket to the loop */ + rc = sd_event_add_io(afb_systemd_get_event_loop(), + NULL, fd, EPOLLIN, + listening, NULL); + if (rc < 0) { + ERROR("handling socket event isn't possible"); + return rc; + } + + return 0; +} + +/*************************************************************************************/ + +static const struct afb_auth _afb_auths_v2_supervisor[] = { /* 0 */ { .type = afb_auth_Permission, @@ -509,93 +453,93 @@ static const struct afb_auth _afb_auths_v2_supervision[] = { } }; -static const struct afb_verb_v2 _afb_verbs_v2_supervision[] = { +static const struct afb_verb_v2 _afb_verbs_v2_supervisor[] = { { .verb = "list", .callback = f_list, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "config", .callback = f_config, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "do", .callback = f_do, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "trace", .callback = f_trace, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "sessions", .callback = f_sessions, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "session-close", .callback = f_session_close, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "exit", .callback = f_exit, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "debug-wait", .callback = f_debug_wait, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "debug-break", .callback = f_debug_break, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = "discover", .callback = f_discover, - .auth = &_afb_auths_v2_supervision[0], + .auth = &_afb_auths_v2_supervisor[0], .info = NULL, .session = AFB_SESSION_NONE_V2 }, { .verb = NULL } }; -static const struct afb_binding_v2 _afb_binding_v2_supervision = { +static const struct afb_binding_v2 _afb_binding_v2_supervisor = { .api = supervisor_apiname, .specification = NULL, .info = NULL, - .verbs = _afb_verbs_v2_supervision, + .verbs = _afb_verbs_v2_supervisor, .preinit = NULL, - .init = NULL, + .init = init_supervisor, .onevent = NULL, .noconcurrency = 0 }; -static int afb_init_supervision_api() +int afs_supervisor_add(struct afb_apiset *apiset) { - return afb_api_so_v2_add_binding(&_afb_binding_v2_supervision, NULL, main_apiset, &datav2); + return afb_api_so_v2_add_binding(&_afb_binding_v2_supervisor, NULL, apiset, &datav2); } diff --git a/src/afs-supervisor.h b/src/afs-supervisor.h new file mode 100644 index 00000000..aeae6c72 --- /dev/null +++ b/src/afs-supervisor.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author: José Bollo + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-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. + */ + +#pragma once + + +extern int afs_supervisor_discover(); +extern int afs_supervisor_add(struct afb_apiset *apiset); + -- 2.16.6