work in progress
authorJosé Bollo <jose.bollo@iot.bzh>
Fri, 1 Apr 2016 14:20:12 +0000 (16:20 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Fri, 1 Apr 2016 14:20:12 +0000 (16:20 +0200)
Change-Id: I3df95def03bb26ca4d1a52f7cd94b0fb67375d4c
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
17 files changed:
CMakeLists.txt
include/local-def.h
include/proto-def.h
plugins/samples/ClientCtx.c
plugins/samples/HelloWorld.c
plugins/session/token-api.c
src/afb-apis.c
src/afb-hreq.c
src/afb-hreq.h
src/afb-req-itf.h
src/afb-rest-api.c
src/afb-websock.c
src/helper-api.c
src/http-svc.c
src/main.c
src/session.c
src/session.h

index d178078..15e7f7e 100644 (file)
@@ -84,7 +84,7 @@ INCLUDE(FindThreads)
 FIND_PACKAGE(Threads)
 
 SET(include_dirs ${INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include ${json-c_INCLUDE_DIRS} ${libmicrohttpd_INCLUDE_DIRS} ${uuid_INCLUDE_DIRS} ${dbus_INCLUDE_DIRS} ${alsa_INCLUDE_DIRS} ${pulseaudio_INCLUDE_DIRS} ${librtlsdr_INCLUDE_DIRS} ${gupnp_INCLUDE_DIRS} ${openssl_INCLUDE_DIRS})
-SET(link_libraries ${json-c_LIBRARIES} ${libmicrohttpd_LIBRARIES} ${uuid_LIBRARIES} ${dbus_LIBRARIES} ${alsa_LIBRARIES} ${pulseaudio_LIBRARIES} ${librtlsdr_LIBRARIES} ${gupnp_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${libefence_LIBRARIES} ${openssl_LIBRARIES} -lmagic -lm -ldl)
+SET(link_libraries ${json-c_LIBRARIES} ${libmicrohttpd_LIBRARIES} ${uuid_LIBRARIES} ${dbus_LIBRARIES} ${alsa_LIBRARIES} ${pulseaudio_LIBRARIES} ${librtlsdr_LIBRARIES} ${gupnp_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${libefence_LIBRARIES} ${openssl_LIBRARIES} -lmagic -lm -ldl -lrt)
 SET(plugin_install_dir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/afb)
 
 ADD_DEFINITIONS(-DPLUGIN_INSTALL_DIR="${plugin_install_dir}")
index 3f61871..605c05a 100644 (file)
 #ifndef LOCAL_DEF_H
 #define LOCAL_DEF_H
 
-#ifndef _GNU_SOURCE
-  #define _GNU_SOURCE
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <sys/signal.h>
-#include <sys/types.h>
-#include <time.h>
 #include <json.h>
-#include <microhttpd.h>
 #include <magic.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <uuid/uuid.h>
-
-
+#include <microhttpd.h>
 
 /* other definitions --------------------------------------------------- */
 
@@ -111,7 +91,7 @@ struct AFB_restapi
 {
        const char *name;
        enum AFB_sessionE session;
-       json_object* (*callback)();
+       struct json_object* (*callback)();
        const char *info;
 };
 
@@ -127,7 +107,7 @@ struct AFB_plugin
 
 typedef enum AFB_pluginE AFB_pluginE;
 typedef enum AFB_sessionE AFB_sessionE;
-typedef json_object* (*AFB_apiCB)();
+typedef struct json_object* (*AFB_apiCB)();
 typedef void (*AFB_freeCtxCB)(void*);
 typedef struct AFB_restapi AFB_restapi;
 typedef struct AFB_plugin AFB_plugin;
@@ -141,12 +121,12 @@ typedef struct AFB_plugin AFB_plugin;
 
 
 
+typedef enum  {AFB_MODE_LOCAL=0, AFB_MODE_REMOTE, AFB_MODE_GLOBAL} AFB_Mode;
 
 
-
+#if 0
 
 typedef enum  {AFB_POST_NONE=0, AFB_POST_JSON, AFB_POST_FORM, AFB_POST_EMPTY} AFB_PostType;
-typedef enum  {AFB_MODE_LOCAL=0, AFB_MODE_REMOTE, AFB_MODE_GLOBAL} AFB_Mode;
 
 
 
@@ -155,7 +135,7 @@ typedef struct {
    int   fd; 
    char *path; 
    int  errcode;
-   json_object* jresp;
+   struct json_object* jresp;
 } AFB_PostCtx;
 
 typedef  struct {
@@ -191,17 +171,19 @@ typedef struct {
   int   fd;
 } AFB_staticfile;
 
+typedef struct {
+     char    *msg;
+     size_t  len;
+} AFB_redirect_msg;
+
+#endif
+
 typedef struct {
   char  *url;
   char  *path;
   size_t len;
 } AFB_aliasdir;
 
-typedef struct {
-     char    *msg;
-     size_t  len;
-} AFB_redirect_msg;
-
 // main config structure
 struct AFB_config
 {
@@ -229,7 +211,7 @@ typedef struct {
 /*
   AFB_PostRequest *post;
 */
-  json_object *jresp;
+  struct json_object *jresp;
   void *context;             // Hold Client Context when using session
   int  restfull;             // request is resfull [uuid token provided]
   int  errcode;              // http error code
@@ -240,7 +222,8 @@ typedef struct {
 struct afb_hsrv_handler;
 struct MHD_Daemon;
 
-struct AFB_session {
+struct AFB_session
+{
   struct AFB_config  *config;   // pointer to current config
   // List of commands to execute
   int  background;        // run in backround mode
index c364035..e2190eb 100644 (file)
@@ -21,7 +21,7 @@
 
 // helper-api
 extern const char* getQueryValue (const AFB_request * request, const char *name);
-extern int getQueryAll(AFB_request * request, char *query, size_t len);
+extern size_t getQueryAll(AFB_request * request, char *query, size_t len);
 /*
 extern json_object* getPostFile (AFB_request *request, AFB_PostItem *item, char* destination) ;
 extern char* getPostPath (AFB_request *request);
@@ -29,12 +29,6 @@ extern char* getPostPath (AFB_request *request);
 
 extern json_object *jsonNewMessage (AFB_error level, char* format, ...);
 
-// rest-api
-extern void endPostRequest(AFB_PostHandle *posthandle); 
-extern int doRestApi(struct MHD_Connection *connection, AFB_session *session, const char* url, const char *method
-    , const char *upload_data, size_t *upload_data_size, void **con_cls);
-
-
 
 // Httpd server
 extern AFB_error httpdStart          (AFB_session *session);
index b59400e..175b938 100644 (file)
@@ -16,6 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdio.h>
 
 #include "local-def.h"
 
index 6c2d0cf..85e92f4 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdio.h>
+#include <string.h>
 
 #include "local-def.h"
+#include "afb-req-itf.h"
 
-STATIC json_object* pingSample (AFB_request *request) {
+static json_object* pingSample (AFB_request *request) {
     static int pingcount = 0;
     json_object *response;
     char query [512];
-    int len;
+    size_t len;
 
     // request all query key/value
     len = getQueryAll (request, query, sizeof(query));
     if (len == 0) strcpy (query,"NoSearchQueryList");
     
     // return response to caller
-    response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon %d query={%s}", pingcount++, query);
+//    response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon %d query={%s}", pingcount++, query);
+    afb_req_success_f(*request->areq, NULL, "Ping Binder Daemon %d query={%s}", pingcount++, query);
     
     if (verbose) fprintf(stderr, "%d: \n", pingcount);
-    return (response);
+    return NULL; //(response);
 }
 
-STATIC json_object* pingFail (AFB_request *request) {
+static json_object* pingFail (AFB_request *request) {
     return NULL;
 }
 
-STATIC json_object* pingBug (AFB_request *request) {
+static json_object* pingBug (AFB_request *request) {
     int a,b,c;
     
     fprintf (stderr, "Use --timeout=10 to trap error\n");
@@ -54,7 +58,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_request *request) {
+static json_object* pingJson (AFB_request *request) {
     json_object *jresp, *embed;    
     
     jresp = json_object_new_object();
@@ -72,7 +76,7 @@ STATIC json_object* pingJson (AFB_request *request) {
 
 // NOTE: this sample does not use session to keep test a basic as possible
 //       in real application most APIs should be protected with AFB_SESSION_CHECK
-STATIC  AFB_restapi pluginApis[]= {
+static  AFB_restapi pluginApis[]= {
   {"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"},
@@ -80,12 +84,13 @@ STATIC  AFB_restapi pluginApis[]= {
   {NULL}
 };
 
+static const AFB_plugin plugin = {
+       .type = AFB_PLUGIN_JSON,
+       .info = "Minimal Hello World Sample",
+       .prefix = "hello",
+       .apis = pluginApis
+};
 
-PUBLIC AFB_plugin *pluginRegister () {
-    AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
-    plugin->type  = AFB_PLUGIN_JSON;
-    plugin->info  = "Minimal Hello World Sample";
-    plugin->prefix= "hello";
-    plugin->apis  = pluginApis;
-    return (plugin);
+const AFB_plugin *pluginRegister () {
+    return &plugin;
 };
index 9a07832..feb269d 100644 (file)
@@ -16,6 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdio.h>
 
 #include "local-def.h"
 
index 856e3f5..effef8a 100644 (file)
 #include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/syscall.h>
+#include <setjmp.h>
 
 #include "../include/local-def.h"
 
@@ -279,36 +283,56 @@ int afb_apis_add_pathset(const char *pathset)
        };
 }
 
-/*
 // Check of apiurl is declare in this plugin and call it
 extern __thread sigjmp_buf *error_handler;
 static int callPluginApi(AFB_request * request)
 {
+       volatile int status, timerset;
+       timer_t timerid;
        sigjmp_buf jmpbuf, *older;
+       struct sigevent sevp;
+       struct itimerspec its;
 
        // save context before calling the API
+       timerset = 0;
+       older = error_handler;
        status = setjmp(jmpbuf);
        if (status != 0) {
-               return 0;
+               status = 0;
        }
+       else {
+               error_handler = &jmpbuf;
+               if (request->config->apiTimeout > 0) {
+                       timerset = 1; /* TODO: check statuses */
+                       sevp.sigev_notify = SIGEV_THREAD_ID;
+                       sevp.sigev_signo = SIGALRM;
+#if defined(sigev_notify_thread_id)
+                       sevp.sigev_notify_thread_id = syscall(SYS_gettid);
+#else
+                       sevp._sigev_un._tid = syscall(SYS_gettid);
+#endif
+                       timer_create(CLOCK_THREAD_CPUTIME_ID, &sevp, &timerid);
+                       its.it_interval.tv_sec = 0;
+                       its.it_interval.tv_nsec = 0;
+                       its.it_value.tv_sec = 15;
+                       its.it_value.tv_nsec = 0;
+                       timer_settime(timerid, 0, &its, NULL);
+               }
 
-       // Trigger a timer to protect from unacceptable long time execution
-       if (request->config->apiTimeout > 0)
-               alarm((unsigned)request->config->apiTimeout);
-
-       older = error_handler;
-       error_handler = &jmpbuf;
-       doCallPluginApi(request, apiidx, verbidx, context);
+               //doCallPluginApi(request, apiidx, verbidx, context);
+               status = 1;
+       }
+       if (timerset)
+               timer_delete(timerid);
        error_handler = older;
 
-       // cancel timeout and plugin signal handle before next call
-       alarm(0);
-       return 1;
+       return status;
 }
-*/
 
 static void handle(struct afb_req req, const struct api_desc *api, const struct AFB_restapi *verb)
 {
+       json_object *jresp, *jcall, *jreqt;
+
        AFB_request request;
 
        request.uuid = request.url = "fake";
@@ -336,7 +360,7 @@ static void handle(struct afb_req req, const struct api_desc *api, const struct
        verb->callback(&request, NULL);
 
        if (verb->session == AFB_SESSION_CLOSE)
-               /*del*/;
+               /*close*/;
 }
 
 int afb_apis_handle(struct afb_req req, const char *api, size_t lenapi, const char *verb, size_t lenverb)
index 506091c..58dbb04 100644 (file)
  */
 
 #define _GNU_SOURCE
-#include <microhttpd.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include <assert.h>
-#include <poll.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
-#include "../include/local-def.h"
+#include <microhttpd.h>
+
+#include "local-def.h"
 #include "afb-method.h"
 #include "afb-req-itf.h"
 #include "afb-hreq.h"
@@ -36,13 +42,19 @@ struct hreq_data {
        char *value;
 };
 
-static struct afb_arg getarg(struct afb_hreq *hreq, const char *name);
-static void iterargs(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure);
+static struct afb_arg req_get(struct afb_hreq *hreq, const char *name);
+static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure);
+static void req_fail(struct afb_hreq *hreq, const char *status, const char *info);
+static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info);
 
 static const struct afb_req_itf afb_hreq_itf = {
-       .get = (void*)getarg,
-       .iterate = (void*)iterargs
+       .get = (void*)req_get,
+       .iterate = (void*)req_iterate,
+       .fail = (void*)req_fail,
+       .success = (void*)req_success
 };
+       void (*fail)(void *data, const char *status, const char *info);
+       void (*success)(void *data, json_object *obj, const char *info);
 
 static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create)
 {
@@ -163,12 +175,20 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f
        struct MHD_Response *response;
 
        /* Opens the file or directory */
-       fd = openat(dirfd, filename, O_RDONLY);
-       if (fd < 0) {
-               if (errno == ENOENT)
-                       return 0;
-               afb_hreq_reply_error(hreq, MHD_HTTP_FORBIDDEN);
-               return 1;
+       if (filename[0]) {
+               fd = openat(dirfd, filename, O_RDONLY);
+               if (fd < 0) {
+                       if (errno == ENOENT)
+                               return 0;
+                       afb_hreq_reply_error(hreq, MHD_HTTP_FORBIDDEN);
+                       return 1;
+               }
+       } else {
+               fd = dup(dirfd);
+               if (fd < 0) {
+                       afb_hreq_reply_error(hreq, MHD_HTTP_INTERNAL_SERVER_ERROR);
+                       return 1;
+               }
        }
 
        /* Retrieves file's status */
@@ -354,33 +374,7 @@ struct afb_req afb_hreq_to_req(struct afb_hreq *hreq)
        return (struct afb_req){ .itf = &afb_hreq_itf, .data = hreq };
 }
 
-struct iterator_data
-{
-       struct afb_hreq *hreq;
-       int (*iterator)(void *closure, const char *key, const char *value, int isfile);
-       void *closure;
-};
-
-static int itargs(struct iterator_data *id, enum MHD_ValueKind kind, const char *key, const char *value)
-{
-       if (get_data(id->hreq, key, 0))
-               return 1;
-       return id->iterator(id->closure, key, value, 0);
-}
-
-void afb_hreq_iterate_arguments(struct afb_hreq *hreq, int (*iterator)(void *closure, const char *key, const char *value, int isfile), void *closure)
-{
-       struct iterator_data id = { .hreq = hreq, .iterator = iterator, .closure = closure };
-       struct hreq_data *data = hreq->data;
-       while (data) {
-               if (!iterator(closure, data->key, data->value, !!data->file))
-                       return;
-               data = data->next;
-       }
-       MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)itargs, &id);
-}
-
-static struct afb_arg getarg(struct afb_hreq *hreq, const char *name)
+static struct afb_arg req_get(struct afb_hreq *hreq, const char *name)
 {
        struct hreq_data *hdat = get_data(hreq, name, 0);
        if (hdat)
@@ -418,7 +412,7 @@ static int _iterargs_(struct iterdata *id, enum MHD_ValueKind kind, const char *
        });
 }
 
-static void iterargs(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure)
+static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure)
 {
        struct iterdata id = { .hreq = hreq, .iterator = iterator, .closure = closure };
        struct hreq_data *hdat = hreq->data;
@@ -445,4 +439,39 @@ void afb_hreq_drop_data(struct afb_hreq *hreq)
                data = hreq->data;
        }
 }
+static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max)
+{
+       ssize_t len = stpncpy(buf, json_object_to_json_string(obj)+pos, max) - buf;
+       return len ? : -1;
+}
+
+static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *status, const char *info, json_object *resp)
+{
+       json_object *root, *request;
+       struct MHD_Response *response;
+
+       root = json_object_new_object();
+       json_object_object_add(root, "jtype", json_object_new_string("afb-reply"));
+       request = json_object_new_object();
+       json_object_object_add(root, "request", request);
+       json_object_object_add(request, "status", json_object_new_string(status));
+       if (info)
+               json_object_object_add(request, "info", json_object_new_string(info));
+       if (resp)
+               json_object_object_add(root, "response", resp);
+
+       response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 65500, (void*)send_json_cb, root, (void*)json_object_put);
+       MHD_queue_response(hreq->connection, retcode, response);
+       MHD_destroy_response(response);
+}
+
+static void req_fail(struct afb_hreq *hreq, const char *status, const char *info)
+{
+       req_reply(hreq, MHD_HTTP_OK, status, info, NULL);
+}
+
+static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info)
+{
+       req_reply(hreq, MHD_HTTP_OK, "success", info, obj);
+}
 
index 01409a5..fb914f1 100644 (file)
  * limitations under the License.
  */
 
+struct AFB_session;
 
 struct afb_hreq {
-       AFB_session *session;
+       struct AFB_session *session;
        struct MHD_Connection *connection;
        enum afb_method method;
        const char *version;
@@ -60,5 +61,3 @@ extern struct afb_req afb_hreq_to_req(struct afb_hreq *hreq);
 
 extern void afb_hreq_drop_data(struct afb_hreq *hreq);
 
-extern void afb_hreq_iterate_arguments(struct afb_hreq *hreq, int (*iterator)(void *closure, const char *key, const char *value, int isfile), void *closure);
-
index ab72a5c..eea7831 100644 (file)
@@ -25,6 +25,8 @@ struct afb_arg {
 struct afb_req_itf {
        struct afb_arg (*get)(void *data, const char *name);
        void (*iterate)(void *data, int (*iterator)(void *closure, struct afb_arg arg), void *closure);
+       void (*fail)(void *data, const char *status, const char *info);
+       void (*success)(void *data, json_object *obj, const char *info);
 };
 
 struct afb_req {
@@ -52,3 +54,51 @@ static inline void afb_req_iterate(struct afb_req req, int (*iterator)(void *clo
        req.itf->iterate(req.data, iterator, closure);
 }
 
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static inline void afb_req_fail(struct afb_req req, const char *status, const char *info)
+{
+       req.itf->fail(req.data, status, info);
+}
+
+static inline void afb_req_fail_v(struct afb_req req, const char *status, const char *info, va_list args)
+{
+       char *message;
+       if (info == NULL || vasprintf(&message, info, args) < 0)
+               message = NULL;
+       afb_req_fail(req, status, message);
+       free(message);
+}
+
+static inline void afb_req_fail_f(struct afb_req req, const char *status, const char *info, ...)
+{
+       va_list args;
+       va_start(args, info);
+       afb_req_fail_v(req, status, info, args);
+       va_end(args);
+}
+
+static inline void afb_req_success(struct afb_req req, json_object *obj, const char *info)
+{
+       req.itf->success(req.data, obj, info);
+}
+
+static inline void afb_req_success_v(struct afb_req req, json_object *obj, const char *info, va_list args)
+{
+       char *message;
+       if (info == NULL || vasprintf(&message, info, args) < 0)
+               message = NULL;
+       afb_req_success(req, obj, message);
+       free(message);
+}
+
+static inline void afb_req_success_f(struct afb_req req, json_object *obj, const char *info, ...)
+{
+       va_list args;
+       va_start(args, info);
+       afb_req_success_v(req, obj, info, args);
+       va_end(args);
+}
+
index 80de7d6..28346b1 100644 (file)
@@ -82,8 +82,7 @@ static AFB_error doCallPluginApi(AFB_request * request, int apiidx, int verbidx,
                clientCtx = ctxClientGet(request);
                if (clientCtx == NULL) {
                        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_add_status(jcall, "fail", "Client Session Context Full !!!");
                        json_object_object_add(jreqt, "request", jcall);
                        goto ExitOnDone;
                }
@@ -98,16 +97,14 @@ static AFB_error doCallPluginApi(AFB_request * request, int apiidx, int verbidx,
                case AFB_SESSION_CREATE:
                        if (clientCtx->token[0] != '\0' && request->config->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_add_status(jcall, "exist", "AFB_SESSION_CREATE Session already exist");
                                json_object_object_add(jreqt, "request", jcall);
                                goto ExitOnDone;
                        }
 
                        if (AFB_SUCCESS != ctxTokenCreate(clientCtx, 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_add_status(jcall, "fail", "AFB_SESSION_CREATE Invalid Initial Token");
                                json_object_object_add(jreqt, "request", jcall);
                                goto ExitOnDone;
                        } else {
@@ -120,8 +117,7 @@ static AFB_error doCallPluginApi(AFB_request * request, int apiidx, int verbidx,
                case AFB_SESSION_RENEW:
                        if (AFB_SUCCESS != ctxTokenRefresh(clientCtx, 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_add_status(jcall, "fail", "AFB_SESSION_REFRESH Broken Exchange Token Chain");
                                json_object_object_add(jreqt, "request", jcall);
                                goto ExitOnDone;
                        } else {
@@ -134,8 +130,7 @@ static AFB_error doCallPluginApi(AFB_request * request, int apiidx, int verbidx,
                case AFB_SESSION_CLOSE:
                        if (AFB_SUCCESS != ctxTokenCheck(clientCtx, 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_add_status(jcall, "fail", "AFB_SESSION_CLOSE Not a Valid Access Token"));
                                json_object_object_add(jreqt, "request", jcall);
                                goto ExitOnDone;
                        } else {
@@ -148,8 +143,7 @@ static AFB_error doCallPluginApi(AFB_request * request, int apiidx, int verbidx,
                        // default action is check
                        if (AFB_SUCCESS != ctxTokenCheck(clientCtx, 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_add_status(jcall, "fail", "AFB_SESSION_CHECK Invalid Active Token"));
                                json_object_object_add(jreqt, "request", jcall);
                                goto ExitOnDone;
                        }
index 23d489a..b9417cb 100644 (file)
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <sys/uio.h>
+#include <string.h>
 
 #include <openssl/sha.h>
 #include <openssl/bio.h>
@@ -29,7 +30,7 @@
 
 #include "websock.h"
 
-#include "../include/local-def.h"
+#include "local-def.h"
 
 #include "afb-method.h"
 #include "afb-hreq.h"
index fd42c48..1e3d882 100644 (file)
  * 
  */
 
-#include "../include/local-def.h"
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+/*
 #include <dirent.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <stdarg.h>
+*/
 
+#include "local-def.h"
 #include "afb-req-itf.h"
 
 // handle to hold queryAll values
@@ -56,19 +63,19 @@ const char* getQueryValue(const AFB_request * request, const char *name) {
 static int getQueryCB (queryHandleT *query, struct afb_arg arg) {
     if (query->idx >= query->len)
        return 0;
-    query->idx += snprintf (&query->msg[query->idx], query->len-query->idx, " %s: %s\'%s\',", arg.name, arg.is_file?"FILE=":"", arg.value);
+    query->idx += (unsigned)snprintf (&query->msg[query->idx], query->len-query->idx, " %s: %s\'%s\',", arg.name, arg.is_file?"FILE=":"", arg.value);
     return 1; /* continue to iterate */
 }
 
 // Helper to retrieve argument from  connection
-int getQueryAll(AFB_request * request, char *buffer, size_t len) {
+size_t getQueryAll(AFB_request * request, char *buffer, size_t len) {
     queryHandleT query;
     buffer[0] = '\0'; // start with an empty string
     query.msg = buffer;
     query.len = len;
     query.idx = 0;
 
-    afb_req_iterate(*request->areq, getQueryCB, &query);
+    afb_req_iterate(*request->areq, (void*)getQueryCB, &query);
     buffer[len-1] = 0;
     return query.idx >= len ? len - 1 : query.idx;
 }
@@ -217,6 +224,41 @@ static void jsoninit()
 }
 
 
+// build an ERROR message and return it as a valid json object
+json_object *json_add_status (json_object *obj, const char *status, const char *info)
+{
+       if (obj == NULL)
+               obj = json_object_new_object();
+       json_object_object_add(obj, "status", json_object_new_string(status));
+       if (info)
+               json_object_object_add(obj, "info", json_object_new_string(info));
+       return obj;
+}
+
+// build an ERROR message and return it as a valid json object
+json_object *json_add_status_v (json_object *obj, const char *status, const char *info, va_list args)
+{
+       char *message;
+       if (info == NULL || vasprintf(&message, info, args) < 0)
+               message = NULL;
+       obj = json_add_status(obj, status, message);
+       free(message);
+       return obj;
+}
+
+
+// build an ERROR message and return it as a valid json object
+json_object *json_add_status_f (json_object *obj, const char *status, const char *info, ...)
+{
+       va_list args;
+       va_start(args, info);
+       obj = json_add_status_v(obj, status, info, args);
+       va_end(args);
+       return obj;
+}
+
+
+
 // build an ERROR message and return it as a valid json object
 struct json_object *jsonNewMessage (AFB_error level, char* format, ...) {
    static int count = 0;
@@ -252,3 +294,20 @@ struct json_object *jsonNewMessage (AFB_error level, char* format, ...) {
    return (AFBResponse);
 }
 
+#if 0
+{
+  jtype: "AFB_message"
+  request:
+    {
+      prefix: "",
+      api: "",
+      status: "", /* exist, fail, empty, null, processed */
+      info: "",
+      uuid: "",
+      token: "",
+      timeout: ""
+    }
+  response: ...
+}
+#endif
+
index 706abbc..9235bf8 100644 (file)
  */
 
 #define _GNU_SOURCE
-#include <microhttpd.h>
+
+#include <stdio.h>
+#include <string.h>
 #include <assert.h>
 #include <poll.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
-#include "../include/local-def.h"
+#include <microhttpd.h>
+
+#include "local-def.h"
 #include "afb-method.h"
 #include "afb-hreq.h"
 #include "afb-websock.h"
@@ -146,7 +151,7 @@ static struct AFB_clientCtx *afb_hreq_context(struct afb_hreq *hreq)
                        uuid = afb_hreq_get_argument(hreq, uuid_arg);
                if (uuid == NULL)
                        uuid = afb_hreq_get_cookie(hreq, uuid_cookie);
-               hreq->context = _ctxClientGet(uuid);
+               hreq->context = ctxClientGet(uuid);
        }
        return hreq->context;
 }
index a602af9..2401043 100644 (file)
  * limitations under the License.
  */
 
-#include <syslog.h>
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
 #include <setjmp.h>
 #include <signal.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <pthread.h>
+#include <syslog.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+/*
+#include <pwd.h>
+#include <pthread.h>
+*/
+
 #include "local-def.h"
 #include "afb-apis.h"
 #include "session.h"
@@ -427,10 +434,10 @@ static void signalError(int signum)
        sigset_t sigset;
 
        // unlock signal to allow a new signal to come
-       sigemptyset(&sigset);
-       sigaddset(&sigset, signum);
-       sigprocmask(SIG_UNBLOCK, &sigset, 0);
        if (error_handler != NULL) {
+               sigemptyset(&sigset);
+               sigaddset(&sigset, signum);
+               sigprocmask(SIG_UNBLOCK, &sigset, 0);
                longjmp(*error_handler, signum);
        }
 }
index eded141..ad41123 100644 (file)
  *
  */
 
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uuid/uuid.h>
+#include <assert.h>
+
 
-#include "local-def.h"
+/*
 #include <dirent.h>
 #include <string.h>
-#include <time.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <pthread.h>
 #include <search.h>
 #include <assert.h>
+*/
 
 #include "afb-apis.h"
 #include "session.h"
@@ -103,7 +111,7 @@ found:
     return client;
 }
 
-static AFB_error ctxStoreDel (AFB_clientCtx *client)
+static int ctxStoreDel (AFB_clientCtx *client)
 {
     int idx;
     int status;
@@ -117,22 +125,22 @@ static AFB_error ctxStoreDel (AFB_clientCtx *client)
                sessions.store[idx]=NULL;
                sessions.count--;
                ctxUuidFreeCB (client);
-               status = AFB_SUCCESS;
+               status = 1;
                goto deleted;
        }
     }
-    status = AFB_FAIL;
+    status = 0;
 deleted:
     pthread_mutex_unlock(&sessions.mutex);
     return status;
 }
 
-static AFB_error ctxStoreAdd (AFB_clientCtx *client)
+static int ctxStoreAdd (AFB_clientCtx *client)
 {
     int idx;
     int status;
-    if (client == NULL)
-       return AFB_FAIL;
+
+    assert (client != NULL);
 
     //fprintf (stderr, "ctxStoreAdd request uuid=%s count=%d\n", client->uuid, sessions.count);
 
@@ -142,12 +150,11 @@ static AFB_error ctxStoreAdd (AFB_clientCtx *client)
         if (NULL == sessions.store[idx]) {
                sessions.store[idx]= client;
                sessions.count++;
-               status = AFB_SUCCESS;
+               status = 1;
                goto added;
        }
     }
-    status = AFB_FAIL;
-
+    status = 0;
 added:
     pthread_mutex_unlock(&sessions.mutex);
     return status;
@@ -169,241 +176,14 @@ void ctxStoreGarbage ()
     // 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) && (ctxStoreTooOld(ctx, now))) {
+        if (ctx != NULL && ctxStoreTooOld(ctx, now)) {
             ctxStoreDel (ctx);
         }
     }
 }
 
 // This function will return exiting client context or newly created client context
-AFB_clientCtx *ctxClientGet (AFB_request *request)
-{
-  AFB_clientCtx *clientCtx=NULL;
-  const char *uuid;
-  uuid_t newuuid;
-
-    if (request->config->token == NULL) return NULL;
-
-    // Check if client as a context or not inside the URL
-    uuid  = NULL; //MHD_lookup_connection_value(request->connection, MHD_GET_ARGUMENT_KIND, key_uuid);
-
-    // if UUID in query we're restfull with no cookies otherwise check for cookie
-    if (uuid != NULL)
-        request->restfull = TRUE;
-    else {
-        char cookie[64];
-        request->restfull = FALSE;
-        snprintf(cookie, sizeof cookie, "%s-%d", COOKIE_NAME, request->config->httpdPort);
-        uuid = NULL; //MHD_lookup_connection_value (request->connection, MHD_COOKIE_KIND, cookie);
-    };
-
-    // Warning when no cookie defined MHD_lookup_connection_value may return something !!!
-    if ((uuid != NULL) && (strnlen (uuid, 10) >= 10))   {
-        // search if client context exist and it not timeout let's use it
-        clientCtx = ctxStoreSearch (uuid);
-
-       if (clientCtx) {
-            if (ctxStoreTooOld (clientCtx, NOW)) {
-                 // this session is too old let's delete it
-                ctxStoreDel (clientCtx);
-                clientCtx = NULL;
-            } else {
-                return clientCtx;
-            }
-        }
-    }
-
-    // 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
-        clientCtx->contexts = calloc ((unsigned)sessions.apicount, sizeof (void*));
-    }
-
-    uuid_generate(newuuid);         // create a new UUID
-    uuid_unparse_lower(newuuid, clientCtx->uuid);
-
-    // if table is full at 50% let's clean it up
-    if(sessions.count > (sessions.max / 2)) ctxStoreGarbage();
-
-    // finally add uuid into hashtable
-    if (AFB_SUCCESS != ctxStoreAdd (clientCtx)) {
-        free (clientCtx);
-        return NULL;
-    }
-    return clientCtx;
-}
-
-// Sample Generic Ping Debug API
-AFB_error ctxTokenCheck (AFB_clientCtx *clientCtx, AFB_request *request)
-{
-    const char *token;
-
-    if (clientCtx->contexts == NULL)
-       return AFB_EMPTY;
-
-    // this time have to extract token from query list
-    token = NULL; //MHD_lookup_connection_value(request->connection, MHD_GET_ARGUMENT_KIND, key_token);
-
-    // if not token is providing we refuse the exchange
-    if ((token == NULL) || (clientCtx->token == NULL))
-       return AFB_FALSE;
-
-    // compare current token with previous one
-    if ((0 == strcmp (token, clientCtx->token)) && (!ctxStoreTooOld (clientCtx, NOW))) {
-       return AFB_SUCCESS;
-    }
-
-    // Token is not valid let move level of assurance to zero and free attached client handle
-    return AFB_FAIL;
-}
-
-// Free Client Session Context
-AFB_error ctxTokenReset (AFB_clientCtx *clientCtx, AFB_request *request)
-{
-    if (clientCtx == NULL)
-       return AFB_EMPTY;
-    //if (verbose) fprintf (stderr, "ctxClientReset New uuid=[%s] token=[%s] timestamp=%d\n", clientCtx->uuid, clientCtx->token, clientCtx->timeStamp);
-
-    // Search for an existing client with the same UUID
-    clientCtx = ctxStoreSearch (clientCtx->uuid);
-    if (clientCtx == NULL)
-       return AFB_FALSE;
-
-    // Remove client from table
-    ctxStoreDel (clientCtx);
-
-    return AFB_SUCCESS;
-}
-
-// generate a new token
-AFB_error ctxTokenCreate (AFB_clientCtx *clientCtx, AFB_request *request)
-{
-    uuid_t newuuid;
-    const char *token;
-
-    if (clientCtx == NULL)
-       return AFB_EMPTY;
-
-    // if config->token!="" then verify that we have the right initial share secret
-    if (request->config->token[0] != '\0') {
-
-        // check for initial token secret and return if not presented
-        token = NULL; //MHD_lookup_connection_value(request->connection, MHD_GET_ARGUMENT_KIND, key_token);
-        if (token == NULL)
-           return AFB_UNAUTH;
-
-        // verify that it fits with initial tokens fit
-        if (strcmp(request->config->token, token))
-           return AFB_UNAUTH;
-    }
-
-    // create a UUID as token value
-    uuid_generate(newuuid);
-    uuid_unparse_lower(newuuid, clientCtx->token);
-
-    // keep track of time for session timeout and further clean up
-    clientCtx->timeStamp = time(NULL) + sessions.timeout;
-
-    // Token is also store in context but it might be convenient for plugin to access it directly
-    return AFB_SUCCESS;
-}
-
-
-// generate a new token and update client context
-AFB_error ctxTokenRefresh (AFB_clientCtx *clientCtx, AFB_request *request)
-{
-    uuid_t newuuid;
-
-    if (clientCtx == NULL)
-        return AFB_EMPTY;
-
-    // Check if the old token is valid
-    if (ctxTokenCheck (clientCtx, 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, clientCtx->token);
-
-    // keep track of time for session timeout and further clean up
-    clientCtx->timeStamp = time(NULL) + sessions.timeout;
-
-    return AFB_SUCCESS;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// This function will return exiting client context or newly created client context
-AFB_clientCtx *_ctxClientGet (const char *uuid)
+AFB_clientCtx *ctxClientGet (const char *uuid)
 {
        uuid_t newuuid;
        AFB_clientCtx *clientCtx;
@@ -434,7 +214,7 @@ AFB_clientCtx *_ctxClientGet (const char *uuid)
                        uuid_unparse_lower(newuuid, clientCtx->uuid);
                        clientCtx->timeStamp = time(NULL) + sessions.timeout;
                        strcpy(clientCtx->token, sessions.initok);
-                       if (AFB_SUCCESS == ctxStoreAdd (clientCtx))
+                       if (ctxStoreAdd (clientCtx))
                                return clientCtx;
                        free(clientCtx->contexts);
                }
@@ -444,32 +224,32 @@ AFB_clientCtx *_ctxClientGet (const char *uuid)
 }
 
 // Free Client Session Context
-AFB_error _ctxClientDel (AFB_clientCtx *clientCtx)
+int ctxClientClose (AFB_clientCtx *clientCtx)
 {
        assert(clientCtx != NULL);
        return ctxStoreDel (clientCtx);
 }
 
 // Sample Generic Ping Debug API
-AFB_error _ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token)
+int ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token)
 {
        assert(clientCtx != NULL);
        assert(token != NULL);
 
        // compare current token with previous one
        if (ctxStoreTooOld (clientCtx, NOW))
-               return AFB_FAIL;
+               return 0;
        if (!clientCtx->token[0] || 0 == strcmp (token, clientCtx->token)) {
                clientCtx->timeStamp = time(NULL) + sessions.timeout;
-               return AFB_SUCCESS;
+               return 1;
        }
 
        // Token is not valid let move level of assurance to zero and free attached client handle
-       return AFB_FAIL;
+       return 0;
 }
 
 // generate a new token and update client context
-AFB_error _ctxTokenNew (AFB_clientCtx *clientCtx)
+int ctxTokenNew (AFB_clientCtx *clientCtx)
 {
        uuid_t newuuid;
 
@@ -482,6 +262,6 @@ AFB_error _ctxTokenNew (AFB_clientCtx *clientCtx)
        // keep track of time for session timeout and further clean up
        clientCtx->timeStamp = time(NULL) + sessions.timeout;
 
-       return AFB_SUCCESS;
+       return 1;
 }
 
index 0862b37..9b54179 100644 (file)
 struct AFB_clientCtx
 {
   time_t timeStamp;     // last time token was refresh
-  int   restfull;       // client does not use cookie
   void **contexts;      // application specific context [one per plugin]]
   char uuid[37];        // long term authentication of remote client
   char token[37];       // short term authentication of remote client
 };
 typedef struct AFB_clientCtx AFB_clientCtx;
 
-/*
-extern AFB_error ctxTokenRefresh (AFB_clientCtx *clientCtx, AFB_request *request);
-extern AFB_error ctxTokenCreate (AFB_clientCtx *clientCtx, AFB_request *request);
-extern AFB_error ctxTokenCheck (AFB_clientCtx *clientCtx, AFB_request *request);
-extern AFB_error ctxTokenReset (AFB_clientCtx *clientCtx, AFB_request *request);
-extern AFB_clientCtx *ctxClientGet (AFB_request *request);
-*/
 extern void ctxStoreGarbage ();
 
 extern void ctxStoreInit (int nbSession, int timeout, int apicount, const char *initok);
 
-extern AFB_clientCtx *_ctxClientGet (const char *uuid);
-extern AFB_error _ctxClientDel (AFB_clientCtx *clientCtx);
-extern AFB_error _ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token);
-extern AFB_error _ctxTokenNew (AFB_clientCtx *clientCtx);
+extern AFB_clientCtx *ctxClientGet (const char *uuid);
+extern int ctxClientClose (AFB_clientCtx *clientCtx);
+extern int ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token);
+extern int ctxTokenNew (AFB_clientCtx *clientCtx);