X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Frest-api.c;h=643acb57d2240451c35cd2b22a50f3a5a1c2a9fb;hb=3a10185ae380956bd356c73f34138f97255bf7e6;hp=dd5c59b9a4170bc48355e6601b62fbd6ad1ab01e;hpb=ae91ae3f2376635127e8cda5ae12171bdd2198c1;p=src%2Fapp-framework-binder.git diff --git a/src/rest-api.c b/src/rest-api.c index dd5c59b9..643acb57 100644 --- a/src/rest-api.c +++ b/src/rest-api.c @@ -45,15 +45,15 @@ PUBLIC void endPostRequest(AFB_PostHandle *postHandle) { if (postHandle->type == AFB_POST_FORM) { if (verbose) fprintf(stderr, "End PostForm Request UID=%d\n", postHandle->uid); } - if (postHandle->private) free(postHandle->private); + if (postHandle->privatebuf) free(postHandle->privatebuf); free(postHandle); } // Check of apiurl is declare in this plugin and call it STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) { - json_object *jresp, *jcall; + json_object *jresp, *jcall, *jreqt; int idx, status, sig; - AFB_clientCtx *clientCtx; + AFB_clientCtx *clientCtx = NULL; AFB_plugin *plugin = request->plugins[plugidx]; int signals[]= {SIGALRM, SIGSEGV, SIGFPE, 0}; @@ -79,9 +79,9 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) if (!strcmp(plugin->apis[idx].name, request->api)) { // Request was found and at least partially executed - request->jresp = json_object_new_object(); + jreqt = json_object_new_object(); json_object_get (afbJsonType); // increate jsontype reference count - json_object_object_add (request->jresp, "jtype", afbJsonType); + json_object_object_add (jreqt, "jtype", afbJsonType); // prepare an object to store calling values jcall=json_object_new_object(); @@ -95,7 +95,7 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) // Plugin aborted somewhere during its execution json_object_object_add(jcall, "status", json_object_new_string ("abort")); json_object_object_add(jcall, "info" , json_object_new_string ("Plugin broke during execution")); - json_object_object_add(request->jresp, "request", jcall); + json_object_object_add(jreqt, "request", jcall); } else { @@ -106,12 +106,12 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) 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; + json_object_object_add(jreqt, "request", jcall); + goto ExitOnDone; } } // Trigger a timer to protect from unacceptable long time execution - alarm (request->config->apiTimeout); + alarm ((unsigned)request->config->apiTimeout); } // Out of SessionNone every call get a client context session @@ -123,30 +123,30 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) request->errcode=MHD_HTTP_INSUFFICIENT_STORAGE; json_object_object_add(jcall, "status", json_object_new_string ("fail")); json_object_object_add(jcall, "info", json_object_new_string ("Client Session Context Full !!!")); - json_object_object_add(request->jresp, "request", jcall); - return (AFB_DONE); + json_object_object_add(jreqt, "request", jcall); + goto ExitOnDone; }; - if (verbose) fprintf(stderr, "Plugin=[%s] Api=[%s] Middleware=[%d] Client=[0x%x] Uuid=[%s] Token=[%s]\n" + if (verbose) fprintf(stderr, "Plugin=[%s] Api=[%s] Middleware=[%d] Client=[%p] Uuid=[%s] Token=[%s]\n" , request->prefix, request->api, plugin->apis[idx].session, clientCtx, clientCtx->uuid, clientCtx->token); switch(plugin->apis[idx].session) { - case AFB_SESSION_CREATE: - if (clientCtx->token[0] != '\0') { + 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_object_object_add(request->jresp, "request", jcall); - return (AFB_DONE); + 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_object_object_add(request->jresp, "request", jcall); - return (AFB_DONE); + json_object_object_add(jreqt, "request", jcall); + goto ExitOnDone; } else { json_object_object_add(jcall, "uuid", json_object_new_string (clientCtx->uuid)); json_object_object_add(jcall, "token", json_object_new_string (clientCtx->token)); @@ -160,8 +160,8 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) 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); + json_object_object_add(jreqt, "request", jcall); + goto ExitOnDone; } else { json_object_object_add(jcall, "uuid", json_object_new_string (clientCtx->uuid)); json_object_object_add(jcall, "token", json_object_new_string (clientCtx->token)); @@ -174,8 +174,8 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) 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); + json_object_object_add(jreqt, "request", jcall); + goto ExitOnDone; } else { json_object_object_add(jcall, "uuid", json_object_new_string (clientCtx->uuid)); } @@ -188,8 +188,8 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) 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); + json_object_object_add(jreqt, "request", jcall); + goto ExitOnDone; } break; } @@ -199,7 +199,7 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) jresp = plugin->apis[idx].callback(request, context); // Store context in case it was updated by plugins - clientCtx->contexts[plugidx] = request->context; + if (request->context != NULL) clientCtx->contexts[plugidx] = request->context; // handle intermediary Post Iterates out of band if ((jresp == NULL) && (request->errcode == MHD_HTTP_OK)) return (AFB_SUCCESS); @@ -210,13 +210,13 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) // API should return NULL of a valid Json Object if (jresp == NULL) { json_object_object_add(jcall, "status", json_object_new_string ("null")); - json_object_object_add(request->jresp, "request", jcall); + json_object_object_add(jreqt, "request", jcall); request->errcode = MHD_HTTP_NO_RESPONSE; } else { json_object_object_add(jcall, "status", json_object_new_string ("processed")); - json_object_object_add(request->jresp, "request", jcall); - json_object_object_add(request->jresp, "response", jresp); + json_object_object_add(jreqt, "request", jcall); + json_object_object_add(jreqt, "response", jresp); } // cancel timeout and plugin signal handle before next call if (request->config->apiTimeout > 0) { @@ -226,10 +226,14 @@ STATIC AFB_error callPluginApi(AFB_request *request, int plugidx, void *context) } } } - return (AFB_DONE); + goto ExitOnDone; } } return (AFB_FAIL); + +ExitOnDone: + request->jresp = jreqt; + return (AFB_DONE); } STATIC AFB_error findAndCallApi (AFB_request *request, void *context) { @@ -267,7 +271,7 @@ ExitOnError: // This CB is call for every item with a form post it reformat iterator values // and callback Plugin API for each Item within PostForm. -doPostIterate (void *cls, enum MHD_ValueKind kind, const char *key, +STATIC int doPostIterate (void *cls, enum MHD_ValueKind kind, const char *key, const char *filename, const char *mimetype, const char *encoding, const char *data, uint64_t offset, size_t size) { @@ -277,10 +281,11 @@ doPostIterate (void *cls, enum MHD_ValueKind kind, const char *key, // retrieve API request from Post iterator handle AFB_PostHandle *postHandle = (AFB_PostHandle*)cls; - AFB_request *request = (AFB_request*)postHandle->private; + AFB_request *request = (AFB_request*)postHandle->privatebuf; AFB_PostRequest postRequest; - fprintf (stderr, "postHandle key=%s filename=%s len=%d mime=%s\n", key, filename, size, mimetype); + if (verbose) + fprintf (stderr, "postHandle key=%s filename=%s len=%zu mime=%s\n", key, filename, size, mimetype); // Create and Item value for Plugin API item.kind = kind; @@ -304,7 +309,7 @@ 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) { @@ -317,12 +322,11 @@ STATIC void freeRequest (AFB_request *request) { STATIC AFB_request *createRequest (struct MHD_Connection *connection, AFB_session *session, const char* url) { AFB_request *request; - int idx; // Start with a clean request request = calloc (1, sizeof (AFB_request)); char *urlcpy1, *urlcpy2; - char *baseapi, *baseurl; + char *baseapi, *baseurl; // Extract plugin urlpath from request and make two copy because strsep overload copy urlcpy1 = urlcpy2 = strdup(url); @@ -364,18 +368,20 @@ 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_request *request = NULL; AFB_PostHandle *postHandle; AFB_PostRequest postRequest; int ret; - + + // fprintf (stderr, "doRestAPI method=%s posthandle=%p\n", method, con_cls); + // 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; - // This is the initial post event let's create form post structure POST datas come in multiple events + // This is the initial post event let's create form post structure POST data come in multiple events if (postHandle == NULL) { // allocate application POST processor handle to zero @@ -394,15 +400,13 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co // Form post is handle through a PostProcessor and call API once per form key if (strcasestr(encoding, FORM_CONTENT) != NULL) { - if (verbose) fprintf(stderr, "Create PostForm[uid=%d]\n", postHandle->uid); + if (verbose) fprintf(stderr, "Create doPostIterate[uid=%d posthandle=%p]\n", postHandle->uid, postHandle); request = createRequest (connection, session, url); if (request->jresp != NULL) goto ProcessApiCall; - - 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; + postHandle->privatebuf = (void*)request; + postHandle->pp = MHD_create_post_processor (connection, MAX_POST_SIZE, &doPostIterate, postHandle); if (NULL == postHandle->pp) { fprintf(stderr,"OOPS: Internal error fail to allocate MHD_create_post_processor\n"); @@ -426,7 +430,7 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co // 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 + postHandle->privatebuf = malloc((unsigned)contentlen + 1); // allocate memory for full POST data + 1 for '\0' enf of string // if (verbose) fprintf(stderr, "Create PostJson[uid=%d] Size=%d\n", postHandle->uid, contentlen); return MHD_YES; @@ -451,7 +455,7 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co // Process JsonPost request when buffer is completed let's call API if (postHandle->type == AFB_POST_JSON) { // if (verbose) fprintf(stderr, "Updating PostJson[uid=%d]\n", postHandle->uid); - memcpy(&postHandle->private[postHandle->len], upload_data, *upload_data_size); + memcpy(&postHandle->privatebuf[postHandle->len], upload_data, *upload_data_size); postHandle->len = postHandle->len + *upload_data_size; } @@ -487,8 +491,8 @@ PUBLIC int doRestApi(struct MHD_Connection *connection, AFB_session *session, co } // Before processing data, make sure buffer string is properly ended - postHandle->private[postHandle->len] = '\0'; - postRequest.data = postHandle->private; + postHandle->privatebuf[postHandle->len] = '\0'; + postRequest.data = postHandle->privatebuf; request->post = &postRequest; // if (verbose) fprintf(stderr, "Close Post[%d] Buffer=%s\n", postHandle->uid, request->post->data); @@ -509,7 +513,7 @@ ProcessApiCall: // client did not pass token on URI let's use cookies if ((!request->restfull) && (request->context != NULL)) { char cookie[256]; - snprintf (cookie, sizeof (cookie), "%s=%s;path=%s;max-age=%d", COOKIE_NAME, request->uuid, request->config->rootapi,request->config->cntxTimeout); + snprintf (cookie, sizeof (cookie), "%s-%d=%s; Path=%s; Max-Age=%d; HttpOnly", COOKIE_NAME, request->config->httpdPort, request->uuid, request->config->rootapi,request->config->cntxTimeout); MHD_add_response_header (webResponse, MHD_HTTP_HEADER_SET_COOKIE, cookie); } @@ -535,7 +539,7 @@ ExitOnError: // Loop on plugins. Check that they have the right type, prepare a JSON object with prefix STATIC AFB_plugin ** RegisterJsonPlugins(AFB_plugin **plugins) { - int idx, jdx; + int idx; for (idx = 0; plugins[idx] != NULL; idx++) { if (plugins[idx]->type != AFB_PLUGIN_JSON) { @@ -555,20 +559,6 @@ STATIC AFB_plugin ** RegisterJsonPlugins(AFB_plugin **plugins) { plugins[idx]->jtype = json_object_new_string(plugins[idx]->prefix); json_object_get(plugins[idx]->jtype); // increase reference count to make it permanent plugins[idx]->prefixlen = strlen(plugins[idx]->prefix); - - - // Prebuild each API jtype to boost API json response - for (jdx = 0; plugins[idx]->apis[jdx].name != NULL; jdx++) { - AFB_privateApi *private = malloc (sizeof (AFB_privateApi)); - if (plugins[idx]->apis[jdx].private != NULL) { - fprintf (stderr, "WARNING: plugin=%s api=%s private handle should be NULL=0x%x\n" - ,plugins[idx]->prefix,plugins[idx]->apis[jdx].name, plugins[idx]->apis[jdx].private); - } - private->len = strlen (plugins[idx]->apis[jdx].name); - private->jtype=json_object_new_string(plugins[idx]->apis[jdx].name); - json_object_get(private->jtype); // increase reference count to make it permanent - plugins[idx]->apis[jdx].private = private; - } } } return (plugins); @@ -628,22 +618,23 @@ STATIC void scanDirectory(char *dirpath, int dirfd, AFB_plugin **plugins, int *c // if max plugin is reached let's stop searching if (*count == AFB_MAX_PLUGINS) { - fprintf(stderr, "[%s] is not loaded [Max Count=%d reached]\n", *count); + fprintf(stderr, "[%s] is not loaded [Max Count=%d reached]\n", pluginDir.d_name, *count); continue; } if (verbose) fprintf(stderr, "[%s] is a valid AFB plugin, loading pos[%d]\n", pluginDir.d_name, *count); - plugins[*count] = (AFB_plugin *) malloc (sizeof(AFB_plugin)); - plugins[*count] = (**pluginRegisterFct)(); - *count = *count +1; - + plugins[*count] = pluginRegisterFct(); + if (!plugins[*count]) { + if (verbose) fprintf(stderr, "ERROR: plugin [%s] register function failed. continuing...\n", pluginDir.d_name); + } else + *count = *count +1; } } closedir (dir); } void initPlugins(AFB_session *session) { - static AFB_plugin **plugins; + AFB_plugin **plugins; afbJsonType = json_object_new_string (AFB_MSG_JTYPE); int count = 0; @@ -651,10 +642,10 @@ void initPlugins(AFB_session *session) { int dirfd; /* pre-allocate for AFB_MAX_PLUGINS plugins, we will downsize later */ - plugins = (AFB_plugin **) malloc (AFB_MAX_PLUGINS *sizeof(AFB_plugin)); + plugins = (AFB_plugin **) malloc (AFB_MAX_PLUGINS *sizeof(AFB_plugin*)); // Loop on every directory passed in --plugins=xxx - while (dirpath = strsep(&session->config->ldpaths, ":")) { + while ((dirpath = strsep(&session->config->ldpaths, ":"))) { // Ignore any directory we fail to open if ((dirfd = open(dirpath, O_DIRECTORY)) <= 0) { fprintf(stderr, "Invalid directory path=[%s]\n", dirpath); @@ -666,11 +657,11 @@ void initPlugins(AFB_session *session) { if (count == 0) { fprintf(stderr, "No plugins found, afb-daemon is unlikely to work in this configuration, exiting...\n"); - exit (-1); + exit (1); } // downsize structure to effective number of loaded plugins - plugins = (AFB_plugin **)realloc (plugins, (count+1)*sizeof(AFB_plugin)); + plugins = (AFB_plugin **)realloc (plugins, (unsigned)(count+1)*sizeof(AFB_plugin*)); plugins[count] = NULL; // complete plugins and save them within current sessions