#include #include #include #include #include #include #include #include #include #define UTIL_MOD_LINE_MAX 1024 static char * util_remove_spaces(char *str) { int i = 0; while (isspace(*str)) str++; i = strlen(str); while (isspace(str[i-1])) str[i-1]='\0'; return str; } int util_parse_modules_file_json(char *filename) { struct stat sb; memset(&sb, 0, sizeof(struct stat)); if (stat(filename, &sb) < 0) { perror("stat"); return -1; } FILE *mf = fopen(filename, "r"); if (!mf) { perror("fopen"); return -1; } char *filebuf = malloc(sb.st_size); memset(filebuf, 0, sb.st_size); int ret = fread(filebuf, sizeof(char), sb.st_size, mf); debuglog("size read: %d content: %s\n", ret, filebuf); if (ret != sb.st_size) { perror("fread"); return -1; } fclose(mf); jsmn_parser modp; jsmn_init(&modp); jsmntok_t toks[MOD_MAX * JSON_ELE_MAX]; int r = jsmn_parse(&modp, filebuf, strlen(filebuf), toks, sizeof(toks) / sizeof(toks[0])); if (r < 0) { debuglog("jsmn_parse: invalid JSON?\n"); return -1; } int nmods = 0; for (int i = 0; i < r; i++) { assert(toks[i].type == JSMN_OBJECT); char mname[MOD_NAME_MAX] = { 0 }; char mpath[MOD_PATH_MAX] = { 0 }; i32 nargs = 0; u32 udp_port = 0; i32 isactive = 0; for (int j = 1; j < (toks[i].size * 2); j+=2) { char val[256] = { 0 }, key[32] = { 0 }; sprintf(val, "%.*s", toks[j + i + 1].end - toks[j + i + 1].start, filebuf + toks[j + i + 1].start); sprintf(key, "%.*s", toks[j + i].end - toks[j + i].start, filebuf + toks[j + i].start); if (strcmp(key, "name") == 0) { strcpy(mname, val); } else if (strcmp(key, "path") == 0) { strcpy(mpath, val); } else if (strcmp(key, "port") == 0) { udp_port = atoi(val); } else if (strcmp(key, "argsize") == 0) { nargs = atoi(val); } else if (strcmp(key, "active") == 0) { isactive = (strcmp(val, "yes") == 0); } else { debuglog("Invalid (%s,%s)\n", key, val); } } i += (toks[i].size * 2); // do not load if it is not active if (isactive == 0) continue; struct module *m = module_alloc(mname, mpath, udp_port, nargs, 0, 0, 0, 0); assert(m); nmods++; } free(filebuf); assert(nmods); debuglog("Loaded %d module%s!\n", nmods, nmods > 1 ? "s" : ""); return 0; } /* * TEST data file should contain: * module_name: * and if your arg has to contain a ',', woops i can't deal with that for now! * if the first character in a line is ";", then the line is ignored! */ int parse_sandbox_file_custom(char *filename) { FILE *mf = fopen(filename, "r"); char buff[UTIL_MOD_LINE_MAX] = { 0 }; int total_boxes = 0; if (!mf) { perror("fopen"); return -1; } while (fgets(buff, UTIL_MOD_LINE_MAX, mf) != NULL) { char mname[MOD_NAME_MAX] = { 0 }; char *tok = NULL, *src = buff; struct module *mod = NULL; struct sandbox *sb = NULL; char *args = NULL; src = util_remove_spaces(src); if (src[0] == ';') goto next; if ((tok = strtok_r(src, ":", &src))) { int ntoks = 0; strncpy(mname, tok, MOD_NAME_MAX); mod = module_find(mname); assert(mod); if (mod->nargs > 0) { args = (char *)malloc(mod->nargs * MOD_ARG_MAX_SZ); assert(args); while ((tok = strtok_r(src, ",", &src))) { strncpy(args + (ntoks * MOD_ARG_MAX_SZ), tok, MOD_ARG_MAX_SZ); ntoks++; assert(ntoks < MOD_MAX_ARGS); } } } else { assert(0); } sb = sandbox_alloc(mod, args, NULL); assert(sb); total_boxes++; next: memset(buff, 0, UTIL_MOD_LINE_MAX); } assert(total_boxes); debuglog("Instantiated %d sandbox%s!\n", total_boxes, total_boxes > 1 ? "es" : ""); return 0; } struct sandbox * util_parse_sandbox_string_json(struct module *mod, char *str, const struct sockaddr *addr) { jsmn_parser sp; jsmntok_t tk[JSON_ELE_MAX]; jsmn_init(&sp); int r = jsmn_parse(&sp, str, strlen(str), tk, sizeof(tk)/sizeof(tk[0])); if (r < 1) { debuglog("Failed to parse string:%s\n", str); return NULL; } if (tk[0].type != JSMN_OBJECT) return NULL; for (int j = 1; j < r; j++) { char key[32] = { 0 }; sprintf(key, "%.*s", tk[j].end - tk[j].start, str + tk[j].start); if (strcmp(key, "module") == 0) { char name[32] = { 0 }; sprintf(name, "%.*s", tk[j + 1].end - tk[j + 1].start, str + tk[j + 1].start); if (strcmp(name, mod->name) != 0) return NULL; j++; } else if (strcmp(key, "args") == 0) { if (tk[j + 1].type != JSMN_ARRAY) return NULL; char *args = malloc(tk[j + 1].size * MOD_ARG_MAX_SZ); assert(args); for (int k = 1; k <= tk[j + 1].size; k++) { jsmntok_t *g = &tk[j + k + 1]; strncpy(args + ((k - 1) * MOD_ARG_MAX_SZ), str + g->start, g->end - g->start); *(args + ((k - 1) * MOD_ARG_MAX_SZ) + g->end - g->start) = '\0'; } struct sandbox *sb = sandbox_alloc(mod, args, addr); assert(sb); return sb; } else { return NULL; } } return NULL; } struct sandbox * util_parse_sandbox_string_custom(struct module *mod, char *str, const struct sockaddr *addr) { char *tok = NULL, *src = str; src = util_remove_spaces(src); if (src[0] == ';') return NULL; if (!(tok = strtok_r(src, ":", &src))) return NULL; if (strcmp(mod->name, tok)) return NULL; // struct module *mod = module_find(tok); // if (!mod) return NULL; assert(mod->nargs >= 0 && mod->nargs < MOD_MAX_ARGS); char *args = (char *)malloc(mod->nargs * MOD_ARG_MAX_SZ); assert(args); int ntoks = 0; while ((tok = strtok_r(src, ",", &src))) { strncpy(args + (ntoks * MOD_ARG_MAX_SZ), tok, MOD_ARG_MAX_SZ); ntoks++; assert(ntoks < MOD_MAX_ARGS); } struct sandbox *sb = sandbox_alloc(mod, args, addr); assert(sb); return sb; } /* * Each line in the file should be like: * * module_path:module_name:module_nargs:module_stack_size:module_max_heap_size[:moreargs::argn\n] * if the first character in a line is ";", then the line is ignored! */ int util_parse_modules_file_custom(char *filename) { FILE *mf = fopen(filename, "r"); char buff[UTIL_MOD_LINE_MAX] = { 0 }; int nmods = 0; if (!mf) { perror("fopen"); return -1; } while (fgets(buff, UTIL_MOD_LINE_MAX, mf) != NULL) { char mname[MOD_NAME_MAX] = { 0 }; char mpath[MOD_PATH_MAX] = { 0 }; i32 nargs = 0; u32 stack_sz = 0; u32 max_heap = 0; u32 timeout = 0; char *tok = NULL, *src = buff; u32 udp_port = 0; i32 ntoks = 0; src = util_remove_spaces(src); if (src[0] == ';') goto next; while ((tok = strtok_r(src, ":", &src))) { switch(ntoks) { case MOD_ARG_MODPATH: strncpy(mpath, tok, MOD_PATH_MAX); break; case MOD_ARG_MODPORT: udp_port = atoi(tok); case MOD_ARG_MODNAME: strncpy(mname, tok, MOD_NAME_MAX); break; case MOD_ARG_MODNARGS: nargs = atoi(tok); break; default: break; } ntoks++; } assert(ntoks >= MOD_ARG_MAX); struct module *m = module_alloc(mname, mpath, udp_port, nargs, 0, 0, 0, 0); assert(m); nmods++; next: memset(buff, 0, UTIL_MOD_LINE_MAX); } assert(nmods); debuglog("Loaded %d module%s!\n", nmods, nmods > 1 ? "s" : ""); fclose(mf); return 0; }