Add Middleware and change Hashtable techno
authorFulup Ar Foll <fulup@iot.bzh>
Wed, 16 Dec 2015 01:30:20 +0000 (02:30 +0100)
committerFulup Ar Foll <fulup@iot.bzh>
Wed, 16 Dec 2015 01:30:20 +0000 (02:30 +0100)
include/local-def.h
include/proto-def.h
nbproject/configurations.xml
nbproject/private/Default.properties
nbproject/private/configurations.xml
src/afbs-api.c
src/alsa-api.c
src/dbus-api.c
src/http-svc.c
src/rest-api.c
src/session.c

index 021ef13..cbbef0f 100644 (file)
@@ -77,7 +77,7 @@ typedef int BOOL;
 extern int verbose;  // this is the only global variable
 
 // Plugin Type
-typedef enum  {AFB_PLUGIN_JSON=123456789, AFB_PLUGIN_JSCRIPT=987654321,  AFB_PLUGIN_RAW=987123546} AFB_pluginT;
+typedef enum  {AFB_PLUGIN_JSON=123456789, AFB_PLUGIN_JSCRIPT=987654321,  AFB_PLUGIN_RAW=987123546} AFB_pluginE;
 
 // prebuild json error are constructed in config.c
 typedef enum  { AFB_FALSE, AFB_TRUE, AFB_FATAL, AFB_FAIL, AFB_WARNING, AFB_EMPTY, AFB_SUCCESS, AFB_DONE, AFB_UNAUTH} AFB_error;
@@ -116,7 +116,7 @@ typedef struct {
   int    uid;               // post uid for debug
   AFB_PostType type;        // JSON or FORM
   AFB_apiCB  completeCB;    // callback when post is completed
-  void   *private;          // use internally to keep track or partial buffer
+  char   *private;          // use internally to keep track or partial buffer
   struct MHD_PostProcessor *pp; // iterator handle
 } AFB_PostHandle;
 
@@ -183,9 +183,13 @@ typedef struct {
      size_t  len;
 } AFB_redirect_msg;
 
+// Enum for Session/Token/Authentication middleware
+typedef enum  {AFB_SESSION_NONE, AFB_SESSION_CREATE, AFB_SESSION_CLOSE, AFB_SESSION_RENEW, AFB_SESSION_CHECK} AFB_sessionE;
+
 // API definition
 typedef struct {
   char *name;
+  AFB_sessionE session;
   AFB_apiCB callback;
   char *info;
   AFB_privateApi *private;
@@ -193,7 +197,7 @@ typedef struct {
 
 // Plugin definition
 typedef struct {
-  AFB_pluginT type;  
+  AFB_pluginE type;  
   char *info;
   char *prefix;
   size_t prefixlen;
index 1a3145f..d800114 100644 (file)
@@ -49,6 +49,7 @@ 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, AFB_plugin *plugin);
+PUBLIC void      ctxStoreInit (int);
 
 
 
index b1f18a0..6b0679d 100644 (file)
         </preBuild>
       </makefileType>
       <item path="src/afbs-api.c" ex="false" tool="0" flavor2="2">
-        <cTool flags="0">
+        <cTool flags="1">
           <incDir>
-            <pElem>include</pElem>
+            <pElem>src</pElem>
             <pElem>/usr/include/json-c</pElem>
+            <pElem>include</pElem>
+            <pElem>/usr/include/uuid</pElem>
             <pElem>build/src</pElem>
           </incDir>
+          <preprocessorList>
+            <Elem>__PIC__=2</Elem>
+            <Elem>__PIE__=2</Elem>
+            <Elem>__REGISTER_PREFIX__=</Elem>
+            <Elem>__USER_LABEL_PREFIX__=</Elem>
+            <Elem>__pic__=2</Elem>
+            <Elem>__pie__=2</Elem>
+          </preprocessorList>
         </cTool>
       </item>
       <item path="src/alsa-api.c" ex="false" tool="0" flavor2="2">
         </cTool>
       </item>
       <item path="src/config.c" ex="false" tool="0" flavor2="2">
-        <cTool flags="0">
+        <cTool flags="1">
           <incDir>
-            <pElem>include</pElem>
+            <pElem>src</pElem>
             <pElem>/usr/include/json-c</pElem>
+            <pElem>include</pElem>
+            <pElem>/usr/include/uuid</pElem>
             <pElem>build/src</pElem>
           </incDir>
+          <preprocessorList>
+            <Elem>__PIC__=2</Elem>
+            <Elem>__PIE__=2</Elem>
+            <Elem>__REGISTER_PREFIX__=</Elem>
+            <Elem>__USER_LABEL_PREFIX__=</Elem>
+            <Elem>__pic__=2</Elem>
+            <Elem>__pie__=2</Elem>
+          </preprocessorList>
         </cTool>
       </item>
       <item path="src/dbus-api.c" ex="false" tool="0" flavor2="2">
-        <cTool flags="0">
+        <cTool flags="1">
           <incDir>
-            <pElem>include</pElem>
+            <pElem>src</pElem>
             <pElem>/usr/include/json-c</pElem>
+            <pElem>include</pElem>
+            <pElem>/usr/include/uuid</pElem>
             <pElem>build/src</pElem>
           </incDir>
+          <preprocessorList>
+            <Elem>__PIC__=2</Elem>
+            <Elem>__PIE__=2</Elem>
+            <Elem>__REGISTER_PREFIX__=</Elem>
+            <Elem>__USER_LABEL_PREFIX__=</Elem>
+            <Elem>__pic__=2</Elem>
+            <Elem>__pie__=2</Elem>
+          </preprocessorList>
         </cTool>
       </item>
       <item path="src/http-svc.c" ex="false" tool="0" flavor2="2">
-        <cTool flags="0">
+        <cTool flags="1">
           <incDir>
-            <pElem>include</pElem>
+            <pElem>src</pElem>
             <pElem>/usr/include/json-c</pElem>
+            <pElem>include</pElem>
+            <pElem>/usr/include/uuid</pElem>
             <pElem>build/src</pElem>
           </incDir>
+          <preprocessorList>
+            <Elem>__PIC__=2</Elem>
+            <Elem>__PIE__=2</Elem>
+            <Elem>__REGISTER_PREFIX__=</Elem>
+            <Elem>__USER_LABEL_PREFIX__=</Elem>
+            <Elem>__pic__=2</Elem>
+            <Elem>__pie__=2</Elem>
+          </preprocessorList>
         </cTool>
       </item>
       <item path="src/main.c" ex="false" tool="0" flavor2="2">
-        <cTool flags="0">
+        <cTool flags="1">
           <incDir>
-            <pElem>include</pElem>
+            <pElem>src</pElem>
             <pElem>/usr/include/json-c</pElem>
+            <pElem>include</pElem>
+            <pElem>/usr/include/uuid</pElem>
             <pElem>build/src</pElem>
           </incDir>
+          <preprocessorList>
+            <Elem>__PIC__=2</Elem>
+            <Elem>__PIE__=2</Elem>
+            <Elem>__REGISTER_PREFIX__=</Elem>
+            <Elem>__USER_LABEL_PREFIX__=</Elem>
+            <Elem>__pic__=2</Elem>
+            <Elem>__pie__=2</Elem>
+          </preprocessorList>
         </cTool>
       </item>
       <item path="src/radio-api.c" ex="false" tool="0" flavor2="2">
         </cTool>
       </item>
       <item path="src/rest-api.c" ex="false" tool="0" flavor2="2">
-        <cTool flags="0">
+        <cTool flags="1">
           <incDir>
-            <pElem>include</pElem>
+            <pElem>src</pElem>
             <pElem>/usr/include/json-c</pElem>
+            <pElem>include</pElem>
+            <pElem>/usr/include/uuid</pElem>
             <pElem>build/src</pElem>
           </incDir>
+          <preprocessorList>
+            <Elem>__PIC__=2</Elem>
+            <Elem>__PIE__=2</Elem>
+            <Elem>__REGISTER_PREFIX__=</Elem>
+            <Elem>__USER_LABEL_PREFIX__=</Elem>
+            <Elem>__pic__=2</Elem>
+            <Elem>__pie__=2</Elem>
+          </preprocessorList>
         </cTool>
       </item>
       <item path="src/session.c" ex="false" tool="0" flavor2="2">
index a45c3d2..e63c237 100644 (file)
@@ -1,2 +1 @@
 /home/fulup/Workspace/afb-daemon/src/session.c=/home/fulup/Workspace/afb-daemon/build/src#-g3 -gdwarf-2 -fPIE -I/home/fulup/Workspace/afb-daemon/include -I/usr/include/json-c -o CMakeFiles/afb-daemon.dir/session.c.o -c /home/fulup/Workspace/afb-daemon/src/session.c
-/home/fulup/Workspace/afb-daemon/src/http-svc.c=/home/fulup/Workspace/afb-daemon/build/src#-g3 -gdwarf-2 -fPIE -I/home/fulup/Workspace/afb-daemon/include -I/usr/include/json-c -o CMakeFiles/afb-daemon.dir/http-svc.c.o -c /home/fulup/Workspace/afb-daemon/src/http-svc.c
index 7306ab2..706acf3 100644 (file)
@@ -11,8 +11,6 @@
           </df>
           <df name="CMakeTmp">
           </df>
-          <df name="Progress">
-          </df>
           <in>feature_tests.c</in>
         </df>
         <df name="src">
@@ -29,6 +27,7 @@
         <in>proto-def.h</in>
       </df>
       <df name="src">
+        <in>SamplePost.c</in>
         <in>afbs-api.c</in>
         <in>alsa-api.c</in>
         <in>config.c</in>
@@ -49,8 +48,6 @@
           </df>
           <df name="CMakeTmp">
           </df>
-          <df name="Progress">
-          </df>
         </df>
         <df name="src">
           <df name="CMakeFiles">
index 1a3399f..9e1c766 100644 (file)
@@ -29,87 +29,45 @@ typedef struct {
 // Request Creation of new context if it does not exist
 STATIC json_object* clientContextCreate (AFB_request *request) {
     json_object *jresp;
-    int   res;
-    char *token;
-    AFB_clientCtx *client=request->client; // get client context from request
-   
-    // check we do not already have a session
-    if ((client != NULL) && (client->ctx != NULL)) {
-        request->errcode=MHD_HTTP_FORBIDDEN;
-        return (jsonNewMessage(AFB_FAIL, "Token exist use refresh"));
-    }
-        
-    // request a new client context token and check result 
-    if (AFB_UNAUTH == ctxTokenCreate (request)) {
-        request->errcode=MHD_HTTP_UNAUTHORIZED;
-        jresp= jsonNewMessage(AFB_FAIL, "No/Invalid initial token provided [should match --token=xxxx]");
-        return (jresp);
-    }
-    
-    // request a new client context token and check result 
-    if (AFB_SUCCESS != ctxTokenCreate (request)) {
-        request->errcode=MHD_HTTP_UNAUTHORIZED;
-        jresp= jsonNewMessage(AFB_FAIL, "Token Session Not Activated [restart with --token=xxxx]");
-        return (jresp);
-    }
-   
-    // add a client context to session
-    client->ctx = malloc (sizeof (MyClientApplicationHandle));
+
+    // 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 (client->token));
+    json_object_object_add(jresp, "token", json_object_new_string ("A New Token and Session Context Was Created"));
 
     return (jresp);
 }
 
-// Renew an existing context
+// Before entering here token will be check and renew
 STATIC json_object* clientContextRefresh (AFB_request *request) {
     json_object *jresp;
 
-    // note: we do not need to parse the old token as clientContextRefresh doit for us
-    if (AFB_SUCCESS != ctxTokenRefresh (request)) {
-        request->errcode=MHD_HTTP_UNAUTHORIZED;
-        jresp= jsonNewMessage(AFB_FAIL, "Token Exchange Broken Refresh Refused");
-    } else {
-        jresp = json_object_new_object();
-        json_object_object_add(jresp, "token", json_object_new_string (request->client->token));              
-    }
-            
+  
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "token", json_object_new_string ("Token was refreshed"));              
+    
     return (jresp);
 }
 
 
-// Verify a context is still valid 
+// Session token will we verified before entering here
 STATIC json_object* clientContextCheck (AFB_request *request) {
     
-    json_object *jresp = json_object_new_object();
-    
-    // add an error code to respond
-    if (AFB_SUCCESS != ctxTokenCheck (request)) {
-        request->errcode=MHD_HTTP_UNAUTHORIZED;
-        json_object_object_add(jresp, "isvalid", json_object_new_boolean (FALSE));
-    } else {
-        json_object_object_add(jresp, "isvalid", json_object_new_boolean (TRUE));       
-    }
+    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;
    
-    // note: we do not need to parse the old token as clientContextRefresh doit for us
-    if (AFB_SUCCESS != ctxTokenReset (request)) {
-        request->errcode=MHD_HTTP_UNAUTHORIZED;
-        jresp= jsonNewMessage(AFB_FAIL, "No Token Client Context [use --token=xxx]");
-    } else {
-        jresp = json_object_new_object();
-        json_object_object_add(jresp, "uuid", json_object_new_string (request->client->uuid));              
-    }
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "uuid", json_object_new_string (request->client->uuid));              
     
     return (jresp); 
 }
@@ -214,12 +172,12 @@ STATIC void clientContextFree(AFB_clientCtx *client) {
 }
 
 STATIC  AFB_restapi pluginApis[]= {
-  {"ping"          , (AFB_apiCB)apiPingTest         ,"Ping Rest Test Service"},
-  {"token-create"  , (AFB_apiCB)clientContextCreate ,"Request Client Context Creation"},
-  {"token-refresh" , (AFB_apiCB)clientContextRefresh,"Refresh Client Context Token"},
-  {"token-check"   , (AFB_apiCB)clientContextCheck  ,"Check Client Context Token"},
-  {"token-reset"   , (AFB_apiCB)clientContextReset  ,"Close Client Context and Free resources"},
-  {"file-upload"   , (AFB_apiCB)ProcessPostForm     ,"Demo for file upload"},
+  {"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"},
   {NULL}
 };
 
index 46b971b..9d4f3cb 100644 (file)
@@ -27,23 +27,6 @@ STATIC json_object* wrongApi (AFB_request *request, void* handle) {
     impossible=bug/zero;
 }
 
-STATIC json_object* pingSample (AFB_request *request) {
-    static pingcount = 0;
-    json_object *response;
-    char query [512];
-
-    // request all query key/value
-    getQueryAll (request,query, sizeof(query)); 
-    
-    // check if we have some post data
-    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, request->post);
-    
-    return (response);
-}
 
 
 STATIC struct {
@@ -52,10 +35,9 @@ STATIC struct {
 
 
 STATIC  AFB_restapi pluginApis[]= {
-  {"ping"     , (AFB_apiCB)pingSample , "Ping Application Framework"},
-  {"error"    , (AFB_apiCB)wrongApi   , "Ping Application Framework"},
-  {"ctx-store", (AFB_apiCB)pingSample , "Verbose Mode"},
-  {"ctx-load" , (AFB_apiCB)pingSample , "Verbose Mode"},
+  {"ping"     , AFB_SESSION_NONE, (AFB_apiCB)apiPingTest,"Ping Application Framework"},
+  {"error"    , AFB_SESSION_NONE, (AFB_apiCB)wrongApi   , "Ping Application Framework"},
+
   {NULL}
 };
 
index f7b071b..70de03f 100644 (file)
@@ -30,7 +30,7 @@ STATIC json_object* pingSample (AFB_request *request) {
     if (len == 0) strcpy (query,"NoSearchQueryList");
     
     // check if we have some post data
-    if (request->post == NULL)  request->post="NoData";  
+    if (request->post == NULL)  request->post->data="NoData";  
         
     // return response to caller
     response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon %d query={%s} PostData: \'%s\' ", pingcount++, query, request->post);
@@ -75,12 +75,12 @@ STATIC json_object* pingJson (AFB_session *session, AFB_request *request) {
 
 
 STATIC  AFB_restapi pluginApis[]= {
-  {"ping"     , (AFB_apiCB)pingSample  , "Ping Application Framework"},
-  {"pingnull" , (AFB_apiCB)pingFail    , "Return NULL"},
-  {"pingbug"  , (AFB_apiCB)pingBug     , "Do a Memory Violation"},
-  {"pingJson" , (AFB_apiCB)pingJson    , "Return a JSON object"},
-  {"ctx-store", (AFB_apiCB)pingSample  , "Verbose Mode"},
-  {"ctx-load" , (AFB_apiCB)pingSample  , "Verbose Mode"},
+  {"ping"     , AFB_SESSION_NONE, (AFB_apiCB)pingSample  , "Ping Application Framework"},
+  {"pingnull" , AFB_SESSION_NONE, (AFB_apiCB)pingFail    , "Return NULL"},
+  {"pingbug"  , AFB_SESSION_NONE, (AFB_apiCB)pingBug     , "Do a Memory Violation"},
+  {"pingJson" , AFB_SESSION_NONE, (AFB_apiCB)pingJson    , "Return a JSON object"},
+  {"ctx-store", AFB_SESSION_NONE, (AFB_apiCB)pingSample  , "Verbose Mode"},
+  {"ctx-load" , AFB_SESSION_NONE, (AFB_apiCB)pingSample  , "Verbose Mode"},
   {NULL}
 };
 
index ac0606e..b3b9a1f 100644 (file)
@@ -267,6 +267,9 @@ PUBLIC AFB_error httpdStart(AFB_session *session) {
     apiUrlLen = strlen (session->config->rootapi);
     baseUrlLen= strlen (session->config->rootbase);
     rootUrlLen= strlen (session->config->rootdir);
+    
+    // Initialise Client Session Hash Table
+    ctxStoreInit (CTX_NBCLIENTS);
      
     // TBD open libmagic cache [fail to pass EFENCE check]
     // initLibMagic (session);
index 35e81d7..ad3a4f2 100644 (file)
@@ -107,7 +107,7 @@ PUBLIC void endPostRequest(AFB_PostHandle *postHandle) {
             if (!postHandle->completeCB) postHandle->completeCB (postHandle->private);
         }
     }
-    freeRequest (postHandle->private);
+    free(postHandle->private);
     free(postHandle);
 }
 
@@ -138,6 +138,11 @@ STATIC AFB_error callPluginApi(AFB_plugin *plugin, AFB_request *request, void *c
     for (idx = 0; plugin->apis[idx].callback != NULL; idx++) {
         if (!strcmp(plugin->apis[idx].name, request->api)) {
             
+            // Request was found and at least partially executed
+            request->jresp  = json_object_new_object();
+            json_object_get (afbJsonType);  // increate jsontype reference count
+            json_object_object_add (request->jresp, "jtype", afbJsonType);
+            
             // prepare an object to store calling values
             jcall=json_object_new_object();
             json_object_object_add(jcall, "prefix", json_object_new_string (plugin->prefix));
@@ -158,25 +163,94 @@ STATIC AFB_error callPluginApi(AFB_plugin *plugin, AFB_request *request, void *c
                 if (request->config->apiTimeout > 0) {
                     for (sig=0; signals[sig] != 0; sig++) {
                        if (signal (signals[sig], pluginError) == SIG_ERR) {
-                           request->errcode = MHD_HTTP_UNPROCESSABLE_ENTITY;
-                           request->jresp = jsonNewMessage(AFB_FATAL, "%s ERR: Signal/timeout handler activation fail.", configTime());
-                           return AFB_FAIL;
+                            request->errcode = MHD_HTTP_UNPROCESSABLE_ENTITY;
+                            json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+                            json_object_object_add(jcall, "info", json_object_new_string ("Setting Timeout Handler Failed"));
+                            json_object_object_add(request->jresp, "request", jcall);
+                            return AFB_DONE;
                        }
                     }
                     // Trigger a timer to protect from unacceptable long time execution
                     alarm (request->config->apiTimeout);
                 }
+
+                // Out of SessionNone every call get a client context session
+                if (AFB_SESSION_NONE != plugin->apis[idx].session) {
+                    
+                    // add client context to request
+                    ctxClientGet(request, plugin);
+                    
+                    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);                        
+                    
+                    switch(plugin->apis[idx].session) {
+
+                        case AFB_SESSION_CREATE:
+                            if (request->client->token[0] != '\0') {
+                                request->errcode=MHD_HTTP_UNAUTHORIZED;
+                                json_object_object_add(jcall, "status", json_object_new_string ("exist"));
+                                json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CREATE Session already exist"));
+                                json_object_object_add(request->jresp, "request", jcall);
+                                return (AFB_DONE);                              
+                            }
+                        
+                            if (AFB_SUCCESS != ctxTokenCreate (request)) {
+                                request->errcode=MHD_HTTP_UNAUTHORIZED;
+                                json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+                                json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CREATE Invalid Initial Token"));
+                                json_object_object_add(request->jresp, "request", jcall);
+                                return (AFB_DONE);
+                            } else {
+                                json_object_object_add(jcall, "uuid", json_object_new_string (request->client->uuid));                                
+                                json_object_object_add(jcall, "token", json_object_new_string (request->client->token));                                
+                            }
+                            break;
+
+
+                        case AFB_SESSION_RENEW:
+                            if (AFB_SUCCESS != ctxTokenRefresh (request)) {
+                                request->errcode=MHD_HTTP_UNAUTHORIZED;
+                                json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+                                json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_REFRESH Broken Exchange Token Chain"));
+                                json_object_object_add(request->jresp, "request", jcall);
+                                return (AFB_DONE);
+                            } else {
+                                json_object_object_add(jcall, "uuid", json_object_new_string (request->client->uuid));                                
+                                json_object_object_add(jcall, "token", json_object_new_string (request->client->token));                                
+                            }
+                            break;
+
+                        case AFB_SESSION_CLOSE:
+                            if (AFB_SUCCESS != ctxTokenCheck (request)) {
+                                request->errcode=MHD_HTTP_UNAUTHORIZED;
+                                json_object_object_add(jcall, "status", json_object_new_string ("empty"));
+                                json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CLOSE Not a Valid Access Token"));
+                                json_object_object_add(request->jresp, "request", jcall);
+                                return (AFB_DONE);
+                            } else {
+                                json_object_object_add(jcall, "uuid", json_object_new_string (request->client->uuid));                                
+                            }
+                            break;
+                        
+                        case AFB_SESSION_CHECK:
+                        default: 
+                            // default action is check
+                            if (AFB_SUCCESS != ctxTokenCheck (request)) {
+                                request->errcode=MHD_HTTP_UNAUTHORIZED;
+                                json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+                                json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CHECK Invalid Active Token"));
+                                json_object_object_add(request->jresp, "request", jcall);
+                                return (AFB_DONE);
+                            }
+                            break;
+                    }
+                }
                 
-                // add client context to request
-                ctxClientGet(request, plugin);      
-             
                 // Effectively call the API with a subset of the context
                 jresp = plugin->apis[idx].callback(request, context);
 
-                // Allocate Json object and build response
-                request->jresp  = json_object_new_object();
-                json_object_get (afbJsonType);  // increate jsontype reference count
-                json_object_object_add (request->jresp, "jtype", afbJsonType);
+                // Session close is done after the API call so API can still use session in closing API
+                if (AFB_SESSION_CLOSE == plugin->apis[idx].session) ctxTokenReset (request);                    
                 
                 // API should return NULL of a valid Json Object
                 if (jresp == NULL) {
@@ -200,17 +274,18 @@ STATIC AFB_error callPluginApi(AFB_plugin *plugin, AFB_request *request, void *c
             return (AFB_DONE);
         }
     }
+    
     return (AFB_FAIL);
 }
 
 STATIC AFB_error findAndCallApi (AFB_request *request, void *context) {
     int idx;
-    char *baseurl, *baseapi;
     AFB_error status;
+    
    
     // Search for a plugin with this urlpath
     for (idx = 0; request->plugins[idx] != NULL; idx++) {
-        if (!strcmp(request->plugins[idx]->prefix, baseurl)) {
+        if (!strcmp(request->plugins[idx]->prefix, request->plugin)) {
             status =callPluginApi(request->plugins[idx], request, context);
             break;
         }
@@ -226,7 +301,10 @@ STATIC AFB_error findAndCallApi (AFB_request *request, void *context) {
         request->jresp = jsonNewMessage(AFB_FATAL, "No API=[%s] for Plugin=[%s]", request->api, request->plugin);
         goto ExitOnError;
     }
-   
+
+
+
+    
     // Everything look OK
     return (status);
     
@@ -262,10 +340,10 @@ doPostIterate (void *cls, enum MHD_ValueKind kind, const char *key,
   item.offset   = offset;
   
   // Reformat Request to make it somehow similar to GET/PostJson case
-  post.data= (char*) postctx;
-  post.len = size;
-  post.type= AFB_POST_FORM;;
-  request->post = &post;
+  postRequest.data= (char*) postHandle;
+  postRequest.len = size;
+  postRequest.type= AFB_POST_FORM;;
+  request->post = &postRequest;
   
   // effectively call plugin API                 
   status = findAndCallApi (request, &item);
@@ -274,10 +352,11 @@ doPostIterate (void *cls, enum MHD_ValueKind kind, const char *key,
   if (status != AFB_SUCCESS) return MHD_NO;
   
   // let's allow iterator to move to next item
-  return (MHD_YES;);
+  return (MHD_YES);
 }
 
 STATIC void freeRequest (AFB_request *request) {
+
  free (request->plugin);    
  free (request->api);    
  free (request);    
@@ -289,32 +368,32 @@ STATIC AFB_request *createRequest (struct MHD_Connection *connection, AFB_sessio
     
     // Start with a clean request
     request = calloc (1, sizeof (AFB_request));
-    char *urlcpy1, urlcpy2;
+    char *urlcpy1, *urlcpy2;
+    char *baseapi, *baseurl;  
       
     // Extract plugin urlpath from request and make two copy because strsep overload copy
     urlcpy1 = urlcpy2 = strdup(url);
     baseurl = strsep(&urlcpy2, "/");
     if (baseurl == NULL) {
-        errMessage = jsonNewMessage(AFB_FATAL, "Invalid API call url=[%s]", url);
-        goto ExitOnError;
+        request->jresp = jsonNewMessage(AFB_FATAL, "Invalid API call url=[%s]", url);
     }
 
     // let's compute URL and call API
     baseapi = strsep(&urlcpy2, "/");
     if (baseapi == NULL) {
-        errMessage = jsonNewMessage(AFB_FATAL, "Invalid API call url=[%s]", url);
-        goto ExitOnError;
+        request->jresp = jsonNewMessage(AFB_FATAL, "Invalid API call url=[%s]", url);
     }
     
     // build request structure
     request->connection = connection;
-    request->config = session.config;
+    request->config = session->config;
     request->url    = url;
     request->plugin = strdup (baseurl);
     request->api    = strdup (baseapi);
     request->plugins= session->plugins;
     
     free(urlcpy1);
+    return (request);
 }
 
 // process rest API query
@@ -326,41 +405,45 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
     AFB_error status;
     struct MHD_Response *webResponse;
     const char *serialized;
-    AFB_request request;
-    AFB_PostHandle *posthandle;
+    AFB_request *request;
+    AFB_PostHandle *postHandle;
+    AFB_PostRequest postRequest;
     int ret;
   
     // if post data may come in multiple calls
     if (0 == strcmp(method, MHD_HTTP_METHOD_POST)) {
         const char *encoding, *param;
         int contentlen = -1;
-        posthandle = *con_cls;
+        postHandle = *con_cls;
 
         // This is the initial post event let's create form post structure POST datas come in multiple events
-        if (posthandle == NULL) {
-            fprintf(stderr, "This is the 1st Post Event postuid=%d\n", posthandle->uid);
+        if (postHandle == NULL) {
 
             // allocate application POST processor handle to zero
-            posthandle = cmalloc(1, sizeof (AFB_PostHandle));
-            posthandle->uid = postcount++; // build a UID for DEBUG
-            *con_cls = posthandle;         // attache POST handle to current HTTP request
+            postHandle = calloc(1, sizeof (AFB_PostHandle));
+            postHandle->uid = postcount++; // build a UID for DEBUG
+            *con_cls = postHandle;         // attache POST handle to current HTTP request
             
             // 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);
-            param = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH);
-            if (param) sscanf(param, "%i", &contentlen);
         
             // Form post is handle through a PostProcessor and call API once per form key
             if (strcasestr(encoding, FORM_CONTENT) != NULL) {
-               
-                posthandle = malloc(sizeof (AFB_PostHandle)); // allocate application POST processor handle
-                posthandle->type   = AFB_POST_FORM;
-                posthandle->private= (void*)createRequest (connection, session, url);
-                posthandle->pp     = MHD_create_post_processor (connection, MAX_POST_SIZE, doPostIterate, posthandle);
-               
-                if (NULL == posthandle->pp) {
+                if (verbose) fprintf(stderr, "Create PostForm[uid=%d]\n", postHandle->uid);
+
+                request = createRequest (connection, session, url);
+                if (request->jresp != NULL) {
+                    errMessage = request->jresp;
+                    goto ExitOnError;
+                }
+                postHandle = malloc(sizeof (AFB_PostHandle)); // allocate application POST processor handle
+                postHandle->type   = AFB_POST_FORM;
+                postHandle->pp     = MHD_create_post_processor (connection, MAX_POST_SIZE, doPostIterate, postHandle);
+                postHandle->private= (void*)request;
+                
+                if (NULL == postHandle->pp) {
                     fprintf(stderr,"OOPS: Internal error fail to allocate MHD_create_post_processor\n");
-                    free (posthandle);
+                    free (postHandle);
                     return MHD_NO;
                 }
                 return MHD_YES;
@@ -369,40 +452,46 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
             // POST json is store into a buffer and present in one piece to API
             if (strcasestr(encoding, JSON_CONTENT) != NULL) {
 
+                param = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH);
+                if (param) sscanf(param, "%i", &contentlen);
+
+                // Because PostJson are build in RAM size is constrained
                 if (contentlen > MAX_POST_SIZE) {
                     errMessage = jsonNewMessage(AFB_FATAL, "Post Date to big %d > %d", contentlen, MAX_POST_SIZE);
                     goto ExitOnError;
                 }
 
-                if (posthandle == NULL) {
-                    posthandle->type = AFB_POST_JSON;
-                    posthandle->private = malloc(contentlen + 1); // allocate memory for full POST data + 1 for '\0' enf of string
+                // Size is OK, let's allocate a buffer to hold post data
+                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[%d] Size=%d\n", posthandle->uid, contentlen);
-                    return MHD_YES;
-                }
+                if (verbose) fprintf(stderr, "Create PostJson[uid=%d] Size=%d\n", postHandle->uid, contentlen);
+                return MHD_YES;
 
+            } else {
                 // We only support Json and Form Post format
                 errMessage = jsonNewMessage(AFB_FATAL, "Post Date wrong type encoding=%s != %s", encoding, JSON_CONTENT);
                 goto ExitOnError;
-            }    
+                
+            }   
         }
 
         // This time we receive partial/all Post data. Note that even if we get all POST data. We should nevertheless
         // return MHD_YES and not process the request directly. Otherwise Libmicrohttpd is unhappy and fails with
         // 'Internal application error, closing connection'.            
         if (*upload_data_size) {
-            if (verbose) fprintf(stderr, "Update Post[%d]\n", posthandle->uid);
     
-            if (posthandle->type == AFB_POST_FORM) {
-                MHD_post_process (con_info->postprocessor, upload_data, *upload_data_size);
+            if (postHandle->type == AFB_POST_FORM) {
+                if (verbose) fprintf(stderr, "Processing PostForm[uid=%d]\n", postHandle->uid);
+                MHD_post_process (postHandle->pp, upload_data, *upload_data_size);
             }
             
             // Process JsonPost request when buffer is completed let's call API    
-            if (posthandle->type == AFB_POST_JSON) {
+            if (postHandle->type == AFB_POST_JSON) {
+                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;
+                memcpy(&postHandle->private[postHandle->len], upload_data, *upload_data_size);
+                postHandle->len = postHandle->len + *upload_data_size;
                 *upload_data_size = 0;
             }
             return MHD_YES;
@@ -411,25 +500,31 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
             
             // Create a request structure to finalise the request
             request= createRequest (connection, session, url);
-
-            // We should only start to process DATA after Libmicrohttpd call or application handler with *upload_data_size==0
-            if (posthandle->type == AFB_POST_FORM) {
-                MHD_post_process (posthandle->pp, upload_data, *upload_data_size);
+            if (request->jresp != NULL) {
+                errMessage = request->jresp;
+                goto ExitOnError;
             }
+
             
-            if (posthandle->type == AFB_POST_JSON) {
+            if (postHandle->type == AFB_POST_JSON) {
+                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);
+
                 // At this level we're may verify that we got everything and process DATA
-                if (posthandle->len != contentlen) {
-                    errMessage = jsonNewMessage(AFB_FATAL, "Post Data Incomplete UID=%d Len %d != %s", posthandle->uid, contentlen, posthandle->len);
+                if (postHandle->len != contentlen) {
+                    errMessage = jsonNewMessage(AFB_FATAL, "Post Data Incomplete UID=%d Len %d != %d", postHandle->uid, contentlen, postHandle->len);
                     goto ExitOnError;
                 }
 
                 // Before processing data, make sure buffer string is properly ended
-                posthandle->private[posthandle->len] = '\0';
-                request->post.data = posthandle->private;
-                request->post.type = posthandle->type;
+                postHandle->private[postHandle->len] = '\0';
+                postRequest.data = postHandle->private;
+                postRequest.type = postHandle->type;
+                request->post = &postRequest;
 
-                if (verbose) fprintf(stderr, "Close Post[%d] Buffer=%s\n", posthandle->uid, request.post);
+                if (verbose) fprintf(stderr, "Close Post[%d] Buffer=%s\n", postHandle->uid, request->post->data);
             }
         }
     } else {
@@ -441,23 +536,23 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co
     status = findAndCallApi (request, NULL);
     
 ExitOnResponse:
-    freeRequest (request);
-    serialized = json_object_to_json_string(request.jresp);
+    serialized = json_object_to_json_string(request->jresp);
     webResponse = MHD_create_response_from_buffer(strlen(serialized), (void*) serialized, MHD_RESPMEM_MUST_COPY);
     
     // client did not pass token on URI let's use cookies 
-    if ((!request.restfull) && (request.client != NULL)) {
+    if ((!request->restfull) && (request->client != NULL)) {
        char cookie[64]; 
-       snprintf (cookie, sizeof (cookie), "%s=%s", COOKIE_NAME,  request.client->uuid); 
+       snprintf (cookie, sizeof (cookie), "%s=%s", COOKIE_NAME,  request->client->uuid); 
        MHD_add_response_header (webResponse, MHD_HTTP_HEADER_SET_COOKIE, cookie);
     }
     
     // if requested add an error status
-    if (request.errcode != 0)  ret=MHD_queue_response (connection, request.errcode, webResponse);
+    if (request->errcode != 0)  ret=MHD_queue_response (connection, request->errcode, webResponse);
     else MHD_queue_response(connection, MHD_HTTP_OK, webResponse);
     
     MHD_destroy_response(webResponse);
-    json_object_put(request.jresp); // decrease reference rqtcount to free the json object
+    json_object_put(request->jresp); // decrease reference rqtcount to free the json object
+    freeRequest (request);
     return MHD_YES;
 
 ExitOnError:
index 3494dad..55098b4 100644 (file)
@@ -27,6 +27,9 @@
 #include <time.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <pthread.h>
+#include <search.h>
+
 
 #define AFB_SESSION_JTYPE "AFB_session"
 #define AFB_SESSION_JLIST "AFB_sessions"
@@ -36,9 +39,8 @@
 #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 struct lh_table *clientCtxs=NULL;    // let's use JsonObject Hashtable to Store Sessions
-
+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
 
 // verify we can read/write in session dir
 PUBLIC AFB_error sessionCheckdir (AFB_session *session) {
@@ -308,32 +310,11 @@ OnErrorExit:
 }
 
 
-// Function to handle Cookies and Client session context it relies on json low level
-// linked list functionalities https://github.com/json-c/json-c/blob/master/linkhash.c
-
-// Hash client UUID before storing in table
-STATIC unsigned long ctxUuidHashCB (const void *k1) {
-    unsigned long hash;
-    
-    AFB_clientCtx *ctx = (AFB_clientCtx*) k1;
-    hash = lh_char_hash(ctx->uuid);
-    return (hash);    
-}
 
-// Compare client UUIDs within table
-STATIC int ctxUuidCompCB (const void *k1, const void *k2) {
-    int res;    
-    AFB_clientCtx *ctx1 = (AFB_clientCtx*) k1;
-    AFB_clientCtx *ctx2 = (AFB_clientCtx*) k2;
-    
-    res = lh_char_equal(ctx1->uuid, ctx2->uuid);
-    return (res);    
-}
 
 // Free context [XXXX Should be protected again memory abort XXXX]
-STATIC void ctxUuidFreeCB (struct lh_entry *entry) {
-    AFB_clientCtx *client = (AFB_clientCtx*) entry->v;
-
+STATIC void ctxUuidFreeCB (AFB_clientCtx *client) {
+  
     // If application add a handle let's free it now
     if (client->ctx != NULL) {
         
@@ -341,41 +322,68 @@ STATIC void ctxUuidFreeCB (struct lh_entry *entry) {
         if (client->plugin->freeCtxCB == NULL) free (client->ctx); 
         else if (client->plugin->freeCtxCB != (void*)-1) client->plugin->freeCtxCB(client); 
     }
-    free ((void*)entry->v);
 }
 
 // Create a new store in RAM, not that is too small it will be automatically extended
-STATIC struct lh_table *ctxStoreCreate (int nbSession) {
-   lh_table *table; 
+PUBLIC void ctxStoreInit (int nbSession) {
+   int res; 
+   // let's create session hash table
+   res = hcreate_r(nbSession, &sessions);
+}
+
+STATIC AFB_clientCtx *ctxStoreSearch (const char* uuid) {
+    ENTRY item = {(char*) uuid};
+    ENTRY *pitem = &item;
+    // printf ("searching uuid=%s\n", uuid);
     
-   // function will exit process in case of error !!! 
-   table=lh_table_new (nbSession, "CtxClient", ctxUuidFreeCB, ctxUuidHashCB, ctxUuidCompCB);
-   return (table);
+    pthread_mutex_lock(&mutexHash);
+    if (hsearch_r(item, FIND, &pitem, &sessions)) {
+        pthread_mutex_unlock(&mutexHash);
+        return  (AFB_clientCtx*) pitem->data;
+    }
+    pthread_mutex_unlock(&mutexHash);
+    return NULL;
+}
+
+// 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;
+    }
+    pthread_mutex_unlock(&mutexHash);
+}
+
+void ctxStoreDel (AFB_clientCtx *client) {
+    ENTRY item = {client->uuid};
+    ENTRY *pitem = &item;
+
+    pthread_mutex_lock(&mutexHash);
+    if (hsearch_r(item, FIND, &pitem, &sessions)) {
+        pitem->data = NULL;
+    }
+    pthread_mutex_unlock(&mutexHash);
 }
 
 // Check if context timeout or not
 STATIC int ctxStoreToOld (const void *k1, int timeout) {
-    int res;    
+    int res;
     AFB_clientCtx *ctx = (AFB_clientCtx*) k1;
-
-    res = ((ctx->timeStamp + timeout) < time(NULL));
+    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) {
-    struct lh_entry *c;
-    
-    // Loop on every entry within table
-    for(c = lht->head; c != NULL; c = c->next) {
-        if(lht->free_fn) {
-            if(c->k == LH_EMPTY) return lht->count;
-            if(c->k != LH_FREED &&  ctxStoreToOld(c->v, timeout)) lh_table_delete_entry (lht, c);
-       }
-    }
+    if (verbose) fprintf (stderr, "****** Garbage Count=%d timeout=%d\n", lht->count, timeout);
+
   
-    // return current size after cleanup
-    return (lht->count);
 }
 
 // This function will return exiting client context or newly created client context
@@ -387,11 +395,6 @@ PUBLIC AFB_error ctxClientGet (AFB_request *request, AFB_plugin *plugin) {
   int ret;
   
     if (request->config->token == NULL) return AFB_EMPTY;
-  
-    // if client session store is null create it
-    if (clientCtxs == NULL) {
-       clientCtxs= ctxStoreCreate(CTX_NBCLIENTS);
-    }
 
     // Check if client as a context or not inside the URL
     uuid  = MHD_lookup_connection_value(request->connection, MHD_GET_ARGUMENT_KIND, "uuid");
@@ -403,32 +406,34 @@ PUBLIC AFB_error ctxClientGet (AFB_request *request, AFB_plugin *plugin) {
         uuid = MHD_lookup_connection_value (request->connection, MHD_COOKIE_KIND, COOKIE_NAME);  
     };
     
-    
-    if (uuid != NULL)   {
+    // Warning when no cookie defined MHD_lookup_connection_value may return something !!!
+    if ((uuid != NULL) && (strnlen (uuid, 10) >= 10))   {
+        int search;
         // search if client context exist and it not timeout let's use it
-       if ((lh_table_lookup_ex (clientCtxs, uuid, (void**) &clientCtx)) 
-                && ! ctxStoreToOld (clientCtx, request->config->cntxTimeout)) {
-                request->client=clientCtx;
-                if (verbose) fprintf (stderr, "ctxClientGet Old uuid=[%s] token=[%s] timestamp=%d\n"
-                             ,request->client->uuid, request->client->token, request->client->timeStamp);
-                return;            
+        printf ("search old UID=%s\n", uuid);
+        clientCtx = ctxStoreSearch (uuid);
+
+       if (clientCtx && ! ctxStoreToOld (clientCtx, request->config->cntxTimeout)) {
+            request->client=clientCtx;
+            return;            
         }
     }
-
-    
+   
     // we have no session let's create one otherwise let's clean any exiting values
     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++;   // simple application uniqueID 
     clientCtx->plugin = plugin;    // provide plugin callbacks a hook to 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*0.5)) ctxStoreGarbage(clientCtxs, request->config->cntxTimeout);
+    // if(clientCtxs->count > (clientCtxs->size / 2)) ctxStoreGarbage(clientCtxs, request->config->cntxTimeout);
     
     // finally add uuid into hashtable
-    ret=lh_table_insert (clientCtxs, (void*)clientCtx->uuid, clientCtx);
-    if (ret < 0) return (AFB_FAIL);
+    ctxStoreAdd (clientCtx);
+    
+    // if (ret < 0) return (AFB_FAIL);
     
     if (verbose) fprintf (stderr, "ctxClientGet New uuid=[%s] token=[%s] timestamp=%d\n", clientCtx->uuid, clientCtx->token, clientCtx->timeStamp);      
     request->client = clientCtx;
@@ -459,16 +464,18 @@ PUBLIC AFB_error ctxTokenCheck (AFB_request *request) {
 
 // Free Client Session Context
 PUBLIC AFB_error ctxTokenReset (AFB_request *request) {
-    struct lh_entry* entry;
     int ret;
+    AFB_clientCtx *clientCtx;
 
     if (request->client == NULL) return AFB_EMPTY;
+    
+    // Search for an existing client with the same UUID
+    clientCtx = ctxStoreSearch (request->client->uuid);
+    if (clientCtx == NULL) return AFB_FALSE;
 
-    entry = lh_table_lookup_entry (clientCtxs, request->client->uuid);
-    if (entry == NULL) return AFB_FALSE;
+    // Remove client from table
+    ctxStoreDel (clientCtx);    
     
-    lh_table_delete_entry (clientCtxs, entry);
     return (AFB_SUCCESS);
 }
 
@@ -492,7 +499,6 @@ PUBLIC AFB_error ctxTokenCreate (AFB_request *request) {
         if (strcmp(request->config->token, token)) return AFB_UNAUTH;       
     }
     
-
     // create a UUID as token value
     uuid_generate(newuuid); 
     uuid_unparse_lower(newuuid, request->client->token);
@@ -514,17 +520,12 @@ PUBLIC AFB_error ctxTokenRefresh (AFB_request *request) {
     if (request->client == NULL) return AFB_EMPTY;
     
     // Check if the old token is valid
-    oldTnkValid= ctxTokenCheck (request);
+    if (ctxTokenCheck (request) != AFB_SUCCESS) return (AFB_FAIL);
+        
+    // Old token was valid let's regenerate a new one    
+    uuid_generate(newuuid);         // create a new UUID
+    uuid_unparse_lower(newuuid, request->client->token);
+    return (AFB_SUCCESS);    
     
-    // if token is not valid let check for query argument "oldornew"
-    if (!oldTnkValid) {
-        oldornew = MHD_lookup_connection_value(request->connection, MHD_GET_ARGUMENT_KIND, "oldornew");
-        if (oldornew != NULL) oldTnkValid= TRUE;
-    }
-   
-    // No existing token and no request to create one
-    if (oldTnkValid != TRUE) return AFB_WARNING;
-
-    return (ctxTokenCreate (request));
 }