aboutsummaryrefslogtreecommitdiffstats
path: root/hook-plugin
diff options
context:
space:
mode:
Diffstat (limited to 'hook-plugin')
-rw-r--r--hook-plugin/PolicyHookCb.c98
-rw-r--r--hook-plugin/README.md14
2 files changed, 51 insertions, 61 deletions
diff --git a/hook-plugin/PolicyHookCb.c b/hook-plugin/PolicyHookCb.c
index fdec61d..b751ed6 100644
--- a/hook-plugin/PolicyHookCb.c
+++ b/hook-plugin/PolicyHookCb.c
@@ -39,6 +39,8 @@
#include "afb/afb-wsj1.h"
#include "afb/afb-ws-client.h"
+#include "afb/afb-proto-ws.h"
+
#include <pthread.h>
#include <semaphore.h>
@@ -63,14 +65,14 @@
// Currently not implemented
#define UNUSED_ARG(x) UNUSED_ ## x __attribute__((__unused__))
-void OnRequestCB(void* UNUSED_ARG(handle) , const char* UNUSED_ARG(api), const char* UNUSED_ARG(verb), struct afb_wsj1_msg*UNUSED_ARG(msg)) {}
+static void OnSuccessCB(void* UNUSED_ARG(handle) , void* UNUSED_ARG(request), struct json_object* UNUSED_ARG(reslt), const char* UNUSED_ARG(info)) {}
+static void OnFailureCB(void* UNUSED_ARG(closure), void* UNUSED_ARG(request), const char *UNUSED_ARG(status), const char *UNUSED_ARG(info)) {}
typedef struct {
- const char *api;
const char *openVerb;
const char *closeVerb;
+ json_object *queryJ;
long timeout;
- char *query;
size_t length;
sd_event_source *evtSource;
@@ -86,7 +88,7 @@ typedef struct {
typedef struct {
snd_pcm_t *pcm;
const char *uri;
- struct afb_wsj1 *wsj1;
+ struct afb_proto_ws *pws;
sd_event *sdLoop;
int verbose;
sem_t semaphore;
@@ -97,7 +99,6 @@ typedef struct {
} afbClientT;
-
static void *LoopInThread(void *handle) {
afbClientT *afbClient = (afbClientT*) handle;
int count=0;
@@ -114,7 +115,7 @@ static void *LoopInThread(void *handle) {
}
// lost connect with the AudioDaemon
-static void OnHangupCB(void *handle, struct afb_wsj1 *wsj1) {
+static void OnHangupCB(void *handle) {
afbClientT *afbClient = (afbClientT*) handle;
SNDERR("(Hoops) Lost Connection to %s", afbClient->uri);
@@ -129,15 +130,13 @@ typedef enum {
HOOK_CLOSE,
} hookActionT;
-
-void OnEventCB(void *handle, const char *event, struct afb_wsj1_msg *msg) {
+void OnEventCB(void *handle, const char *event, int evtid, struct json_object *eventJ) {
afbClientT *afbClient = (afbClientT*) handle;
afbEventT **afbEvent = afbClient->event;
- json_object *eventJ, *tmpJ, *dataJ;
+ json_object *dataJ, *tmpJ;
const char *label;
int value, done, index;
- eventJ = afb_wsj1_msg_object_j(msg);
done= json_object_object_get_ex(eventJ,"data", &dataJ);
if (!done) {
SNDERR ("PCM_HOOK: uri=%s empty event label", afbClient->uri);
@@ -166,15 +165,22 @@ void OnEventCB(void *handle, const char *event, struct afb_wsj1_msg *msg) {
return;
OnErrorExit:
- SNDERR("ON-EVENT %s(%s)\n", event, afb_wsj1_msg_object_s(msg));
+ SNDERR("ON-EVENT %s(%s)\n", event, json_object_get_string(dataJ));
return;
}
-// callback interface for wsj1
-static struct afb_wsj1_itf itf = {
- .on_hangup = OnHangupCB,
- .on_call = OnRequestCB,
- .on_event = OnEventCB
+
+/* the callback interface for pws */
+static struct afb_proto_ws_client_itf itf = {
+ .on_reply_success = OnSuccessCB,
+ .on_reply_fail = OnFailureCB,
+ .on_event_create = NULL,
+ .on_event_remove = NULL,
+ .on_event_subscribe = NULL,
+ .on_event_unsubscribe = NULL,
+ .on_event_push = OnEventCB,
+ .on_event_broadcast = NULL,
+ .on_subcall = NULL,
};
void OnResponseCB(void *handle, struct afb_wsj1_msg *msg) {
@@ -222,7 +228,7 @@ static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int c
int err;
// create a unique tag for request
- (void) asprintf(&afbRequest->callIdTag, "%d:%s/%s", count, afbRequest->api, afbRequest->openVerb);
+ (void) asprintf(&afbRequest->callIdTag, "%d:%s", count, afbRequest->openVerb);
// create a timer with ~250us accuracy
sd_event_now(afbClient->sdLoop, CLOCK_MONOTONIC, &usec);
@@ -235,9 +241,9 @@ static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int c
// release action is optional
if (apiVerb) {
- if (afbClient->verbose) printf("CALL-REQUEST api=%s/%s tag=%s\n", afbRequest->api, apiVerb, afbRequest->callIdTag);
- err = afb_wsj1_call_s(afbClient->wsj1, afbRequest->api, apiVerb, afbRequest->query, OnResponseCB, afbRequest);
- if (err) goto OnErrorExit;
+ if (afbClient->verbose) printf("CALL-REQUEST verb=%s tag=%s\n", apiVerb, afbRequest->callIdTag);
+ err = afb_proto_ws_client_call(afbClient->pws, apiVerb, afbRequest->queryJ, "xxxx", afbRequest);
+ if (err < 0 ) goto OnErrorExit;
}
// save client handle in request
afbRequest->afbClient = afbClient;
@@ -246,7 +252,7 @@ static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int c
return 0;
OnErrorExit:
- fprintf(stderr, "LaunchCallRequest: Fail call %s//%s/%s&%s", afbClient->uri, afbRequest->api, apiVerb, afbRequest->query);
+ fprintf(stderr, "LaunchCallRequest: Fail call %s//%s&%s", afbClient->uri, apiVerb, json_object_get_string(afbRequest->queryJ));
return 1;
}
@@ -272,13 +278,15 @@ static int LaunchCallRequest(afbClientT *afbClient, hookActionT action) {
// start a thread with a mainloop to monitor Audio-Agent
err = pthread_create(&tid, NULL, &LoopInThread, afbClient);
if (err) goto OnErrorExit;
-
- // connect the websocket wsj1 to the uri given by the first argument
- afbClient->wsj1 = afb_ws_client_connect_wsj1(afbClient->sdLoop, afbClient->uri, &itf, afbClient);
- if (afbClient->wsj1 == NULL) {
+
+ afbClient->pws = afb_ws_client_connect_api(afbClient->sdLoop, afbClient->uri, &itf, afbClient);
+ if (afbClient->pws == NULL) {
fprintf(stderr, "LaunchCallRequest: Connection to %s failed\n", afbClient->uri);
goto OnErrorExit;
- }
+ }
+
+ // register hanghup callback
+ afb_proto_ws_on_hangup(afbClient->pws, OnHangupCB);
}
// send call request to audio-agent asynchronously (respond with thread mainloop context)
@@ -345,7 +353,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) {
if (snd_config_get_id(node, &id) < 0) continue;
if (strcmp(id, "comment") == 0 || strcmp(id, "hint") == 0) continue;
- if (strcmp(id, "uri") == 0) {
+ if (strcmp(id, "ws-client") == 0) {
const char *uri;
if (snd_config_get_string(node, &uri) < 0) {
SNDERR("Invalid String for %s", id);
@@ -377,8 +385,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) {
SNDERR("Invalid compound type for %s", callConf);
goto OnErrorExit;
}
-
-
+
// loop on each call
snd_config_for_each(currentCall, follow, node) {
snd_config_t *ctlconfig = snd_config_iterator_entry(currentCall);
@@ -397,17 +404,6 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) {
// allocate an empty call request
afbRequest[callCount] = calloc(1, sizeof (afbRequestT));
-
- err = snd_config_search(ctlconfig, "api", &itemConf);
- if (!err) {
- const char *api;
- if (snd_config_get_string(itemConf, &api) < 0) {
- SNDERR("Invalid api string for %s", callLabel);
- goto OnErrorExit;
- }
- afbRequest[callCount]->api=strdup(api);
- }
-
err = snd_config_search(ctlconfig, "request", &itemConf);
if (!err) {
const char *verb;
@@ -438,33 +434,27 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) {
err = snd_config_search(ctlconfig, "args", &itemConf);
if (!err) {
- const char *query;
- if (snd_config_get_string(itemConf, &query) < 0) {
+ char *query;
+ if (snd_config_get_string(itemConf, (const char**) &query) < 0) {
SNDERR("Invalid args string %s", id);
goto OnErrorExit;
}
- // reserve enough space to ad closing message
- afbRequest[callCount]->length= strlen(query);
- afbRequest[callCount]->query = malloc (afbRequest[callCount]->length+strlen(CLOSING_MSG)+1);
- strcpy (afbRequest[callCount]->query, query);
// cleanup string for json_tokener
for (int idx = 0; query[idx] != '\0'; idx++) {
- if (query[idx] == '\'') afbRequest[callCount]->query[idx] = '"';
- else afbRequest[callCount]->query[idx] = query[idx];
+ if (query[idx] == '\'') query[idx] = '"';
}
- json_object *queryJ = json_tokener_parse(afbRequest[callCount]->query);
- if (!queryJ) {
- SNDERR("Invalid Json %s args=%s should be args=\"{'tok1':'val1', 'tok2':'val2'}\" ", id, afbRequest[callCount]->query);
+ afbRequest[callCount]->queryJ = json_tokener_parse(query);
+ if (!afbRequest[callCount]->queryJ) {
+ SNDERR("Invalid Json %s args=%s should be args=\"{'tok1':'val1', 'tok2':'val2'}\" ", id, query);
goto OnErrorExit;
}
}
// Simple check on call request validity
- if (!afbRequest[callCount]->query) afbRequest[callCount]->query= "";
if (!afbRequest[callCount]->timeout) afbRequest[callCount]->timeout=REQUEST_DEFAULT_TIMEOUT ;
- if (!afbRequest[callCount]->openVerb || !afbRequest[callCount]->api) {
- SNDERR("Missing api/open(verb)/close(verb) %s in asoundrc", callLabel);
+ if (!afbRequest[callCount]->openVerb || !afbRequest[callCount]->closeVerb) {
+ SNDERR("Missing open(verb)/close(verb) %s in asoundrc", callLabel);
goto OnErrorExit;
}
diff --git a/hook-plugin/README.md b/hook-plugin/README.md
index 0472c7b..748f66f 100644
--- a/hook-plugin/README.md
+++ b/hook-plugin/README.md
@@ -6,8 +6,8 @@ Author: Fulup Ar Foll fulup@iot.bzh
Date : August-2017
Functionalities:
- - Execute a set of websocket RPC request again AGL binders to allow/deny access
- - Keep websocket open in an idepandant thread on order to monitor event receive from AGL audio agent
+ - Execute a set of unix/ws RPC request again AGL binders to allow/deny access
+ - Keep websocket open in an idependant thread in order to monitor event received from AGL audio agent
Installation
- Alsaplugins are typically search in /usr/share/alsa-lib. Nevertheless a full path might be given
@@ -41,12 +41,12 @@ pcm.MyNavigationHook {
# Every Call should return OK in order PCM to open (default timeout 100ms)
uri "ws://localhost:1234/api?token='audio-agent-token'"
+ ws-client="unix:/var/tmp/pol4a"
request {
# Request authorisation to write on navigation
navigation-ctl {
- api "pol4a"
request "navigation-role"
- release "navigation-role"
+ release "release-role"
args "{'uid':'alsa-hook-navigation'}"
}
# subscribe to Audio Agent Event map them to signal
@@ -69,9 +69,9 @@ pcm.MyNavigationHook {
NOTE:
-* Hook plugin is loaded by Alsa libasound within player context. It inherits client process attributes, as UID/GID or
-the SMACK label on AGL. This smack label is tested by AGL security framework when requested a call on the audio-agent binder.
-As a result the call will only succeed it the permission attached the application in Cynara matches.
+* Hook plugin is loaded by Alsa libasound within client context. It inherits client process attributes, as UID/GID and
+SMACK label when running on AGL. The smack label is control by AGL security framework.
+As a result a control request succeeds only when client application permission match requested audio role inside Cynara security database.
* Hook plugin keep a connection with the Audio-Agent until PCM is closed by the application. This connection allow the
Audio-Agent to send events. eg: pause, quit, mute, ... \ No newline at end of file