예제 #1
0
/*----------------------------------------------------------------------------*/
int rp_bazaar_install(ngx_http_request_t *r)
{
    rp_bazaar_ctx_t *ctx;

    ctx = ngx_http_get_module_ctx(r, ngx_http_rp_module);
    if(ctx == NULL) {
        fprintf(stderr,
                 "%s: Cannot get request context\n",
                 __FUNCTION__);
        return NGX_ERROR;
    }

    if(r->method & NGX_HTTP_POST) {

        ngx_int_t rc;
        ctx->finalize_on_post_handler = 0;

        rc = ngx_http_read_client_request_body(r, rp_bazaar_post_read);

        if(rc == NGX_AGAIN) {
            ctx->finalize_on_post_handler = 1;
        } else {
            return rp_module_redirect(r, ctx->redirect);
        }

        return rc;
    }

    return rp_module_cmd_error(&ctx->json_root, "Unsupported request method.",
                               NULL, r->pool);
}
예제 #2
0
/*----------------------------------------------------------------------------*/
int rp_bazaar_help(ngx_http_request_t *r, cJSON **json_root,
                   int argc, char **argv)
{
    cJSON *root = *json_root;
    int i;

    if(argc != 0) {
        return rp_module_cmd_error(json_root,
                                "Incorrect number of arguments (should be 0)",
                                   NULL, r->pool);
    }

    for(i = 0; bazaar_cmds[i].name != NULL; i++) {
        /* omit arg_ in the name */
        const char *strings[] = { (const char *)&bazaar_cmds[i].name[4],
                                  (const char *)bazaar_cmds[i].params,
                                  (const char *)bazaar_cmds[i].desc };

        cJSON_AddItemToObject(root, "command",
                              cJSON_CreateStringArray((const char **)strings,
                                                      3, r->pool),
                              r->pool);
    }

    return rp_module_cmd_ok(json_root, r->pool);
}
예제 #3
0
/*----------------------------------------------------------------------------*/
int rp_bazaar_stop(ngx_http_request_t *r,
                   cJSON **json_root, int argc, char **argv)
{
/*    if(argc != 0) {
        return rp_module_cmd_error(json_root,
                                "Incorrect number of arguments (should be 0)",
                                   NULL, r->pool);
    }*/

    if(rp_module_ctx.app.handle == NULL) {
        /* Ignore requests to unload the application controller, if none is loaded. */
        return rp_module_cmd_ok(json_root, r->pool);
    }
    if(rp_bazaar_app_unload_module(&rp_module_ctx.app) < 0) {
        return rp_module_cmd_error(json_root,
                                   "Can not unload application.", NULL, r->pool);
    }

    return rp_module_cmd_ok(json_root, r->pool);
}
예제 #4
0
int rp_bazaar_app_get_local_list(const char *dir, cJSON **json_root,
                                 ngx_pool_t *pool, int verbose)
{
	static int once = 1;
	if (once) {
		system("bazaar idgen 0");	
		once = 0;
	}
	
    DIR *dp;
    struct dirent *ep;

    if((dp = opendir(dir)) == NULL)
        return rp_module_cmd_error(json_root, "Can not open apps directory", 
                                   strerror(errno), pool);

    while((ep = readdir (dp))) {
        const char *app_id = ep->d_name;
        cJSON *info = NULL;

        /* check if structure is correct, we need: 
         *  <app_id>/info/info.json
         *  <app_id>/info/icon.png
         *  <app_id>/controllerhf.so
         *  <app_id>/fpga.bit
         * And we must be able to load the application and test mandatory
         * functions.
         */
        
        if (!is_readable(dir, app_id, "info/icon.png"))
            continue;
        if (!is_readable(dir, app_id, "fpga.conf"))
            continue;
        if (!is_controller_ok(dir, app_id, "controllerhf.so"))
            continue;
        if (!get_info(&info, dir, app_id, pool))
            continue;
        if (info == NULL)
            continue;

        /* We have an application */
        int demo = !is_registered(dir, app_id, "controllerhf.so");
		
        if (verbose) {
            /* Attach whole info JSON */
            cJSON_AddItemToObject(info, "type", cJSON_CreateString(demo ? "demo" : "run", pool), pool);
            cJSON_AddItemToObject(*json_root, app_id, info, pool);
        } else {
            /* Include version only */
            cJSON *j_ver = cJSON_GetObjectItem(info, "version");

            if(j_ver == NULL) {
                fprintf(stderr, "Cannot get version from info JSON.\n");
                cJSON_Delete(info, pool);
                continue;
            }
            
            cJSON_AddItemToObject(*json_root, app_id, cJSON_CreateString(j_ver->valuestring, pool), pool);
            cJSON_AddItemToObject(*json_root, "type", cJSON_CreateString(demo ? "demo" : "run", pool), pool);
            cJSON_Delete(j_ver, pool);
            cJSON_Delete(info, pool);
        }
    }

    closedir(dp);

    return 0;
}
예제 #5
0
/*----------------------------------------------------------------------------*/
ngx_int_t rp_bazaar_cmd_handler(ngx_http_request_t *r)
{
    ngx_http_rp_loc_conf_t *lc;
    rp_bazaar_ctx_t *ctx;
    size_t i = 0;

    ctx = ngx_pcalloc(r->pool, sizeof(rp_bazaar_ctx_t));
    if (ctx == NULL) {
        return NGX_ERROR;
    }
    ctx->redirect = ngx_pcalloc(r->pool, c_redirect_len);
    if (ctx->redirect == NULL) {
        return NGX_ERROR;
    }
    ctx->json_root = NULL;
    ctx->finalize_on_post_handler = 0;
    ctx->in_buffer = NULL;
    ctx->in_buffer_len = 0;
    ctx->in_status = 0;
    ngx_http_set_ctx(r, ctx, ngx_http_rp_module);

    lc = ngx_http_get_module_loc_conf(r, ngx_http_rp_module);

    /* Just test local directory here - we would need to check it for almost
     * all calls anyway
     */
    if(lc->bazaar_dir.data == NULL) {
        fprintf(stderr, "Bazaar local directory not found\n");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ctx->json_root = cJSON_CreateObject(r->pool);
    if(ctx->json_root == NULL) {
        fprintf(stderr, "Cannot allocate cJSON object\n");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Bazaar commands */
    for(i = 0; bazaar_cmds[i].name != NULL; i++) {

        ngx_str_t arg_name = { strlen(bazaar_cmds[i].name),
                               (u_char *)bazaar_cmds[i].name };
        ngx_uint_t arg_key = ngx_hash_key(arg_name.data, arg_name.len);
        ngx_http_variable_value_t *arg_val = NULL;

        int rc;
        char **arg_argv = NULL;
        int    arg_argc = 0;

        arg_val = ngx_http_get_variable(r, &arg_name, arg_key);

        /* check validity of the specified http variables
         * note: not all attributes of arg_value are set within ngx_http_get_variable, thus
         * the order of the following checks are important otherwise it could come to the usage
         * of uninitialized value what would lead to invalid processing
         */
        if (!arg_val)                continue;
        if (arg_val->not_found == 1) continue;
        if (arg_val->valid == 0)     continue;

        arg_val->data[arg_val->len] = '\0';
        arg_argc = rp_module_cmd_parse_args((const char *)arg_val->data,
                                            arg_val->len,
                                            &arg_argv);

        fprintf(stderr, "Calling application: %s\n", &bazaar_cmds[i].name[4]);

        /* Install/Remove special case */
        if ( !strncmp(&bazaar_cmds[i].name[4], "install", 7) ||
             !strncmp(&bazaar_cmds[i].name[4], "remove",  6) ) {
            if(arg_argv) {
                for(i = 0; i < (size_t)arg_argc; i++) {
                    if(arg_argv[i]) {
                        free(arg_argv[i]);
                        arg_argv[i] = NULL;
                    }
                }
                free(arg_argv);
            }
            return rp_bazaar_install(r);
        }

        if((rc = bazaar_cmds[i].func(r, &ctx->json_root, arg_argc, arg_argv)) < 0) {
            /* error - fill the output buffer and send it back */
            fprintf(stderr, "Application %s failed: %d\n",
                     bazaar_cmds[i].name, rc);
        }

        if(arg_argv) {
            for(i = 0; i < (size_t)arg_argc; i++) {
                if(arg_argv[i]) {
                    free(arg_argv[i]);
                    arg_argv[i] = NULL;
                }
            }
            free(arg_argv);
        }

        /* Prepare response header & body */
        return rp_module_send_response(r, &ctx->json_root);
    }

    int ret = 0;

    /* Unknown command response */
    if (i >= sizeof(bazaar_cmds)/sizeof(rp_module_cmd_t)) {
        rp_module_cmd_error(&ctx->json_root, "Unknown command.", NULL, r->pool);
        return rp_module_send_response(r, &ctx->json_root);
    }

    /* Default Bazaar entry point - list of applications with versions */
    cJSON *json_tok = NULL;

    char *host = (char *)r->headers_in.server.data;
    char mac[18];
    sprintf(mac, "00:00:00:00:00:00");
    if (rp_bazaar_get_mac("/sys/class/net/eth0/address", mac)) {
        fprintf(stderr, "Cannot obtain MAC address.\n");
    }

    static unsigned long long dna = 0;
    if (!dna || dna == 1) {
		if (rp_bazaar_get_dna(&dna)) {
			fprintf(stderr, "Cannot obtain DNA number.\n");
		}
	}
    char dna_s[64];
    sprintf(dna_s, "%016llx", dna);

    /* Get Ecosystem version */
    char ecoversion[64];
    sprintf(ecoversion, "unknown");
    cJSON *ecoinfo = NULL;
    if (!get_info(&ecoinfo, (const char *)lc->bazaar_dir.data,
                  "", r->pool)) {
        fprintf(stderr, "Cannot obtain Ecosystem version.\n");
    } else {
        if (ecoinfo != NULL) {

            cJSON *j_ver = cJSON_GetObjectItem(ecoinfo, "version");
            if(j_ver == NULL) {
                fprintf(stderr, "Cannot get version from ecoinfo JSON.\n");
            } else {
                strncpy(ecoversion, j_ver->valuestring, sizeof ecoversion);
                cJSON_Delete(j_ver, r->pool);
            }

            cJSON_Delete(ecoinfo, r->pool);
        }
    }

    /* Populate JSON */
    cJSON_AddItemToObject(ctx->json_root, "version",
                          cJSON_CreateString(ecoversion, r->pool),
                          r->pool);

    cJSON_AddItemToObject(ctx->json_root, "dna",
                          cJSON_CreateString(dna_s, r->pool), r->pool);

    cJSON_AddItemToObject(ctx->json_root, "mac",
                          cJSON_CreateString(mac, r->pool), r->pool);

    // TODO: Serial number?

    cJSON_AddItemToObject(ctx->json_root, "host",
                          cJSON_CreateString(host, r->pool),
                          r->pool);

    cJSON *apps_root;
    cJSON_AddItemToObject(ctx->json_root, "apps",
                          apps_root=cJSON_CreateObject(r->pool), r->pool);
    if(apps_root == NULL) {
        fprintf(stderr, "Can not allocate cJSON object\n");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    fprintf(stderr, "Making list of apps\n");

    /* Add the non-verbose list of apps */
    rp_bazaar_app_get_local_list((const char *)lc->bazaar_dir.data,
                                 &apps_root, r->pool, 0);

    /* Issue a POST with JSON defined above to Bazaar server */
    char *js = cJSON_Print(ctx->json_root, r->pool);
    cJSON_Minify(js);

    fprintf(stderr, "Bazaar handshake:\n%s", js);

    char *jse = NULL;
    char *jsp = NULL;
    char *bazaar_dv = NULL;
    const char *c_payload = "payload=";
    const char *c_device = "/device";

    jse = url_encode(js);

    jsp = malloc(strlen(jse) + strlen(c_payload) + 1);
    if (!jsp) {
        fprintf(stderr, "Cannot malloc() payload.\n");
        ret = NGX_HTTP_INTERNAL_SERVER_ERROR;
        goto out;
    }
    sprintf(jsp, "%s%s", c_payload, jse);

    bazaar_dv = (char *)malloc(strlen((char *)lc->bazaar_server.data) +
                               strlen(c_device) + 1);
    if (!bazaar_dv) {
        fprintf(stderr, "Cannot malloc() device.\n");
        ret = NGX_HTTP_INTERNAL_SERVER_ERROR;
        goto out;
    }
    sprintf(bazaar_dv, "%s%s", lc->bazaar_server.data, c_device);
    fprintf(stderr, "post bazaar_dv %s\n", bazaar_dv);

    post_resp_t resp = { NULL, 0 };
    if (post(jsp, bazaar_dv, &resp)) {
        if (resp.data) free(resp.data);
        /* Redirect to Bazaar access error */
        fprintf(stderr, "Cannot access %s.\n", bazaar_dv);
        snprintf(ctx->redirect, c_redirect_len,
                 "http://%s/error_bazaar_access.html", host);
        goto out;
    }

    /* Get token from POST response */
    if (resp.data) {

        fprintf(stderr,"Bazaar handshake response:\n%s", resp.data);

        json_tok = cJSON_Parse(resp.data, r->pool);
        if (!json_tok) {
            /* Redirect to Bazaar protocol error */
            fprintf(stderr,"No JSON found in the following response:\n\"%s\"\n", resp.data);
            snprintf(ctx->redirect, c_redirect_len,
                     "http://%s/error_bazaar_proto.html", host);
        } else {

            cJSON *jtok = cJSON_GetObjectItem(json_tok, "token");

            if (!jtok) {
                /* Redirect to Bazaar protocol error */
                fprintf(stderr, "No token found in the following JSON:\n\"%s\"\n", resp.data);
                snprintf(ctx->redirect, c_redirect_len,
                         "http://%s/error_bazaar_proto.html", host);
            } else {
                /* Redirect to Bazaar with token */
                snprintf(ctx->redirect, c_redirect_len, "%s/token/%s",
                        lc->bazaar_server.data, jtok->valuestring);
                /* Store token for session control */
                strncpy(g_token, jtok->valuestring, c_token_len);
                g_token[c_token_len - 1] = '\0';
            }
        }

        free(resp.data);
    }

 out:
    if (jsp) free(jsp);
    if (jse) free(jse);
    if (bazaar_dv) free(bazaar_dv);
    //TODO: Is ctx->json_root handled by the pool deallocator?
    //if (ctx->json_root) cJSON_Delete(ctx->json_root, r->pool);
    if (json_tok) cJSON_Delete(json_tok, r->pool);

    if (ret) return ret;

    fprintf(stderr, "Redirecting to: %s\n", ctx->redirect);
    return rp_module_redirect(r, ctx->redirect);
}
예제 #6
0
/**
 * @brief Handler function for operation.
 *
 * Function parses the POST request, which is defined by JSON packet and
 * installs/removes the archive.
 *
 * @param[in]  r          HTTP request as defined by NGINX framework
 * @param[out] act        Bazaar action
 * @retval     0          successful operation
 * @retval     !=0        failure
 */
int rp_bazaar_interpret(ngx_http_request_t *r, action_e *act)
{
    rp_bazaar_ctx_t *ctx;
    cJSON *req_body = NULL;
    cJSON *j_cmd = NULL;
    cJSON *j_url = NULL;
    cJSON *j_app = NULL;
    cJSON *j_md5 = NULL;
    cJSON *j_tok = NULL;
    char  *urld = NULL;
    char  *action = NULL;
    int ret = 0;


    fprintf(stderr, "%s\n", __FUNCTION__);

    *act = eUnknown;

    ctx = ngx_http_get_module_ctx(r, ngx_http_rp_module);
    if(ctx == NULL) {
        fprintf(stderr,
                 "%s: Cannot get request context\n",
                 __FUNCTION__);
        return -1;
    }

    /* check if this is a POST operation */
    if(!(r->method & NGX_HTTP_POST)) {
        return rp_module_cmd_error(&ctx->json_root, "Expected POST method",
                                   NULL, r->pool);
    }

    /* check for payload buffers */
    if((ctx->in_buffer_len == 0) ||
       (ctx->in_buffer == NULL) ||
       (ctx->in_status != 0)) {
        fprintf(stderr, "Body is empty, unknown error\n");
        return -1;
    }

    /* parse incoming body to cJSON and search for 'params' */
    fprintf(stderr, "Bazaar install/remove: Received body: %s\n",
             ctx->in_buffer);

    urld = url_decode(ctx->in_buffer);
    cJSON_Minify(urld);

    /* Get rid of "payload=" header */
    char *urld_strip = memchr(urld, '{', 10);

    req_body = cJSON_Parse(urld_strip, r->pool);
    if (urld) free (urld);

    if(req_body == NULL) {
        fprintf(stderr, "Can not parse incoming body to JSON\n");
        return -1;
    }


    /* "command" object */
    j_cmd = cJSON_GetObjectItem(req_body, "command");
    if(j_cmd == NULL) {
        cJSON_Delete(req_body, r->pool);
        fprintf(stderr, "Can not find 'command' in req body\n");
        return -1;
    }

    /* Install/Upgrade */
    if ( !strncmp(j_cmd->valuestring, "install", sizeof("install")) ) {
        *act = eInstall;
        action = j_cmd->valuestring;
    }

    if ( !strncmp(j_cmd->valuestring, "upgrade", sizeof("upgrade")) ) {
        *act = eUpgrade;
        action = j_cmd->valuestring;
    }

    if ( (*act == eInstall) || (*act == eUpgrade) ) {
        /* "archive" object */
        j_url = cJSON_GetObjectItem(req_body, "archive");
        if(j_url == NULL) {
            cJSON_Delete(req_body, r->pool);
            fprintf(stderr, "Can not find 'archive' in req body\n");
            return -1;
        }

        /* "md5" object */
        j_md5 = cJSON_GetObjectItem(req_body, "md5");
        if(j_md5 == NULL) {
            cJSON_Delete(req_body, r->pool);
            fprintf(stderr, "Can not find 'md5' in req body\n");
            return -1;
        }
    }

    /* Uninstall */
    if (!strncmp(j_cmd->valuestring, "uninstall", sizeof("uninstall"))) {
        *act = eRemove;
        action = "remove";
    }

    /* Unknown action */
    if (!action) {
        cJSON_Delete(req_body, r->pool);
        fprintf(stderr, "Unknown action: %s\n",
                 j_cmd->valuestring);
        return -1;
    }

    /* "app_id" object */
    j_app = cJSON_GetObjectItem(req_body, "app_id");
    if(j_app == NULL) {
        cJSON_Delete(req_body, r->pool);
        fprintf(stderr, "Can not find 'app_id' in req body\n");
        return -1;
    }

    /* "token" object */
    j_tok = cJSON_GetObjectItem(req_body, "token");
    if(j_tok == NULL) {
        cJSON_Delete(req_body, r->pool);
        fprintf(stderr, "Can not find 'token' in req body\n");
        return -1;
    }
    if (strncmp(j_tok->valuestring, g_token, c_token_len)) {
        cJSON_Delete(req_body, r->pool);
        fprintf(stderr, "Unauthorized Bazaar %s request\n", action);
        return -1;
    }

    /* Call bazaar script */
    char  cmd[256];
    switch (*act) {
    case eInstall:
    case eUpgrade:
        fprintf(stderr, "Installing: %s\n", j_url->valuestring);
        sprintf(cmd, "bazaar install %s %s %s",
                j_app->valuestring,
                j_url->valuestring,
                j_md5->valuestring);
        break;

    case eRemove:
        fprintf(stderr, "Removing: %s\n", j_app->valuestring);
        sprintf(cmd, "bazaar remove %s",
                j_app->valuestring);
        break;

    default:
        fprintf(stderr, "Unknown Bazaar action: %s\n",
                 j_cmd->valuestring);
        ret = -1;
        goto out;

    }

    ret = system(cmd);

 out:
    /* release our resources */
    cJSON_Delete(req_body, r->pool);

    return ret;
}
예제 #7
0
/*----------------------------------------------------------------------------*/
int rp_bazaar_start(ngx_http_request_t *r,
                    cJSON **json_root, int argc, char **argv)
{
    char* url = strstr(argv[0], "?type=demo");
    if (url)
    {
        *url = '\0';
    }
    else
    {
       url = strstr(argv[0], "?type=run");
       if(url)
            *url = '\0';
    }

    int unsigned len;
    ngx_http_rp_loc_conf_t *lc =
        ngx_http_get_module_loc_conf(r, ngx_http_rp_module);

    if(argc != 1) {
        return rp_module_cmd_error(json_root,
                                "Incorrect number of arguments (should be 1)",
                                   NULL, r->pool);
    }

    /* Check if application is already running and unload it if so. */
    if(rp_module_ctx.app.handle != NULL) {
        if(rp_bazaar_app_unload_module(&rp_module_ctx.app)) {
            return rp_module_cmd_error(json_root,
                                       "Can not unload existing application.",
                                       NULL, r->pool);
        }
    }

    /* Application id string */
    len = strlen(argv[0]) + 1;
    rp_module_ctx.app.id = (char *)malloc(len);
    if(rp_module_ctx.app.id == NULL) {
        return rp_module_cmd_error(json_root, "Can not allocate memory",
                                   strerror(errno), r->pool);
    }
    strcpy(rp_module_ctx.app.id, argv[0]);

    /* Assemble the application and FPGA filename: <app_dir>/<app_id>/controllerhf.so */
    len = strlen((char *)lc->bazaar_dir.data) + strlen(argv[0]) + strlen("/controllerhf.so") + 2;
    char app_name[len];
    sprintf(app_name, "%s/%s/controllerhf.so", lc->bazaar_dir.data, argv[0]);
    app_name[len-1]='\0';

    /* Unload existing application before, new fpga load */
    if(rp_module_ctx.app.handle != NULL){
        if(rp_bazaar_app_unload_module(&rp_module_ctx.app)){
            return rp_module_cmd_error(json_root,
                                       "Cannot unload existing application.",
                                       NULL, r->pool);
        }
    }

    /* Get FPGA config file in <app_dir>/<app_id>/fpga.conf */
    char *fpga_name = NULL;
    if (system("/opt/redpitaya/rmamba_pl.sh"))
        fprintf(stderr, "Problem running /opt/redpitaya/rmamba_pl.sh\n");
    if(get_fpga_path((const char *)argv[0], (const char *)lc->bazaar_dir.data, &fpga_name) == 0) { // FIXME !!!
        /* Here we do not have application running anymore - load new FPGA */
        fprintf(stderr, "Loading specific FPGA from: '%s'\n", fpga_name);
        /* Try loading FPGA code
         *    - Test if fpga loaded correctly
         *    - Read/write permissions
         *    - File exists/not exists */
        switch (rp_bazaar_app_load_fpga(fpga_name)) {
            case FPGA_FIND_ERR:
                if (fpga_name)  free(fpga_name);
                return rp_module_cmd_error(json_root, "Cannot find fpga file.", NULL, r->pool);
            case FPGA_READ_ERR:
                if (fpga_name)  free(fpga_name);
                return rp_module_cmd_error(json_root, "Unable to read FPGA file.", NULL, r->pool);
            case FPGA_WRITE_ERR:
                if (fpga_name)  free(fpga_name);
                return rp_module_cmd_error(json_root, "Unable to write FPGA file into memory.", NULL, r->pool);
            /* App is a new app and doesn't need custom fpga.bit */
            case FPGA_NOT_REQ:
                if (fpga_name)  free(fpga_name);
                break;
            case FPGA_OK:
            {
                if (fpga_name)  free(fpga_name);
                char dmaDrv[len];
                len = strlen((char *)lc->bazaar_dir.data) + strlen(argv[0]) + strlen("/fpga.sh") + 2;
                sprintf(dmaDrv, "%s/%s/fpga.sh", lc->bazaar_dir.data, argv[0]);
                if (system(dmaDrv))
                    fprintf(stderr, "Problem running %s\n", dmaDrv);
                break;
            }
            default:
                if (fpga_name)  free(fpga_name);
                return rp_module_cmd_error(json_root, "Unknown error.", NULL, r->pool);
        }
    } else {
        fprintf(stderr, "Not loading specific FPGA, since no fpga.conf file was found.\n");
    }

    /* Load new application. */
    fprintf(stderr, "Loading application: '%s'\n", app_name);
    if(rp_bazaar_app_load_module(&app_name[0], &rp_module_ctx.app) < 0) {
        rp_bazaar_app_unload_module(&rp_module_ctx.app);
        return rp_module_cmd_error(json_root, "Can not load application.",
                                   NULL, r->pool);
    }

    if(rp_module_ctx.app.init_func() < 0) {
        rp_module_cmd_error(json_root,
                            "Application init failed, aborting",
                            NULL, r->pool);
        rp_bazaar_app_unload_module(&rp_module_ctx.app);
        return -1;
    }
    rp_module_ctx.app.initialized=1;
    fprintf(stderr, "Application loaded succesfully!\n");

    //start web socket server
    if(rp_module_ctx.app.ws_api_supported)
    {
        struct server_parameters params;
        ngx_memset(&params, 0, sizeof(struct server_parameters));

        params.set_params_interval_func = rp_module_ctx.app.ws_set_params_interval_func;
        params.set_signals_interval_func = rp_module_ctx.app.ws_set_signals_interval_func;
        params.get_params_interval_func = rp_module_ctx.app.ws_get_params_interval_func;
        params.get_signals_interval_func = rp_module_ctx.app.ws_get_signals_interval_func;
        params.get_params_func = rp_module_ctx.app.ws_get_params_func;
        params.set_params_func = rp_module_ctx.app.ws_set_params_func;
        params.get_signals_func = rp_module_ctx.app.ws_get_signals_func;
        params.set_signals_func = rp_module_ctx.app.ws_set_signals_func;
        params.gzip_func = rp_module_ctx.app.ws_gzip_func;
        fprintf(stderr, "Starting WS-server\n");

        start_ws_server(&params);
    }

    return rp_module_cmd_ok(json_root, r->pool);
}