Remove Hashtable for session and cleanup
authorFulup Ar Foll <fulup@iot.bzh>
Wed, 16 Dec 2015 23:41:53 +0000 (00:41 +0100)
committerFulup Ar Foll <fulup@iot.bzh>
Wed, 16 Dec 2015 23:41:53 +0000 (00:41 +0100)
plugins/samples/SamplePost.c
plugins/session/token-api.c
src/rest-api.c
src/session.c

index 9e1c766..c4b9bc2 100644 (file)
 
 #include "local-def.h"
 
-// Dummy sample of Client Application Context
-typedef struct {
-  int  something;       
-  void *whateveryouwant;
-} MyClientApplicationHandle;
-
-
-// Request Creation of new context if it does not exist
-STATIC json_object* clientContextCreate (AFB_request *request) {
-    json_object *jresp;
-
-    // add an application specific client context to session
-    request->client->ctx = malloc (sizeof (MyClientApplicationHandle));
-    
-    // Send response to UI
-    jresp = json_object_new_object();               
-    json_object_object_add(jresp, "token", json_object_new_string ("A New Token and Session Context Was Created"));
-
-    return (jresp);
-}
-
-// Before entering here token will be check and renew
-STATIC json_object* clientContextRefresh (AFB_request *request) {
-    json_object *jresp;
-
-  
-    jresp = json_object_new_object();
-    json_object_object_add(jresp, "token", json_object_new_string ("Token was refreshed"));              
-    
-    return (jresp);
-}
-
-
-// Session token will we verified before entering here
-STATIC json_object* clientContextCheck (AFB_request *request) {
-    
-    json_object *jresp = json_object_new_object();    
-    json_object_object_add(jresp, "isvalid", json_object_new_boolean (TRUE));       
-        
-    return (jresp); 
-}
-
-
-// Close and Free context
-STATIC json_object* clientContextReset (AFB_request *request) {
-    json_object *jresp;
-   
-    jresp = json_object_new_object();
-    json_object_object_add(jresp, "uuid", json_object_new_string (request->client->uuid));              
-    
-    return (jresp); 
-}
 
 // In this case or handle is quite basic
 typedef struct {
@@ -172,12 +120,8 @@ STATIC void clientContextFree(AFB_clientCtx *client) {
 }
 
 STATIC  AFB_restapi pluginApis[]= {
-  {"ping"          , AFB_SESSION_NONE  , (AFB_apiCB)apiPingTest         ,"Ping Rest Test Service"},
-  {"token-create"  , AFB_SESSION_CREATE, (AFB_apiCB)clientContextCreate ,"Request Client Context Creation"},
-  {"token-refresh" , AFB_SESSION_RENEW , (AFB_apiCB)clientContextRefresh,"Refresh Client Context Token"},
-  {"token-check"   , AFB_SESSION_CHECK , (AFB_apiCB)clientContextCheck  ,"Check Client Context Token"},
-  {"token-reset"   , AFB_SESSION_CLOSE , (AFB_apiCB)clientContextReset  ,"Close Client Context and Free resources"},
-  {"file-upload"   , AFB_SESSION_NONE  , (AFB_apiCB)ProcessPostForm     ,"Demo for file upload"},
+  {"ping"   , AFB_SESSION_NONE  , (AFB_apiCB)apiPingTest         ,"Ping Rest Test Service"},
+  {"upload" , AFB_SESSION_NONE  , (AFB_apiCB)ProcessPostForm     ,"Demo for file upload"},
   {NULL}
 };
 
@@ -185,7 +129,7 @@ PUBLIC AFB_plugin *afsvRegister () {
     AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
     plugin->type  = AFB_PLUGIN_JSON; 
     plugin->info  = "Application Framework Binder Service";
-    plugin->prefix= "afbs";  // url base
+    plugin->prefix= "post";  // url base
     plugin->apis  = pluginApis;
     plugin->handle= (void*) "What ever you want";
     plugin->freeCtxCB= (void*) clientContextFree;
index 3b49d2e..b6ebb8a 100644 (file)
@@ -77,92 +77,6 @@ typedef struct {
    int fd; 
 } appPostCtx;
 
-// This function is call when PostForm processing is completed
-STATIC void DonePostForm (AFB_request *request) {
-    AFB_PostHandle  *postHandle = (AFB_PostHandle*)request->post->data;
-    appPostCtx *appCtx= postHandle->ctx;
-    
-    // Close upload file ID
-    close (appCtx->fd);
-
-    // Free application specific handle
-    free (postHandle->ctx);
-    
-    if (verbose) fprintf (stderr, "DonePostForm upload done\n");
-}
-
-
-// WARNING: PostForm callback are call multiple time (one or each key within form)
-// When processing POST_JSON request->data hold a PostHandle and not data directly as for POST_JSON
-STATIC json_object* ProcessPostForm (AFB_request *request, AFB_PostItem *item) {
-
-    AFB_PostHandle  *postHandle;
-    appPostCtx *appCtx;
-    char filepath[512];
-            
-    // When Post is fully processed the same callback is call with a item==NULL
-    if (item == NULL) {
-        // Close file, Free handle
-        
-        request->errcode = MHD_HTTP_OK;
-        return(jsonNewMessage(AFB_SUCCESS,"File [%s] uploaded at [%s] error=\n", item->filename, request->config->sessiondir));  
-    }
-    
-    // Let's make sure this is a valid PostForm request
-    if (!request->post && request->post->type != AFB_POST_FORM) {
-        request->errcode = MHD_HTTP_FORBIDDEN;
-        return(jsonNewMessage(AFB_FAIL,"This is not a valid PostForm request\n"));          
-    } else {
-        // In AFB_POST_FORM case post->data is a PostForm handle
-        postHandle = (AFB_PostHandle*) request->post->data;
-        appCtx = (appPostCtx*) postHandle->ctx;
-    }
-
-    // Check this is a file element
-    if (0 != strcmp (item->key, "file")) {
-        request->errcode = MHD_HTTP_FORBIDDEN;
-        return (jsonNewMessage(AFB_FAIL,"No File within element key=%s\n", item->key));
-    }
-
-    // This is the 1st Item iteration let's open output file and allocate necessary resources
-    if (postHandle->ctx == NULL)  {
-        int fd;
-        
-        strncpy (filepath, request->config->sessiondir, sizeof(filepath));
-        strncat (filepath, "/", sizeof(filepath));
-        strncat (filepath, item->filename, sizeof(filepath));  
-
-        if((fd = open(request->config->sessiondir, O_RDONLY)) < 0) {
-            request->errcode = MHD_HTTP_FORBIDDEN;
-            return (jsonNewMessage(AFB_FAIL,"Fail to Upload file [%s] at [%s] error=\n", item->filename, request->config->sessiondir, strerror(errno)));
-        };            
-
-        // Create an application specific context
-        appCtx = malloc (sizeof(appPostCtx)); // May place anything here until post->completeCB handle resources liberation
-        appCtx->fd = fd;
-        
-        // attach application to postHandle
-        postHandle->ctx = (void*) appCtx;   // May place anything here until post->completeCB handle resources liberation        
-        postHandle->completeCB = (AFB_apiCB)DonePostForm; // CallBack when Form Processing is finished
-        
-    } else {
-        // this is not the call, FD is already open
-        appCtx = (appPostCtx*) postHandle->ctx;
-    }
-
-    // We have something to write
-    if (item->len > 0) {
-        
-        if (!write (appCtx->fd, item->data, item->len)) {
-            request->errcode = MHD_HTTP_FORBIDDEN;
-            return (jsonNewMessage(AFB_FAIL,"Fail to write file [%s] at [%s] error=\n", item->filename, strerror(errno)));
-        }
-    }
-  
-    // every event should return Sucess or Form processing stop
-    request->errcode = MHD_HTTP_OK;
-    return NULL;
-}
 
 // This function is call when Client Session Context is removed
 // Note: when freeCtxCB==NULL standard free/malloc is called
@@ -172,12 +86,11 @@ STATIC void clientContextFree(AFB_clientCtx *client) {
 }
 
 STATIC  AFB_restapi pluginApis[]= {
-  {"ping"          , AFB_SESSION_NONE  , (AFB_apiCB)apiPingTest         ,"Ping Rest Test Service"},
+  {"ping"    , AFB_SESSION_NONE  , (AFB_apiCB)apiPingTest         ,"Ping Rest Test Service"},
   {"create"  , AFB_SESSION_CREATE, (AFB_apiCB)clientContextCreate ,"Request Client Context Creation"},
   {"refresh" , AFB_SESSION_RENEW , (AFB_apiCB)clientContextRefresh,"Refresh Client Context Token"},
   {"check"   , AFB_SESSION_CHECK , (AFB_apiCB)clientContextCheck  ,"Check Client Context Token"},
   {"reset"   , AFB_SESSION_CLOSE , (AFB_apiCB)clientContextReset  ,"Close Client Context and Free resources"},
-  {"file-upload"   , AFB_SESSION_NONE  , (AFB_apiCB)ProcessPostForm     ,"Demo for file upload"},
   {NULL}
 };
 
index c7f4b03..c8a5029 100644 (file)
@@ -95,7 +95,7 @@ PUBLIC int getQueryAll(AFB_request * request, char *buffer, size_t len) {
 PUBLIC void endPostRequest(AFB_PostHandle *postHandle) {
 
     if (postHandle->type == AFB_POST_JSON) {
-        if (verbose) fprintf(stderr, "End PostJson Request UID=%d\n", postHandle->uid);
+        // if (verbose) fprintf(stderr, "End PostJson Request UID=%d\n", postHandle->uid);
     }
 
     if (postHandle->type == AFB_POST_FORM) {
@@ -178,7 +178,13 @@ STATIC AFB_error callPluginApi(AFB_plugin *plugin, AFB_request *request, void *c
                 if (AFB_SESSION_NONE != plugin->apis[idx].session) {
                     
                     // add client context to request
-                    ctxClientGet(request, plugin);
+                    if (ctxClientGet(request, plugin) != AFB_SUCCESS) {
+                        request->errcode=MHD_HTTP_INSUFFICIENT_STORAGE;
+                        json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+                        json_object_object_add(jcall, "info", json_object_new_string ("Client Session Context Full !!!"));
+                        json_object_object_add(request->jresp, "request", jcall);
+                        return (AFB_DONE);                              
+                    };
                     
                     if (verbose) fprintf(stderr, "Plugin=[%s] Api=[%s] Middleware=[%d] Client=[0x%x] Uuid=[%s] Token=[%s]\n"
                            , request->plugin, request->api, plugin->apis[idx].session, request->client, request->client->uuid, request->client->token);                        
@@ -428,6 +434,12 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
             
             // Let make sure we have the right encoding and a valid length
             encoding = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_TYPE);
+            
+            // We are facing an empty post let's process it as a get
+            if (encoding == NULL) {
+                request= createRequest (connection, session, url);
+                goto ProcessApiCall;
+            }
         
             // Form post is handle through a PostProcessor and call API once per form key
             if (strcasestr(encoding, FORM_CONTENT) != NULL) {
@@ -467,7 +479,7 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
                 postHandle->type = AFB_POST_JSON;
                 postHandle->private = malloc(contentlen + 1); // allocate memory for full POST data + 1 for '\0' enf of string
 
-                if (verbose) fprintf(stderr, "Create PostJson[uid=%d] Size=%d\n", postHandle->uid, contentlen);
+                // if (verbose) fprintf(stderr, "Create PostJson[uid=%d] Size=%d\n", postHandle->uid, contentlen);
                 return MHD_YES;
 
             } else {
@@ -490,7 +502,7 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
             
             // Process JsonPost request when buffer is completed let's call API    
             if (postHandle->type == AFB_POST_JSON) {
-                if (verbose) fprintf(stderr, "Updating PostJson[uid=%d]\n", postHandle->uid);
+                // if (verbose) fprintf(stderr, "Updating PostJson[uid=%d]\n", postHandle->uid);
 
                 memcpy(&postHandle->private[postHandle->len], upload_data, *upload_data_size);
                 postHandle->len = postHandle->len + *upload_data_size;
@@ -509,7 +521,7 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
 
             
             if (postHandle->type == AFB_POST_JSON) {
-                if (verbose) fprintf(stderr, "Processing PostJson[uid=%d]\n", postHandle->uid);
+                // if (verbose) fprintf(stderr, "Processing PostJson[uid=%d]\n", postHandle->uid);
 
                 param = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH);
                 if (param) sscanf(param, "%i", &contentlen);
@@ -526,18 +538,18 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
                 postRequest.type = postHandle->type;
                 request->post = &postRequest;
 
-                if (verbose) fprintf(stderr, "Close Post[%d] Buffer=%s\n", postHandle->uid, request->post->data);
+                // if (verbose) fprintf(stderr, "Close Post[%d] Buffer=%s\n", postHandle->uid, request->post->data);
             }
         }
     } else {
         // this is a get we only need a request
         request= createRequest (connection, session, url);
     };
-    
+
+ProcessApiCall:    
     // Request is ready let's call API without any extra handle
     status = findAndCallApi (request, NULL);
-    
-ExitOnResponse:
+
     serialized = json_object_to_json_string(request->jresp);
     webResponse = MHD_create_response_from_buffer(strlen(serialized), (void*) serialized, MHD_RESPMEM_MUST_COPY);
     
index 55098b4..4877acf 100644 (file)
@@ -16,8 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * 
  * Reference: 
- * https://github.com/json-c/json-c/blob/master/linkhash.c
- * https://github.com/json-c/json-c/blob/master/linkhash.h
+ * http://stackoverflow.com/questions/25971505/how-to-delete-element-from-hsearch
+ *
  */
 
 
 
 
 #define AFB_SESSION_JTYPE "AFB_session"
-#define AFB_SESSION_JLIST "AFB_sessions"
+#define AFB_SESSION_JLIST "AFB_sessions.hash"
 #define AFB_SESSION_JINFO "AFB_infos"
 
 
 #define AFB_CURRENT_SESSION "active-session"  // file link name within sndcard dir
 #define AFB_DEFAULT_SESSION "current-session" // should be in sync with UI
 
-static pthread_mutex_t mutexHash;             // declare a mutex to protect hash table
-static struct hsearch_data sessions = {0};    // Create an empty hash table for sessions
+// Session UUID are store in a simple array [for 10 sessions this should be enough]
+static struct {
+  pthread_mutex_t mutex;          // declare a mutex to protect hash table
+  AFB_clientCtx **store;          // sessions store
+  int count;                      // current number of sessions
+  int max;
+} sessions;
 
 // verify we can read/write in session dir
 PUBLIC AFB_error sessionCheckdir (AFB_session *session) {
@@ -67,7 +72,7 @@ PUBLIC AFB_error sessionCheckdir (AFB_session *session) {
    return AFB_SUCCESS;
 }
 
-// let's return only sessions files
+// let's return only sessions.hash files
 STATIC int fileSelect (const struct dirent *entry) {
    return (strstr (entry->d_name, ".afb") != NULL);
 }
@@ -105,7 +110,7 @@ PUBLIC json_object *sessionList (AFB_session *session, AFB_request *request) {
     struct dirent **namelist;
     int  count, sessionDir;
 
-    // if directory for card's sessions does not exist create it
+    // if directory for card's sessions.hash does not exist create it
     ajgResponse = checkCardDirExit (session, request);
     if (ajgResponse != NULL) return ajgResponse;
 
@@ -119,7 +124,7 @@ PUBLIC json_object *sessionList (AFB_session *session, AFB_request *request) {
     close (sessionDir);
 
     if (count < 0) {
-        return (jsonNewMessage (AFB_FAIL,"Fail to scan sessions directory [%s/%s] error=%s", session->config->sessiondir, request->plugin, strerror(sessionDir)));
+        return (jsonNewMessage (AFB_FAIL,"Fail to scan sessions.hash directory [%s/%s] error=%s", session->config->sessiondir, request->plugin, strerror(sessionDir)));
     }
     if (count == 0) return (jsonNewMessage (AFB_EMPTY,"[%s] no session at [%s]", request->plugin, session->config->sessiondir));
 
@@ -189,7 +194,7 @@ PUBLIC json_object *sessionFromDisk (AFB_session *session, AFB_request *request,
     // check for current session request
     defsession = (strcmp (name, AFB_DEFAULT_SESSION) ==0);
 
-    // if directory for card's sessions does not exist create it
+    // if directory for card's sessions.hash does not exist create it
     response = checkCardDirExit (session, request);
     if (response != NULL) return response;
 
@@ -238,7 +243,7 @@ PUBLIC json_object * sessionToDisk (AFB_session *session, AFB_request *request,
    // check for current session request
    defsession = (strcmp (name, AFB_DEFAULT_SESSION) ==0);
 
-   // if directory for card's sessions does not exist create it
+   // if directory for card's sessions.hash does not exist create it
    response = checkCardDirExit (session, request);
    if (response != NULL) return response;
 
@@ -326,64 +331,107 @@ STATIC void ctxUuidFreeCB (AFB_clientCtx *client) {
 
 // Create a new store in RAM, not that is too small it will be automatically extended
 PUBLIC void ctxStoreInit (int nbSession) {
-   int res; 
-   // let's create session hash table
-   res = hcreate_r(nbSession, &sessions);
+   int res;
+   
+   // let's create as store as hashtable does not have any
+   sessions.store = calloc (nbSession+1, sizeof(AFB_clientCtx));
+   sessions.max=nbSession;
 }
 
 STATIC AFB_clientCtx *ctxStoreSearch (const char* uuid) {
-    ENTRY item = {(char*) uuid};
-    ENTRY *pitem = &item;
-    // printf ("searching uuid=%s\n", uuid);
-    
-    pthread_mutex_lock(&mutexHash);
-    if (hsearch_r(item, FIND, &pitem, &sessions)) {
-        pthread_mutex_unlock(&mutexHash);
-        return  (AFB_clientCtx*) pitem->data;
+    int  idx;
+    AFB_clientCtx *client;
+    
+    if (uuid == NULL) return NULL;
+    
+    pthread_mutex_lock(&sessions.mutex);
+    
+    for (idx=0; idx < sessions.max; idx++) {
+        if (sessions.store[idx] && (0 == strcmp (uuid, sessions.store[idx]->uuid))) break;
     }
-    pthread_mutex_unlock(&mutexHash);
-    return NULL;
+    
+    if (idx == sessions.max) client=NULL;
+    else client= sessions.store[idx];
+    
+    pthread_mutex_unlock(&sessions.mutex);
+    
+    return (client);
 }
 
-// Reference http://stackoverflow.com/questions/25971505/how-to-delete-element-from-hsearch
-void ctxStoreAdd (AFB_clientCtx *client) {
-    ENTRY item = {client->uuid, (void*)client};
-    ENTRY *pitem = &item;
 
-    pthread_mutex_lock(&mutexHash);
-    if (hsearch_r(item, ENTER, &pitem, &sessions)) {
-        // printf ("storing uuid=%s\n", client->uuid);
-        pitem->data = (void *)client;
+STATIC AFB_error ctxStoreDel (AFB_clientCtx *client) {
+    int idx;
+    int status;
+    if (client == NULL) return (AFB_FAIL);
+
+    //fprintf (stderr, "ctxStoreDel request uuid=%s count=%d\n", client->uuid, sessions.count);
+    
+    pthread_mutex_lock(&sessions.mutex);
+    
+    for (idx=0; idx < sessions.max; idx++) {
+        if (sessions.store[idx] && (0 == strcmp (client->uuid, sessions.store[idx]->uuid))) break;
+    }
+    
+    if (idx == sessions.max) status=AFB_FAIL;
+    else {
+        sessions.count --;
+        sessions.store[idx]=NULL;
+        status=AFB_SUCCESS;
     }
-    pthread_mutex_unlock(&mutexHash);
+    
+    pthread_mutex_unlock(&sessions.mutex);
+    
+    return (status);
+    
+    // plugin registered a callback let's release semaphore and cleanup now
+    if ((client->plugin->freeCtxCB != NULL) && client->ctx) client->plugin->freeCtxCB(client);
 }
 
-void ctxStoreDel (AFB_clientCtx *client) {
-    ENTRY item = {client->uuid};
-    ENTRY *pitem = &item;
+STATIC AFB_error ctxStoreAdd (AFB_clientCtx *client) {
+    int idx;
+    int status;
+    if (client == NULL) return (AFB_FAIL);
 
-    pthread_mutex_lock(&mutexHash);
-    if (hsearch_r(item, FIND, &pitem, &sessions)) {
-        pitem->data = NULL;
+    //fprintf (stderr, "ctxStoreAdd request uuid=%s count=%d\n", client->uuid, sessions.count);
+    
+    pthread_mutex_lock(&sessions.mutex);
+    
+    for (idx=0; idx < sessions.max; idx++) {
+        if (NULL == sessions.store[idx]) break;
+    }
+    
+    if (idx == sessions.max) status=AFB_FAIL;
+    else {
+        status=AFB_SUCCESS;
+        sessions.count ++;
+        sessions.store[idx]= client;
     }
-    pthread_mutex_unlock(&mutexHash);
+    
+    pthread_mutex_unlock(&sessions.mutex);
+    
+    return (status);
 }
 
 // Check if context timeout or not
-STATIC int ctxStoreToOld (const void *k1, int timeout) {
+STATIC int ctxStoreToOld (AFB_clientCtx *ctx, int timeout) {
     int res;
-    AFB_clientCtx *ctx = (AFB_clientCtx*) k1;
     time_t now =  time(NULL);
     res = ((ctx->timeStamp + timeout) <= now);
     return (res);    
 }
 
-// Loop on every entry and remove old context sessions
-PUBLIC int ctxStoreGarbage (struct lh_table *lht, const int timeout) {
-    if (verbose) fprintf (stderr, "****** Garbage Count=%d timeout=%d\n", lht->count, timeout);
-
-  
+// Loop on every entry and remove old context sessions.hash
+PUBLIC int ctxStoreGarbage (const int timeout) {
+    AFB_clientCtx *ctx;
+    long idx;
+    
+    // Loop on Sessions Table and remove anything that is older than timeout
+    for (idx=0; idx < sessions.max; idx++) {
+        ctx=sessions.store[idx];
+        if ((ctx != NULL) && (ctxStoreToOld(ctx, timeout))) {
+            ctxStoreDel (ctx);
+        }
+    }
 }
 
 // This function will return exiting client context or newly created client context
@@ -410,12 +458,17 @@ PUBLIC AFB_error ctxClientGet (AFB_request *request, AFB_plugin *plugin) {
     if ((uuid != NULL) && (strnlen (uuid, 10) >= 10))   {
         int search;
         // search if client context exist and it not timeout let's use it
-        printf ("search old UID=%s\n", uuid);
         clientCtx = ctxStoreSearch (uuid);
 
-       if (clientCtx && ! ctxStoreToOld (clientCtx, request->config->cntxTimeout)) {
-            request->client=clientCtx;
-            return;            
+       if (clientCtx) {
+            if (ctxStoreToOld (clientCtx, request->config->cntxTimeout)) {
+                 // this session is too old let's delete it
+                ctxStoreDel (clientCtx);
+                clientCtx=NULL;
+            } else {
+                request->client=clientCtx;
+                return (AFB_SUCCESS);            
+            }
         }
     }
    
@@ -428,17 +481,18 @@ PUBLIC AFB_error ctxClientGet (AFB_request *request, AFB_plugin *plugin) {
     clientCtx->plugin;    // provide plugin callbacks a hook to plugin
         
     // if table is full at 50% let's clean it up
-    // if(clientCtxs->count > (clientCtxs->size / 2)) ctxStoreGarbage(clientCtxs, request->config->cntxTimeout);
+    if(sessions.count > (sessions.max / 2)) ctxStoreGarbage(request->config->cntxTimeout);
     
     // finally add uuid into hashtable
-    ctxStoreAdd (clientCtx);
-    
-    // if (ret < 0) return (AFB_FAIL);
+    if (AFB_SUCCESS != ctxStoreAdd (clientCtx)) {
+        free (clientCtx);
+        return(AFB_FAIL);
+    }
     
-    if (verbose) fprintf (stderr, "ctxClientGet New uuid=[%s] token=[%s] timestamp=%d\n", clientCtx->uuid, clientCtx->token, clientCtx->timeStamp);      
+    // if (verbose) fprintf (stderr, "ctxClientGet New uuid=[%s] token=[%s] timestamp=%d\n", clientCtx->uuid, clientCtx->token, clientCtx->timeStamp);      
     request->client = clientCtx;
 
-    return (AFB_SUCCESS);
+    return(AFB_SUCCESS);
 }
 
 // Sample Generic Ping Debug API