Fixed Session Context Free with ctxFreeCB
authorFulup Ar Foll <fulup@iot.bzh>
Sun, 13 Dec 2015 09:21:46 +0000 (10:21 +0100)
committerFulup Ar Foll <fulup@iot.bzh>
Sun, 13 Dec 2015 09:21:46 +0000 (10:21 +0100)
include/local-def.h
include/proto-def.h
src/afbs-api.c
src/alsa-api.c
src/dbus-api.c
src/radio-api.c
src/rest-api.c
src/session.c

index b37cd75..2f8fd20 100644 (file)
@@ -169,26 +169,37 @@ typedef struct {
   AFB_privateApi *private;
 } AFB_restapi;
 
+// Plugin definition
+typedef struct {
+  AFB_pluginT type;  
+  char *info;
+  char *prefix;
+  size_t prefixlen;
+  json_object *jtype;
+  AFB_restapi *apis;
+  void *handle;
+  int  ctxCount;
+  AFB_apiCB freeCtxCB;  // callback to free application context [null for standard free]
+} AFB_plugin;
+
 
 // User Client Session Context
 typedef struct {
-  int  cid;         // index 0 if global
-  char uuid[37];    // long term authentication of remote client
-  char token[37];   // short term authentication of remote client
-  time_t timeStamp; // last time token was refresh
-  int   restfull;   // client does not use cookie
-  void *handle;     // application specific context
-  AFB_apiCB freeHandleCB;  // callback to free application handle [null for standard free]
+  int  cid;             // index 0 if global
+  char uuid[37];        // long term authentication of remote client
+  char token[37];       // short term authentication of remote client
+  time_t timeStamp;     // last time token was refresh
+  int   restfull;       // client does not use cookie
+  void *ctx;            // application specific context
+  AFB_plugin *plugin;   // provide callback and easy access to plugin
 } AFB_clientCtx;
 
-
 // MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "value");
 typedef struct {
   const char *url;
   char *plugin;
   char *api;
   char *post;
-  int  loa;
   json_object *jresp;
   AFB_clientCtx *client;      // needed because libmicrohttp cannot create an empty response
   int   restfull;             // request is resfull [uuid token provided]
@@ -199,19 +210,6 @@ typedef struct {
 } AFB_request;
 
 
-// Plugin definition
-typedef struct {
-  AFB_pluginT type;  
-  char *info;
-  char *prefix;
-  size_t prefixlen;
-  json_object *jtype;
-  AFB_restapi *apis;
-  void *handle;
-  int  ctxCount;
-} AFB_plugin;
-
-
 typedef struct {
   AFB_config  *config;   // pointer to current config
   // List of commands to execute
index b6cdb94..55585e7 100644 (file)
@@ -22,7 +22,7 @@
 
 // Rest-api
 
-PUBLIC json_object* apiPingTest(AFB_request *request, void *pluginHandle);
+PUBLIC json_object* apiPingTest(AFB_request *request);
 PUBLIC const char* getQueryValue (AFB_request * request, char *name);
 PUBLIC int getQueryAll(AFB_request * request, char *query, size_t len);
 
@@ -48,7 +48,7 @@ PUBLIC AFB_error ctxTokenRefresh (AFB_request *request);
 PUBLIC AFB_error ctxTokenCreate (AFB_request *request);
 PUBLIC AFB_error ctxTokenCheck (AFB_request *request);
 PUBLIC AFB_error ctxTokenReset (AFB_request *request);
-PUBLIC AFB_error ctxClientGet (AFB_request *request);
+PUBLIC AFB_error ctxClientGet (AFB_request *request, AFB_plugin *plugin);
 
 
 
index 44fa033..344377b 100644 (file)
@@ -34,7 +34,7 @@ STATIC json_object* clientContextCreate (AFB_request *request) {
     AFB_clientCtx *client=request->client; // get client context from request
    
     // check we do not already have a session
-    if ((client != NULL) && (client->handle != NULL)) {
+    if ((client != NULL) && (client->ctx != NULL)) {
         request->errcode=MHD_HTTP_FORBIDDEN;
         return (jsonNewMessage(AFB_FAIL, "Token exist use refresh"));
     }
@@ -53,8 +53,8 @@ STATIC json_object* clientContextCreate (AFB_request *request) {
         return (jresp);
     }
    
-    // add a client handle to session
-    client->handle = malloc (sizeof (MyClientApplicationHandle));
+    // add a client context to session
+    client->ctx = malloc (sizeof (MyClientApplicationHandle));
     
     // Send response to UI
     jresp = json_object_new_object();               
@@ -112,6 +112,12 @@ STATIC json_object* clientContextReset (AFB_request *request) {
     return (jresp); 
 }
 
+// This function is call when Client Session Context is removed
+// Note: when freeCtxCB==NULL standard free/malloc is called
+STATIC void clientContextFree(AFB_clientCtx *client) {
+    fprintf (stderr,"Plugin[%s] Closing Session uuid=[%s]\n", client->plugin->prefix, client->uuid);
+    free (client->ctx);
+}
 
 STATIC  AFB_restapi pluginApis[]= {
   {"ping"          , (AFB_apiCB)apiPingTest         ,"Ping Rest Test Service"},
@@ -129,6 +135,7 @@ PUBLIC AFB_plugin *afsvRegister () {
     plugin->prefix= "afbs";  // url base
     plugin->apis  = pluginApis;
     plugin->handle= (void*) "What ever you want";
+    plugin->freeCtxCB= (void*) clientContextFree;
     
     return (plugin);
 };
\ No newline at end of file
index 61c7953..23964a6 100644 (file)
@@ -27,7 +27,7 @@ STATIC json_object* wrongApi (AFB_request *request, void* handle) {
     impossible=bug/zero;
 }
 
-STATIC json_object* pingSample (AFB_request *request, void* handle) {
+STATIC json_object* pingSample (AFB_request *request) {
     static pingcount = 0;
     json_object *response;
     char query [512];
@@ -39,7 +39,8 @@ STATIC json_object* pingSample (AFB_request *request, void* handle) {
     if (request->post == NULL)  request->post="NoData";  
         
     // return response to caller
-    response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon %d query={%s} handle=[%s] PostData: \'%s\' ", pingcount++, query, handle, request->post);
+    response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon %d query={%s} handle=[%s] PostData: \'%s\' " 
+                             , pingcount++, query, request->post);
     
     if (verbose) fprintf(stderr, "%d: \n", pingcount);
     return (response);
@@ -65,6 +66,5 @@ PUBLIC AFB_plugin *alsaRegister () {
     plugin->info  = "Application Framework Binder Service";
     plugin->prefix= "alsa";        
     plugin->apis  = pluginApis;
-    plugin->handle= "bla bla bla";
     return (plugin);
 };
\ No newline at end of file
index d7097fc..f7b071b 100644 (file)
@@ -57,7 +57,7 @@ STATIC json_object* pingBug (AFB_request *request) {
 
 
 // For samples https://linuxprograms.wordpress.com/2010/05/20/json-c-libjson-tutorial/
-STATIC json_object* pingJson (AFB_session *session, AFB_request *request, void* handle) {
+STATIC json_object* pingJson (AFB_session *session, AFB_request *request) {
     json_object *jresp, *embed;    
     
     jresp = json_object_new_object();
@@ -91,6 +91,5 @@ PUBLIC AFB_plugin *dbusRegister () {
     plugin->info  = "Application Framework Binder Service";
     plugin->prefix= "dbus";        
     plugin->apis  = pluginApis;
-    plugin->handle= (void*) "Any you Want";        
     return (plugin);
 };
\ No newline at end of file
index eb040a1..35cab38 100644 (file)
@@ -554,7 +554,7 @@ STATIC AFB_error releaseRadio (pluginHandleT* handle, AFB_clientCtx *client) {
    handle->radios[client->idx].used = FALSE;
    
    // stop related threads and free attached resources
-   radio_stop (client->radio);
+   radio_stop (&client->radio);
    
    // May be some further cleanup ????
    
@@ -581,7 +581,7 @@ STATIC clientHandleT  *reserveRadio (pluginHandleT* handle) {
    client = calloc (1, sizeof (clientHandleT));
    
    // stop related threads and free attached resources
-   radio_start (client->radio);
+   radio_start (&client->radio);
    
    // May be some things to do ????
    
@@ -597,10 +597,10 @@ STATIC freeRadio (clientHandleT *client) {
 }
 
 
-STATIC json_object* powerOnOff (AFB_session *session, AFB_request *request, void* handle) {
+STATIC json_object* powerOnOff (AFB_session *session, AFB_request *request) {
     json_object *jresp;
-    dev_ctx *dev_ctx = (dev_ctx *)handle;
     AFB_clientCtx *client=request->client; // get client context from request
+    dev_ctx *dev_ctx = (dev_ctx *)client->ctx;
    
     // Make sure binder was started with client session
     if ((client != NULL) {
@@ -655,7 +655,7 @@ PUBLIC AFB_plugin *radioRegister (AFB_session *session) {
     plugin->apis  = pluginApis;
     
     plugin->handle = initRadioPlugin();
-    plugin->freeHandleCB = freeRadio();
+    plugin->freeCtxCB = freeRadio();
 
     return (plugin);
 };
index 83bb2d2..62b782d 100644 (file)
@@ -37,22 +37,29 @@ static json_object     *afbJsonType;
 
 
 // Sample Generic Ping Debug API
-PUBLIC json_object* apiPingTest(AFB_request *request, void *pluginHandle) {
+PUBLIC json_object* apiPingTest(AFB_request *request) {
     static pingcount = 0;
     json_object *response;
-    char query [512];
-    int len;
+    char query  [256];
+    char session[256];
 
+    int len;
+    AFB_clientCtx *client=request->client; // get client context from request
+    
     // request all query key/value
     len = getQueryAll (request, query, sizeof(query));
-    if (len == 0) strcpy (query,"NoSearchQueryList");
+    if (len == 0) strncpy (query, "NoSearchQueryList", sizeof(query));
     
     // check if we have some post data
-    if (request->post == NULL)  request->post="NoData";  
+    if (request->post == NULL)  request->post="NoData"; 
+    
+    // check is we have a session and a plugin handle
+    if (client == NULL) strcpy (session,"NoSession");       
+    else snprintf(session, sizeof(session),"uuid=%s token=%s ctx=0x%x handle=0x%x", client->uuid, client->token, client->ctx, client->ctx); 
         
     // return response to caller
-    response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon count=%d CtxtId=%d Loa=%d query={%s} Handle=0x%x PostData: \'%s\' "
-               , pingcount++, request->client->cid, request->loa, query, request->post, pluginHandle);
+    response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon count=%d CtxtId=%d query={%s} session={%s} PostData: [%s] "
+               , pingcount++, request->client->cid, query, session, request->post);
     return (response);
 }
 
@@ -151,7 +158,7 @@ STATIC AFB_error callPluginApi(AFB_plugin *plugin, AFB_request *request) {
                 }
                 
                 // add client context to request
-                ctxClientGet(request);      
+                ctxClientGet(request, plugin);      
                 
                 // Effectively call the API with a subset of the context
                 jresp = plugin->apis[idx].callback(request, plugin->handle);
index 56620f3..45005ab 100644 (file)
@@ -332,14 +332,14 @@ STATIC int ctxUuidCompCB (const void *k1, const void *k2) {
 
 // Free context [XXXX Should be protected again memory abort XXXX]
 STATIC void ctxUuidFreeCB (struct lh_entry *entry) {
-    AFB_clientCtx *ctx = (AFB_clientCtx*) entry->v;
+    AFB_clientCtx *client = (AFB_clientCtx*) entry->v;
 
     // If application add a handle let's free it now
-    if (ctx->handle != NULL) {
+    if (client->ctx != NULL) {
         
         // Free client handle with a standard Free function, with app callback or ignore it
-        if (ctx->freeHandleCB == NULL) free (ctx->handle); 
-        else if (ctx->freeHandleCB != (void*)-1) ctx->freeHandleCB(ctx->handle); 
+        if (client->plugin->freeCtxCB == NULL) free (client->ctx); 
+        else if (client->plugin->freeCtxCB != (void*)-1) client->plugin->freeCtxCB(client); 
     }
     free ((void*)entry->v);
 }
@@ -379,7 +379,7 @@ PUBLIC int ctxStoreGarbage (struct lh_table *lht, const int timeout) {
 }
 
 // This function will return exiting client context or newly created client context
-PUBLIC AFB_error ctxClientGet (AFB_request *request) {
+PUBLIC AFB_error ctxClientGet (AFB_request *request, AFB_plugin *plugin) {
   static int cid=0;
   AFB_clientCtx *clientCtx=NULL;
   const char *uuid;
@@ -420,7 +420,8 @@ PUBLIC AFB_error ctxClientGet (AFB_request *request) {
     if (clientCtx == NULL) clientCtx = calloc(1, sizeof(AFB_clientCtx)); // init NULL clientContext
     uuid_generate(newuuid);         // create a new UUID
     uuid_unparse_lower(newuuid, clientCtx->uuid);
-    clientCtx->cid=cid++;
+    clientCtx->cid=cid++;   // simple application uniqueID 
+    clientCtx->plugin = plugin;    // provide plugin callbacks a hook to plugin
         
     // if table is full at 50% let's clean it up
     if(clientCtxs->count > (clientCtxs->size*0.5)) ctxStoreGarbage(clientCtxs, request->config->cntxTimeout);