static char *to_string(const json_value *value) { if (value->type == json_string) { return ss_strndup(value->u.string.ptr, value->u.string.length); } else if (value->type == json_integer) { #ifdef __MINGW32__ return strdup(ss_itoa(value->u.integer)); #else return strdup(itoa(value->u.integer)); #endif } else if (value->type == json_null) { return "null"; } else { LOGE("%d", value->type); FATAL("Invalid config format."); } return 0; }
void parse_addr(const char *str, ss_addr_t *addr) { int ret = -1, n = 0; char *pch; pch = strchr(str, ':'); while (pch != NULL) { n++; ret = pch - str; pch = strchr(pch + 1, ':'); } if (n > 1) { if (strcmp(str+ret, "]") != 0) { ret = -1; } } if (ret == -1) { addr->host = strdup(str); addr->port = NULL; } else { addr->host = ss_strndup(str, ret); addr->port = strdup(str + ret + 1); } }
static void parse_addr_cidr(const char *str, char **host, int *cidr) { int ret = -1, n = 0; char *pch; pch = strchr(str, '/'); while (pch != NULL) { n++; ret = pch - str; pch = strchr(pch + 1, '/'); } if (n > 1) { if (strcmp(str+ret, "]") != 0) { ret = -1; } } if (ret == -1) { *host = strdup(str); *cidr = -1; } else { *host = ss_strndup(str, ret); *cidr = atoi(strdup(str + ret + 1)); } }
void parse_addr(const char *str, ss_addr_t *addr) { int ipv6 = 0, ret = -1, n = 0; char *pch; struct cork_ip ip; if (cork_ip_init(&ip, str) != -1) { addr->host = strdup(str); addr->port = NULL; return; } pch = strchr(str, ':'); while (pch != NULL) { n++; ret = pch - str; pch = strchr(pch + 1, ':'); } if (n > 1) { ipv6 = 1; if (str[ret - 1] != ']') { ret = -1; } } if (ret == -1) { if (ipv6) { addr->host = ss_strndup(str + 1, strlen(str) - 2); } else { addr->host = strdup(str); } addr->port = NULL; } else { if (ipv6) { addr->host = ss_strndup(str + 1, ret - 2); } else { addr->host = ss_strndup(str, ret); } addr->port = strdup(str + ret + 1); } }
jconf_t *read_jconf(const char *file) { static jconf_t conf; char *buf; json_value *obj; FILE *f = fopen(file, "rb"); if (f == NULL) { FATAL("Invalid config path."); } fseek(f, 0, SEEK_END); long pos = ftell(f); fseek(f, 0, SEEK_SET); if (pos >= MAX_CONF_SIZE) { FATAL("Too large config file."); } buf = ss_malloc(pos + 1); if (buf == NULL) { FATAL("No enough memory."); } int nread = fread(buf, pos, 1, f); if (!nread) { FATAL("Failed to read the config file."); } fclose(f); buf[pos] = '\0'; // end of string json_settings settings = { 0UL, 0, NULL, NULL, NULL }; char error_buf[512]; obj = json_parse_ex(&settings, buf, pos, error_buf); if (obj == NULL) { FATAL(error_buf); } if (obj->type == json_object) { unsigned int i, j; for (i = 0; i < obj->u.object.length; i++) { char *name = obj->u.object.values[i].name; json_value *value = obj->u.object.values[i].value; if (strcmp(name, "server") == 0) { if (value->type == json_array) { for (j = 0; j < value->u.array.length; j++) { if (j >= MAX_REMOTE_NUM) { break; } json_value *v = value->u.array.values[j]; parse_addr(to_string(v), conf.remote_addr + j); conf.remote_num = j + 1; } } else if (value->type == json_string) { conf.remote_addr[0].host = to_string(value); conf.remote_addr[0].port = NULL; conf.remote_num = 1; } } else if (strcmp(name, "port_password") == 0) { if (value->type == json_object) { for (j = 0; j < value->u.object.length; j++) { if (j >= MAX_PORT_NUM) { break; } json_value *v = value->u.object.values[j].value; if (v->type == json_string) { conf.port_password[j].port = ss_strndup(value->u.object.values[j].name, value->u.object.values[j].name_length); conf.port_password[j].password = to_string(v); conf.port_password_num = j + 1; } } } } else if (strcmp(name, "server_port") == 0) { conf.remote_port = to_string(value); } else if (strcmp(name, "local_address") == 0) { conf.local_addr = to_string(value); } else if (strcmp(name, "local_port") == 0) { conf.local_port = to_string(value); } else if (strcmp(name, "password") == 0) { conf.password = to_string(value); } else if (strcmp(name, "method") == 0) { conf.method = to_string(value); } else if (strcmp(name, "timeout") == 0) { conf.timeout = to_string(value); } else if (strcmp(name, "fast_open") == 0) { conf.fast_open = value->u.boolean; } else if (strcmp(name, "auth") == 0) { conf.auth = value->u.boolean; } else if (strcmp(name, "nofile") == 0) { conf.nofile = value->u.integer; } else if (strcmp(name, "nameserver") == 0) { conf.nameserver = to_string(value); } } } else { FATAL("Invalid config file"); } ss_free(buf); json_value_free(obj); return &conf; }