aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2016-04-01 16:20:12 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2016-04-01 16:20:12 +0200
commitbbe18a624f4961165cf52d7f4c25de6f3a7ec012 (patch)
tree8167fa621fbcdcd91e11988ce6d8c9cf4072fc48
parentc95f72616f59a317f72c58c0e5664992504a48e5 (diff)
work in progress
Change-Id: I3df95def03bb26ca4d1a52f7cd94b0fb67375d4c Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--CMakeLists.txt2
-rw-r--r--include/local-def.h49
-rw-r--r--include/proto-def.h8
-rw-r--r--plugins/samples/ClientCtx.c1
-rw-r--r--plugins/samples/HelloWorld.c35
-rw-r--r--plugins/session/token-api.c1
-rw-r--r--src/afb-apis.c52
-rw-r--r--src/afb-hreq.c111
-rw-r--r--src/afb-hreq.h5
-rw-r--r--src/afb-req-itf.h50
-rw-r--r--src/afb-rest-api.c18
-rw-r--r--src/afb-websock.c3
-rw-r--r--src/helper-api.c69
-rw-r--r--src/http-svc.c11
-rw-r--r--src/main.c21
-rw-r--r--src/session.c278
-rw-r--r--src/session.h16
17 files changed, 327 insertions, 403 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d1780784..15e7f7ec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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}")
diff --git a/include/local-def.h b/include/local-def.h
index 3f618717..605c05a3 100644
--- a/include/local-def.h
+++ b/include/local-def.h
@@ -21,29 +21,9 @@
#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 {
@@ -192,16 +172,18 @@ typedef struct {
} 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
diff --git a/include/proto-def.h b/include/proto-def.h
index c364035a..e2190eb1 100644
--- a/include/proto-def.h
+++ b/include/proto-def.h
@@ -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);
diff --git a/plugins/samples/ClientCtx.c b/plugins/samples/ClientCtx.c
index b59400e1..175b9387 100644
--- a/plugins/samples/ClientCtx.c
+++ b/plugins/samples/ClientCtx.c
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdio.h>
#include "local-def.h"
diff --git a/plugins/samples/HelloWorld.c b/plugins/samples/HelloWorld.c
index 6c2d0cf9..85e92f45 100644
--- a/plugins/samples/HelloWorld.c
+++ b/plugins/samples/HelloWorld.c
@@ -16,31 +16,35 @@
* 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;
};
diff --git a/plugins/session/token-api.c b/plugins/session/token-api.c
index 9a078328..feb269dd 100644
--- a/plugins/session/token-api.c
+++ b/plugins/session/token-api.c
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdio.h>
#include "local-def.h"
diff --git a/src/afb-apis.c b/src/afb-apis.c
index 856e3f5d..effef8a9 100644
--- a/src/afb-apis.c
+++ b/src/afb-apis.c
@@ -32,6 +32,10 @@
#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)
diff --git a/src/afb-hreq.c b/src/afb-hreq.c
index 506091cb..58dbb04e 100644
--- a/src/afb-hreq.c
+++ b/src/afb-hreq.c
@@ -16,12 +16,18 @@
*/
#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);
+}
diff --git a/src/afb-hreq.h b/src/afb-hreq.h
index 01409a58..fb914f13 100644
--- a/src/afb-hreq.h
+++ b/src/afb-hreq.h
@@ -15,9 +15,10 @@
* 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);
-
diff --git a/src/afb-req-itf.h b/src/afb-req-itf.h
index ab72a5ce..eea78317 100644
--- a/src/afb-req-itf.h
+++ b/src/afb-req-itf.h
@@ -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);
+}
+
diff --git a/src/afb-rest-api.c b/src/afb-rest-api.c
index 80de7d65..28346b19 100644
--- a/src/afb-rest-api.c
+++ b/src/afb-rest-api.c
@@ -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;
}
diff --git a/src/afb-websock.c b/src/afb-websock.c
index 23d489ab..b9417cbe 100644
--- a/src/afb-websock.c
+++ b/src/afb-websock.c
@@ -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"
diff --git a/src/helper-api.c b/src/helper-api.c
index fd42c482..1e3d8820 100644
--- a/src/helper-api.c
+++ b/src/helper-api.c
@@ -17,12 +17,19 @@
*
*/
-#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;
}
@@ -218,6 +225,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;
json_object * AFBResponse;
@@ -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
+
diff --git a/src/http-svc.c b/src/http-svc.c
index 706abbc5..9235bf87 100644
--- a/src/http-svc.c
+++ b/src/http-svc.c
@@ -16,12 +16,17 @@
*/
#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;
}
diff --git a/src/main.c b/src/main.c
index a602af92..2401043c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,15 +16,22 @@
* 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);
}
}
diff --git a/src/session.c b/src/session.c
index eded1416..ad411239 100644
--- a/src/session.c
+++ b/src/session.c
@@ -20,16 +20,24 @@
*
*/
+#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;
}
diff --git a/src/session.h b/src/session.h
index 0862b37b..9b54179b 100644
--- a/src/session.h
+++ b/src/session.h
@@ -19,26 +19,18 @@
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);