X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fhelper-api.c;h=7c70330bc8c46e1c478f0048f5d4587cf055f0fc;hb=bcc7f5e4fc170c7feaad561d13e3fb6b4e6dd798;hp=670c9a1db4fb7abe7bb3cd1db9b9d28b9e567573;hpb=e76dff6729fb9acd1638019507e7edbbd8af23f5;p=src%2Fapp-framework-binder.git diff --git a/src/helper-api.c b/src/helper-api.c index 670c9a1d..7c70330b 100644 --- a/src/helper-api.c +++ b/src/helper-api.c @@ -18,6 +18,10 @@ */ #include "../include/local-def.h" +#include +#include +#include +#include // handle to hold queryAll values @@ -27,15 +31,47 @@ typedef struct { size_t len; } queryHandleT; +// Error code are requested through function to manage json usage count +typedef struct { + int level; + const char* label; + json_object *json; +} AFB_errorT; + +static AFB_errorT AFBerr [AFB_SUCCESS+1]; +static json_object *jTypeStatic; + +PUBLIC int verbose; + +static const char *ERROR_LABEL[] = {"false", "true", "fatal", "fail", "warning", "empty", "success"}; + +/* ------------------------------------------------------------------------------ + * Get localtime and return in a string + * ------------------------------------------------------------------------------ */ + +PUBLIC char * configTime (void) { + static char reqTime [26]; + time_t tt; + struct tm *rt; + + /* Get actual Date and Time */ + time (&tt); + rt = localtime (&tt); + + strftime (reqTime, sizeof (reqTime), "(%d-%b %H:%M)",rt); + + // return pointer on static data + return (reqTime); +} + + // Sample Generic Ping Debug API -PUBLIC json_object* getPingTest(AFB_request *request) { - static pingcount = 0; +json_object* getPingTest(AFB_request *request) { + static int pingcount = 0; json_object *response; char query [256]; char session[256]; - int len; - AFB_clientCtx *client=request->client; // get client context from request // request all query key/value len = getQueryAll (request, query, sizeof(query)); @@ -43,52 +79,49 @@ PUBLIC json_object* getPingTest(AFB_request *request) { // check if we have some post data if (request->post == NULL) request->post->data="NoData"; - - // check is we have a session and a plugin handle - if (client == NULL) strncpy (session,"NoSession", sizeof(session)); - else snprintf(session, sizeof(session),"uuid=%s token=%s ctx=0x%x handle=0x%x", client->uuid, client->token, client->ctx, client->ctx); - + // return response to caller - response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon count=%d CtxtId=%d query={%s} session={%s} PostData: [%s] " - , pingcount++, request->client->cid, query, session, request->post->data); + response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon count=%d uuid=%s query={%s} session={0x%x} PostData: [%s] " + , pingcount++, request->uuid, query, session, request->post->data); return (response); } // Helper to retrieve argument from connection -PUBLIC const char* getQueryValue(AFB_request * request, char *name) { +const char* getQueryValue(const AFB_request * request, const char *name) { const char *value; value = MHD_lookup_connection_value(request->connection, MHD_GET_ARGUMENT_KIND, name); return (value); } -STATIC int getQueryCB (void*handle, enum MHD_ValueKind kind, const char *key, const char *value) { +static int getQueryCB (void*handle, enum MHD_ValueKind kind, const char *key, const char *value) { queryHandleT *query = (queryHandleT*)handle; query->idx += snprintf (&query->msg[query->idx],query->len," %s: \'%s\',", key, value); + return MHD_YES; /* continue to iterate */ } // Helper to retrieve argument from connection -PUBLIC int getQueryAll(AFB_request * request, char *buffer, size_t len) { +int 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; + query.msg = buffer; + query.len = len; + query.idx = 0; MHD_get_connection_values (request->connection, MHD_GET_ARGUMENT_KIND, getQueryCB, &query); return (len); } // Helper to retrieve POST handle -PUBLIC AFB_PostHandle* getPostHandle (AFB_request *request) { +AFB_PostHandle* getPostHandle (AFB_request *request) { if (request->post == NULL) return (NULL); return ((AFB_PostHandle*) request->post->data); } // Helper to retrieve POST file context -PUBLIC AFB_PostCtx* getPostContext (AFB_request *request) { +AFB_PostCtx* getPostContext (AFB_request *request) { AFB_PostHandle* postHandle; if (request->post == NULL) return (NULL); @@ -98,104 +131,115 @@ PUBLIC AFB_PostCtx* getPostContext (AFB_request *request) { return ((AFB_PostCtx*) postHandle->ctx); } -PUBLIC json_object* getPostFile (AFB_request *request, AFB_PostItem *item, char* destination) { +char* getPostPath (AFB_request *request) { + AFB_PostHandle *postHandle = getPostHandle(request); + AFB_PostCtx *postFileCtx; + + if (postHandle == NULL) return NULL; + + postFileCtx = (AFB_PostCtx*) postHandle->ctx; + if (postFileCtx == NULL) return NULL; + + return (postFileCtx->path); +} + +json_object* getPostFile (AFB_request *request, AFB_PostItem *item, char* destination) { AFB_PostHandle *postHandle = getPostHandle(request); - AFB_PostCtx *appCtx; + AFB_PostCtx *postFileCtx; char filepath[512]; - int len; + ssize_t len; // This is called after PostForm and then after DonePostForm if (item == NULL) { json_object* jresp; - appCtx = (AFB_PostCtx*) postHandle->ctx; + postFileCtx = (AFB_PostCtx*) postHandle->ctx; // No Post Application Context [something really bad happen] - if (appCtx == NULL) { + if (postFileCtx == NULL) { request->errcode = MHD_HTTP_EXPECTATION_FAILED; return(jsonNewMessage(AFB_FAIL,"Error: PostForm no PostContext to free\n")); } - // We have a context but last Xform iteration fail. - if (appCtx->jerror != NULL) { - // request->errcode = appCtx->errcode; - jresp = appCtx->jerror; // retrieve previous error from postCtx - } else jresp = jsonNewMessage(AFB_FAIL,"UploadFile Post Request file=[%s] done", appCtx->path); + // We have a context but last Xform iteration fail or application set a message + if (request->jresp != NULL) { + jresp = request->jresp; // retrieve previous error from postCtx + } else jresp = jsonNewMessage(AFB_SUCCESS,"getPostFile Post Request done"); // Error or not let's free all resources - close(appCtx->fd); - free (appCtx->path); - free (appCtx); + close(postFileCtx->fd); + free (postFileCtx->path); + free (postFileCtx); return (jresp); } - +#if defined(PLEASE_FIX_ME_THE_ERROR_IS_postFileCtx_NOT_INITIALIZED) // Make sure it's a valid PostForm request if (!request->post && request->post->type != AFB_POST_FORM) { - appCtx->jerror= jsonNewMessage(AFB_FAIL,"This is not a valid PostForm request\n"); + postFileCtx->jresp= jsonNewMessage(AFB_FAIL,"This is not a valid PostForm request\n"); goto ExitOnError; } // Check this is a file element if (item->filename == NULL) { - appCtx->jerror= jsonNewMessage(AFB_FAIL,"No Filename attached to key=%s\n", item->key); + postFileCtx->jresp= jsonNewMessage(AFB_FAIL,"No Filename attached to key=%s\n", item->key); goto ExitOnError; } // Check we got something in buffer if (item->len <= 0) { - appCtx->jerror= jsonNewMessage(AFB_FAIL,"Buffer size NULL key=%s]\n", item->key); + postFileCtx->jresp= jsonNewMessage(AFB_FAIL,"Buffer size NULL key=%s]\n", item->key); goto ExitOnError; } - +#endif // Extract Application Context from posthandle [NULL == 1st iteration] - appCtx = (AFB_PostCtx*) postHandle->ctx; + postFileCtx = (AFB_PostCtx*) postHandle->ctx; // This is the 1st Item iteration let's open output file and allocate necessary resources - if (appCtx == NULL) { - int destDir; + if (postFileCtx == NULL) { + DIR* destDir; // Create an application specific context - appCtx = calloc (1, sizeof(AFB_PostCtx)); // May place anything here until post->completeCB handle resources liberation - appCtx->path = strdup (filepath); + postFileCtx = calloc (1, sizeof(AFB_PostCtx)); // May place anything here until post->completeCB handle resources liberation // attach application to postHandle - postHandle->ctx = (void*) appCtx; // May place anything here until post->completeCB handle resources liberation + postHandle->ctx = (void*) postFileCtx; // May place anything here until post->completeCB handle resources liberation // Build destination directory full path if (destination[0] != '/') { strncpy (filepath, request->config->sessiondir, sizeof(filepath)); - strncat (filepath, destination, sizeof(filepath)); strncat (filepath, "/", sizeof(filepath)); strncat (filepath, destination, sizeof(filepath)); } else strncpy (filepath, destination, sizeof(filepath)); - + // make sure destination directory exist - destDir = openat (filepath, request->plugin, O_DIRECTORY); - if (destDir < 0) { - destDir = mkdir(filepath,O_RDWR | S_IRWXU | S_IRGRP); - if (destDir < 0) { - appCtx->jerror= jsonNewMessage(AFB_FAIL,"Fail to Create destination directory=[%s] error=%s\n", filepath, strerror(errno)); + destDir = opendir (filepath); + if (destDir == NULL) { + if (mkdir(filepath,O_RDWR | S_IRWXU | S_IRGRP) < 0) { + postFileCtx->jresp= jsonNewMessage(AFB_FAIL,"Fail to Create destination directory=[%s] error=%s\n", filepath, strerror(errno)); goto ExitOnError; } - } else close (destDir); + } else closedir (destDir); strncat (filepath, "/", sizeof(filepath)); strncat (filepath, item->filename, sizeof(filepath)); - if((appCtx->fd = open(filepath, O_RDWR |O_CREAT, S_IRWXU|S_IRGRP)) < 0) { - appCtx->jerror= jsonNewMessage(AFB_FAIL,"Fail to Create destination=[%s] error=%s\n", filepath, strerror(errno)); + postFileCtx->path = strdup (filepath); + if (verbose) fprintf(stderr, "getPostFile path=%s\n", filepath); + + if((postFileCtx->fd = open(filepath, O_RDWR |O_CREAT, S_IRWXU|S_IRGRP)) <= 0) { + postFileCtx->jresp= jsonNewMessage(AFB_FAIL,"Fail to Create destination File=[%s] error=%s\n", filepath, strerror(errno)); goto ExitOnError; } } else { // reuse existing application context - appCtx = (AFB_PostCtx*) postHandle->ctx; + postFileCtx = (AFB_PostCtx*) postHandle->ctx; } // Check we successfully wrote full buffer - len = write (appCtx->fd, item->data, item->len); - if (item->len != len) { - appCtx->jerror= jsonNewMessage(AFB_FAIL,"Fail to write file [%s] at [%s] error=\n", item->filename, strerror(errno)); + len = write (postFileCtx->fd, item->data, item->len); + if ((ssize_t)item->len != len) { + postFileCtx->jresp= jsonNewMessage(AFB_FAIL,"Fail to write file [%s] at [%s] error=\n", item->filename, strerror(errno)); goto ExitOnError; } @@ -207,3 +251,88 @@ ExitOnError: request->errcode = MHD_HTTP_EXPECTATION_FAILED; return NULL; } + + + +static void jsoninit() +{ + int idx, verbosesav; + + if (jTypeStatic) + return; + + // initialise JSON constant messages and increase reference count to make them permanent + verbosesav = verbose; + verbose = 0; // run initialisation in silent mode + jTypeStatic = json_object_new_string ("AFB_message"); + for (idx = 0; idx <= AFB_SUCCESS; idx++) { + AFBerr[idx].level = idx; + AFBerr[idx].label = ERROR_LABEL [idx]; + AFBerr[idx].json = jsonNewMessage (idx, NULL); + } + verbose = verbosesav; +} + + + +// get JSON object from error level and increase its reference count +struct json_object *jsonNewStatus (AFB_error level) +{ + jsoninit(); + json_object *target = AFBerr[level].json; + json_object_get (target); + + return (target); +} + +// get AFB object type with adequate usage count +struct json_object *jsonNewjtype (void) +{ + jsoninit(); + json_object_get (jTypeStatic); // increase reference count + return (jTypeStatic); +} + +// 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; + va_list args; + char message [512]; + + jsoninit(); + + // format message + if (format != NULL) { + va_start(args, format); + vsnprintf (message, sizeof (message), format, args); + va_end(args); + } + + AFBResponse = json_object_new_object(); + json_object_object_add (AFBResponse, "jtype", jsonNewjtype ()); + json_object_object_add (AFBResponse, "status" , json_object_new_string (ERROR_LABEL[level])); + if (format != NULL) { + json_object_object_add (AFBResponse, "info" , json_object_new_string (message)); + } + if (verbose) { + fprintf (stderr, "AFB:%-6s [%3d]: ", AFBerr [level].label, count++); + if (format != NULL) { + fprintf (stderr, "%s", message); + } else { + fprintf (stderr, "No Message"); + } + fprintf (stderr, "\n"); + } + + return (AFBResponse); +} + +// Dump a message on stderr +void jsonDumpObject (struct json_object * jObject) { + + if (verbose) { + fprintf (stderr, "AFB:dump [%s]\n", json_object_to_json_string(jObject)); + } +} +