Browse Source

update: loader module

dev
dnomd343 2 years ago
parent
commit
a374fb4274
  1. 1
      include/applet/adguard.h
  2. 1
      include/applet/dnsproxy.h
  3. 1
      include/applet/overture.h
  4. 7
      include/common.h
  5. 2
      include/loader/config.h
  6. 5
      include/loader/loader.h
  7. 29
      src/applet/adguard.c
  8. 17
      src/applet/dnsproxy.c
  9. 22
      src/applet/overture.c
  10. 32
      src/cleardns.c
  11. 1
      src/loader/CMakeLists.txt
  12. 4
      src/loader/config.c
  13. 23
      src/loader/loader.c
  14. 124
      src/loader/parser.c
  15. 77
      src/utils/json.c
  16. 1
      src/utils/structure.c

1
include/applet/adguard.h

@ -14,6 +14,7 @@ typedef struct {
} adguard; } adguard;
adguard* adguard_init(); adguard* adguard_init();
void adguard_free(adguard *info);
process* adguard_load(adguard *info, const char *dir); process* adguard_load(adguard *info, const char *dir);
#endif #endif

1
include/applet/dnsproxy.h

@ -16,6 +16,7 @@ typedef struct {
char **primary; char **primary;
} dnsproxy; } dnsproxy;
void dnsproxy_free(dnsproxy *info);
dnsproxy* dnsproxy_init(uint16_t port); dnsproxy* dnsproxy_init(uint16_t port);
void dnsproxy_add_primary(dnsproxy *info, const char *server); void dnsproxy_add_primary(dnsproxy *info, const char *server);
void dnsproxy_add_fallback(dnsproxy *info, const char *server); void dnsproxy_add_fallback(dnsproxy *info, const char *server);

1
include/applet/overture.h

@ -20,6 +20,7 @@ typedef struct {
} overture; } overture;
overture* overture_init(); overture* overture_init();
void overture_free(overture *info);
process* overture_load(overture *info, const char *file); process* overture_load(overture *info, const char *file);
#endif #endif

7
include/common.h

@ -62,4 +62,11 @@ char* to_json(const char *config_file);
cJSON* json_field_get(cJSON *entry, const char *field); cJSON* json_field_get(cJSON *entry, const char *field);
void json_field_replace(cJSON *entry, const char *field, cJSON *content); void json_field_replace(cJSON *entry, const char *field, cJSON *content);
uint8_t json_bool_value(char *key, cJSON *json);
uint32_t** json_uint32_list_value(char *key, cJSON *json, uint32_t **uint32_list);
char** json_string_list_value(char *key, cJSON *json, char **string_list);
char* json_string_value(char* key, cJSON *json);
int json_int_value(char *key, cJSON *json);
uint8_t is_json_suffix(const char *file_name);
#endif #endif

2
include/loader/config.h

@ -1,7 +1,7 @@
#ifndef _CONFIG_H_ #ifndef _CONFIG_H_
#define _CONFIG_H_ #define _CONFIG_H_
#include "common.h" #include <stdint.h>
typedef struct { typedef struct {
uint16_t port; uint16_t port;

5
include/loader/loader.h

@ -1,14 +1,15 @@
#ifndef _LOADER_H_ #ifndef _LOADER_H_
#define _LOADER_H_ #define _LOADER_H_
#include "adguard.h"
#include "dnsproxy.h" #include "dnsproxy.h"
#include "overture.h" #include "overture.h"
struct { extern struct {
dnsproxy *domestic; dnsproxy *domestic;
dnsproxy *foreign; dnsproxy *foreign;
overture *diverter; overture *diverter;
// adguard adguard *filter;
} loader; } loader;
void load_config(const char *config_file); void load_config(const char *config_file);

29
src/applet/adguard.c

@ -7,9 +7,16 @@
void adguard_dump(adguard *info); void adguard_dump(adguard *info);
char *adguard_config(adguard *info, const char *raw_config); char *adguard_config(adguard *info, const char *raw_config);
adguard* adguard_init() { void adguard_free(adguard *info) { // free adguard options
free(info->upstream);
free(info->username);
free(info->password);
free(info);
}
adguard* adguard_init() { // init adguard options
adguard *info = (adguard *)malloc(sizeof(adguard)); adguard *info = (adguard *)malloc(sizeof(adguard));
char *port_str = uint32_to_string(DIVERTER_PORT); char *port_str = uint32_to_string(DIVERTER_PORT); // diverter port in string
info->debug = FALSE; info->debug = FALSE;
info->dns_port = DNS_PORT; info->dns_port = DNS_PORT;
info->web_port = ADGUARD_PORT; info->web_port = ADGUARD_PORT;
@ -20,7 +27,7 @@ adguard* adguard_init() {
return info; return info;
} }
void adguard_dump(adguard *info) { // show adguard info in debug log void adguard_dump(adguard *info) { // show adguard options in debug log
log_debug("AdGuardHome debug -> %s", show_bool(info->debug)); log_debug("AdGuardHome debug -> %s", show_bool(info->debug));
log_debug("AdGuardHome dns port -> %u", info->dns_port); log_debug("AdGuardHome dns port -> %u", info->dns_port);
log_debug("AdGuardHome web port -> %u", info->web_port); log_debug("AdGuardHome web port -> %u", info->web_port);
@ -35,7 +42,7 @@ char *adguard_config(adguard *info, const char *raw_config) { // modify adguard
log_fatal("AdGuardHome configure error"); log_fatal("AdGuardHome configure error");
} }
cJSON *user_config = cJSON_CreateObject(); cJSON *user_config = cJSON_CreateObject(); // setting up username and password
cJSON *users_config = cJSON_CreateArray(); cJSON *users_config = cJSON_CreateArray();
char *password = gen_bcrypt(info->password); char *password = gen_bcrypt(info->password);
cJSON_AddItemToObject(user_config, "name", cJSON_CreateString(info->username)); cJSON_AddItemToObject(user_config, "name", cJSON_CreateString(info->username));
@ -44,7 +51,7 @@ char *adguard_config(adguard *info, const char *raw_config) { // modify adguard
json_field_replace(json, "users", users_config); json_field_replace(json, "users", users_config);
free(password); free(password);
cJSON *dns = json_field_get(json, "dns"); cJSON *dns = json_field_get(json, "dns"); // setting up dns options
cJSON *upstream = cJSON_CreateArray(); cJSON *upstream = cJSON_CreateArray();
cJSON_AddItemToArray(upstream, cJSON_CreateString(info->upstream)); cJSON_AddItemToArray(upstream, cJSON_CreateString(info->upstream));
json_field_replace(dns, "port", cJSON_CreateNumber(info->dns_port)); json_field_replace(dns, "port", cJSON_CreateNumber(info->dns_port));
@ -53,12 +60,12 @@ char *adguard_config(adguard *info, const char *raw_config) { // modify adguard
json_field_replace(dns, "upstream_dns_file", cJSON_CreateString("")); json_field_replace(dns, "upstream_dns_file", cJSON_CreateString(""));
json_field_replace(dns, "bootstrap_dns", cJSON_CreateArray()); json_field_replace(dns, "bootstrap_dns", cJSON_CreateArray());
char *config = cJSON_Print(json); char *config = cJSON_Print(json); // generate json string
cJSON_free(json); cJSON_free(json);
return config; return config;
} }
process* adguard_load(adguard *info, const char *dir) { process* adguard_load(adguard *info, const char *dir) { // load adguard options
adguard_dump(info); adguard_dump(info);
if (!check_port(info->dns_port)) { // invalid dns port if (!check_port(info->dns_port)) { // invalid dns port
log_fatal("Invalid dns port `%u`", info->dns_port); log_fatal("Invalid dns port `%u`", info->dns_port);
@ -67,7 +74,7 @@ process* adguard_load(adguard *info, const char *dir) {
log_fatal("Invalid web port `%u`", info->web_port); log_fatal("Invalid web port `%u`", info->web_port);
} }
create_folder(dir); create_folder(dir); // ensure adguard work dir exist
char *adguard_config_ret; char *adguard_config_ret;
char *adguard_config_file = string_join(dir, "AdGuardHome.yaml"); char *adguard_config_file = string_join(dir, "AdGuardHome.yaml");
char *adguard_config_raw = to_json(adguard_config_file); char *adguard_config_raw = to_json(adguard_config_file);
@ -81,12 +88,12 @@ process* adguard_load(adguard *info, const char *dir) {
save_file(adguard_config_file, adguard_config_ret); // save modified configure save_file(adguard_config_file, adguard_config_ret); // save modified configure
free(adguard_config_file); free(adguard_config_file);
process *proc = process_init("AdGuardHome", ADGUARD_BIN); process *proc = process_init("AdGuardHome", ADGUARD_BIN); // generate adguard command
char *port_str = uint32_to_string(info->web_port); char *port_str = uint32_to_string(info->web_port);
process_add_arg(proc, "--no-check-update"); process_add_arg(proc, "--no-check-update"); // disable update check (invalid in docker)
process_add_arg(proc, "--work-dir"); process_add_arg(proc, "--work-dir");
process_add_arg(proc, dir); process_add_arg(proc, dir);
process_add_arg(proc, "--port"); process_add_arg(proc, "--port"); // web server port
process_add_arg(proc, port_str); process_add_arg(proc, port_str);
if (info->debug) { if (info->debug) {
process_add_arg(proc, "--verbose"); // adguard enable debug mode process_add_arg(proc, "--verbose"); // adguard enable debug mode

17
src/applet/dnsproxy.c

@ -20,6 +20,13 @@ void dnsproxy_add_bootstrap(dnsproxy *info, const char *server) { // add bootstr
info->bootstrap = string_list_append(info->bootstrap, server); info->bootstrap = string_list_append(info->bootstrap, server);
} }
void dnsproxy_free(dnsproxy *info) { // free dnsproxy options
string_list_free(info->bootstrap);
string_list_free(info->fallback);
string_list_free(info->primary);
free(info);
}
dnsproxy* dnsproxy_init(uint16_t port) { // init dnsproxy options dnsproxy* dnsproxy_init(uint16_t port) { // init dnsproxy options
dnsproxy *info = (dnsproxy *)malloc(sizeof(dnsproxy)); dnsproxy *info = (dnsproxy *)malloc(sizeof(dnsproxy));
info->port = port; info->port = port;
@ -34,7 +41,7 @@ dnsproxy* dnsproxy_init(uint16_t port) { // init dnsproxy options
return info; return info;
} }
void dnsproxy_dump(const char *caption, dnsproxy *info) { // show dnsproxy info in debug log void dnsproxy_dump(const char *caption, dnsproxy *info) { // show dnsproxy options in debug log
char *str_dump; char *str_dump;
log_debug("%s port -> %u", caption, info->port); log_debug("%s port -> %u", caption, info->port);
log_debug("%s cache -> %u", caption, info->cache); log_debug("%s cache -> %u", caption, info->cache);
@ -56,7 +63,7 @@ void dnsproxy_dump(const char *caption, dnsproxy *info) { // show dnsproxy info
free(str_dump); free(str_dump);
} }
process* dnsproxy_load(const char *caption, dnsproxy *info, const char *file) { process* dnsproxy_load(const char *caption, dnsproxy *info, const char *file) { // load dnsproxy options
dnsproxy_dump(caption, info); dnsproxy_dump(caption, info);
if (!check_port(info->port)) { // invalid server port if (!check_port(info->port)) { // invalid server port
log_fatal("Invalid port `%u`", info->port); log_fatal("Invalid port `%u`", info->port);
@ -65,15 +72,15 @@ process* dnsproxy_load(const char *caption, dnsproxy *info, const char *file) {
log_fatal("%s without primary dns server", caption); log_fatal("%s without primary dns server", caption);
} }
create_folder(WORK_DIR); create_folder(WORK_DIR); // ensure work dir exist
char *config = dnsproxy_config(info); // string config (JSON format) char *config = dnsproxy_config(info); // string config with json format
char *config_file = string_join(WORK_DIR, file); char *config_file = string_join(WORK_DIR, file);
save_file(config_file, config); // load dnsproxy configure save_file(config_file, config); // load dnsproxy configure
free(config_file); free(config_file);
free(config); free(config);
char *option = string_join("--config-path=", file); char *option = string_join("--config-path=", file);
process *proc = process_init(caption, DNSPROXY_BIN); process *proc = process_init(caption, DNSPROXY_BIN); // generate dnsproxy command
process_add_arg(proc, option); process_add_arg(proc, option);
if (info->debug) { if (info->debug) {
process_add_arg(proc, "--verbose"); // dnsproxy enable debug mode process_add_arg(proc, "--verbose"); // dnsproxy enable debug mode

22
src/applet/overture.c

@ -8,11 +8,21 @@
void overture_dump(overture *info); void overture_dump(overture *info);
char* overture_config(overture *info); char* overture_config(overture *info);
void overture_free(overture *info) { // free overture options
free(info->ttl_file); // free(NULL) is valid
free(info->host_file);
free(info->foreign_ip_file);
free(info->domestic_ip_file);
free(info->foreign_domain_file);
free(info->domestic_domain_file);
free(info);
}
overture* overture_init() { // init overture options overture* overture_init() { // init overture options
overture *info = (overture *)malloc(sizeof(overture)); overture *info = (overture *)malloc(sizeof(overture));
info->port = DIVERTER_PORT; info->port = DIVERTER_PORT;
info->debug = FALSE; info->debug = FALSE;
info->timeout = DIVERTER_TIMEOUT; // default timeout -> 6s info->timeout = DIVERTER_TIMEOUT; // default timeout
info->ttl_file = NULL; info->ttl_file = NULL;
info->host_file = NULL; info->host_file = NULL;
info->foreign_port = FOREIGN_PORT; info->foreign_port = FOREIGN_PORT;
@ -25,7 +35,7 @@ overture* overture_init() { // init overture options
return info; return info;
} }
void overture_dump(overture *info) { // show overture info in debug log void overture_dump(overture *info) { // show overture options in debug log
char *reject_type = uint32_list_dump(info->reject_type); char *reject_type = uint32_list_dump(info->reject_type);
log_debug("Overture port -> %u", info->port); log_debug("Overture port -> %u", info->port);
log_debug("Overture debug -> %s", show_bool(info->debug)); log_debug("Overture debug -> %s", show_bool(info->debug));
@ -42,23 +52,23 @@ void overture_dump(overture *info) { // show overture info in debug log
free(reject_type); free(reject_type);
} }
process* overture_load(overture *info, const char *file) { process* overture_load(overture *info, const char *file) { // load overture options
overture_dump(info); overture_dump(info);
if (!check_port(info->port)) { // invalid server port if (!check_port(info->port)) { // invalid server port
log_fatal("Invalid port `%u`", info->port); log_fatal("Invalid port `%u`", info->port);
} }
if (info->timeout == 0) { if (info->timeout == 0) { // invalid timeout value
log_fatal("Timeout of overture with invalid value 0"); log_fatal("Timeout of overture with invalid value 0");
} }
create_folder(WORK_DIR); create_folder(WORK_DIR); // ensure work dir exist
char *config = overture_config(info); // string config (JSON format) char *config = overture_config(info); // string config (JSON format)
char *config_file = string_join(WORK_DIR, file); char *config_file = string_join(WORK_DIR, file);
save_file(config_file, config); save_file(config_file, config);
free(config_file); free(config_file);
free(config); free(config);
process *proc = process_init("Overture", OVERTURE_BIN); process *proc = process_init("Overture", OVERTURE_BIN); // generate overture command
process_add_arg(proc, "-c"); process_add_arg(proc, "-c");
process_add_arg(proc, file); process_add_arg(proc, file);
if (info->debug) { if (info->debug) {

32
src/cleardns.c

@ -41,8 +41,8 @@ int main(int argc, char *argv[]) { // ClearDNS server
log_info("ClearDNS server start (%s)", VERSION); log_info("ClearDNS server start (%s)", VERSION);
// load_config("test.json"); load_config("test.json");
//
// dnsproxy_load("Domestic", loader.domestic, "domestic.json"); // dnsproxy_load("Domestic", loader.domestic, "domestic.json");
// dnsproxy_load("Foreign", loader.foreign, "foreign.json"); // dnsproxy_load("Foreign", loader.foreign, "foreign.json");
@ -110,20 +110,20 @@ int main(int argc, char *argv[]) { // ClearDNS server
// log_info("cwd -> %s", p->cwd); // log_info("cwd -> %s", p->cwd);
adguard *filter = adguard_init(); // adguard *filter = adguard_init();
//
filter->debug = TRUE; // filter->debug = TRUE;
filter->dns_port = 54; // filter->dns_port = 54;
filter->web_port = 8080; // filter->web_port = 8080;
filter->upstream = "127.0.0.1:5454"; // filter->upstream = "127.0.0.1:5454";
//
filter->username = "dnomd343"; // filter->username = "dnomd343";
filter->password = "password"; // filter->password = "password";
//
process *p = adguard_load(filter, "/cleardns/adguard/"); // process *p = adguard_load(filter, "/cleardns/adguard/");
log_info("cmd -> %s", string_list_dump(p->cmd)); // log_info("cmd -> %s", string_list_dump(p->cmd));
log_info("env -> %s", string_list_dump(p->env)); // log_info("env -> %s", string_list_dump(p->env));
log_info("cwd -> %s", p->cwd); // log_info("cwd -> %s", p->cwd);
// int debug_mode = 0; // int debug_mode = 0;

1
src/loader/CMakeLists.txt

@ -1,3 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8.12)
add_library(loader config.c loader.c parser.c) add_library(loader config.c loader.c parser.c)
target_link_libraries(loader applet)

4
src/loader/config.c

@ -1,13 +1,13 @@
#include <stdlib.h> #include <stdlib.h>
#include "common.h"
#include "config.h" #include "config.h"
#include "common.h"
#include "logger.h" #include "logger.h"
#include "structure.h" #include "structure.h"
cleardns_config* config_init() { // init config struct of cleardns cleardns_config* config_init() { // init config struct of cleardns
cleardns_config *config = (cleardns_config *)malloc(sizeof(cleardns_config)); cleardns_config *config = (cleardns_config *)malloc(sizeof(cleardns_config));
config->port = DNS_PORT; config->port = DNS_PORT;
config->cache.size = 0; config->cache.size = 0; // disable cache in default
config->cache.enable = FALSE; config->cache.enable = FALSE;
config->cache.optimistic = FALSE; config->cache.optimistic = FALSE;

23
src/loader/loader.c

@ -1,4 +1,3 @@
#include <stdlib.h>
#include "loader.h" #include "loader.h"
#include "config.h" #include "config.h"
#include "parser.h" #include "parser.h"
@ -34,9 +33,8 @@ dnsproxy* load_foreign(cleardns_config *config) {
} }
overture* load_diverter(cleardns_config *config) { overture* load_diverter(cleardns_config *config) {
overture *diverter = overture_init(config->diverter.port); overture *diverter = overture_init();
// timeout
// ttl_file // ttl_file
// host_file // host_file
// foreign_port // foreign_port
@ -48,9 +46,26 @@ overture* load_diverter(cleardns_config *config) {
// domestic_ip_file // domestic_ip_file
// foreign_domain_file // foreign_domain_file
// domestic_domain_file // domestic_domain_file
// TODO: load assets file
return diverter; return diverter;
} }
adguard* load_filter(cleardns_config *config) {
adguard *filter = adguard_init();
// dns_port
// web_port
// upstream
// username
// password
return filter;
}
void load_config(const char *config_file) { void load_config(const char *config_file) {
cleardns_config *config = config_init(); cleardns_config *config = config_init();
config_parser(config, config_file); config_parser(config, config_file);
@ -61,6 +76,6 @@ void load_config(const char *config_file) {
loader.domestic = load_domestic(config); loader.domestic = load_domestic(config);
loader.foreign = load_foreign(config); loader.foreign = load_foreign(config);
loader.diverter = load_diverter(config); loader.diverter = load_diverter(config);
// load adguard loader.filter = load_filter(config);
config_free(config); config_free(config);
} }

124
src/loader/parser.c

@ -4,75 +4,8 @@
#include "common.h" #include "common.h"
#include "logger.h" #include "logger.h"
#include "config.h" #include "config.h"
#include "structure.h"
int json_int_value(char *key, cJSON *json) { // json int or string value -> int void cache_parser(cache_config *config, cJSON *json) { // cache options parser
if (cJSON_IsNumber(json)) {
return json->valueint;
} else if (cJSON_IsString(json)) {
char *p;
int int_ret = (int)strtol(json->valuestring, &p, 10);
if (int_ret == 0 && strcmp(json->valuestring, "0") != 0) { // invalid number in string
log_fatal("`%s` not a valid number", key);
}
return int_ret;
} else {
log_fatal("`%s` must be number or string", key);
}
return 0; // never reach
}
char* json_string_value(char* key, cJSON *json) {
if (!cJSON_IsString(json)) {
log_fatal("`%s` must be string", key);
}
return json->valuestring;
}
char** json_string_list_value(char *key, cJSON *json, char **string_list) {
if (cJSON_IsString(json)) {
string_list = string_list_append(string_list, json->valuestring);
} else if (cJSON_IsArray(json)) {
json = json->child;
while (json != NULL) {
if (!cJSON_IsString(json)) {
log_fatal("`%s` must be string array", key);
}
string_list = string_list_append(string_list, json->valuestring);
json = json->next; // next field
}
} else if (!cJSON_IsNull(json)) {
log_fatal("`%s` must be array or string", key);
}
return string_list;
}
uint32_t** json_uint32_list_value(char *key, cJSON *json, uint32_t **uint32_list) {
if (cJSON_IsNumber(json)) {
uint32_list = uint32_list_append(uint32_list, json->valueint);
} else if (cJSON_IsArray(json)) {
json = json->child;
while (json != NULL) {
if (!cJSON_IsNumber(json)) {
log_fatal("`%s` must be number array", key);
}
uint32_list = uint32_list_append(uint32_list, json->valueint);
json = json->next; // next field
}
} else if (!cJSON_IsNull(json)) {
log_fatal("`%s` must be array or number", key);
}
return uint32_list;
}
uint8_t json_bool_value(char *key, cJSON *json) { // json bool value -> bool
if (!cJSON_IsBool(json)) {
log_fatal("`%s` must be boolean", key);
}
return json->valueint;
}
void json_cache_parser(cache_config *config, cJSON *json) { // cache options parser
if (!cJSON_IsObject(json)) { if (!cJSON_IsObject(json)) {
log_fatal("`cache` must be object"); log_fatal("`cache` must be object");
} }
@ -91,7 +24,7 @@ void json_cache_parser(cache_config *config, cJSON *json) { // cache options par
} }
} }
void json_upstream_parser(char *caption, upstream_config *config, cJSON *json) { void upstream_parser(char *caption, upstream_config *config, cJSON *json) { // upstream options parser
if (!cJSON_IsObject(json)) { if (!cJSON_IsObject(json)) {
log_fatal("`%s` must be object", caption); log_fatal("`%s` must be object", caption);
} }
@ -132,7 +65,7 @@ void json_upstream_parser(char *caption, upstream_config *config, cJSON *json) {
} }
} }
void json_diverter_parser(diverter_config *config, cJSON *json) { // diverter options parser void diverter_parser(diverter_config *config, cJSON *json) { // diverter options parser
if (!cJSON_IsObject(json)) { if (!cJSON_IsObject(json)) {
log_fatal("`diverter` must be object"); log_fatal("`diverter` must be object");
} }
@ -154,7 +87,7 @@ void json_diverter_parser(diverter_config *config, cJSON *json) { // diverter op
} }
} }
void json_adguard_parser(adguard_config *config, cJSON *json) { // adguard options parser void adguard_parser(adguard_config *config, cJSON *json) { // adguard options parser
if (!cJSON_IsObject(json)) { if (!cJSON_IsObject(json)) {
log_fatal("`adguard` must be array"); log_fatal("`adguard` must be array");
} }
@ -167,19 +100,21 @@ void json_adguard_parser(adguard_config *config, cJSON *json) { // adguard optio
config->enable = json_bool_value("adguard.enable", json); config->enable = json_bool_value("adguard.enable", json);
} }
if (!strcmp(json->string, "username")) { if (!strcmp(json->string, "username")) {
free(config->username);
config->username = json_string_value("adguard.username", json); config->username = json_string_value("adguard.username", json);
} }
if (!strcmp(json->string, "password")) { if (!strcmp(json->string, "password")) {
free(config->password);
config->password = json_string_value("adguard.password", json); config->password = json_string_value("adguard.password", json);
} }
json = json->next; // next field json = json->next; // next field
} }
} }
void json_config_parser(cleardns_config *config, const char *config_content) { // JSON format configure void cleardns_parser(cleardns_config *config, const char *config_content) { // JSON format configure
cJSON *json = cJSON_Parse(config_content); cJSON *json = cJSON_Parse(config_content);
if (json == NULL) { if (json == NULL) {
log_fatal("JSON configure format error"); log_fatal("ClearDNS configure format error");
} }
json = json->child; json = json->child;
while (json != NULL) { while (json != NULL) {
@ -187,19 +122,19 @@ void json_config_parser(cleardns_config *config, const char *config_content) { /
config->port = json_int_value("port", json); config->port = json_int_value("port", json);
} }
if (!strcmp(json->string, "cache")) { if (!strcmp(json->string, "cache")) {
json_cache_parser(&config->cache, json); cache_parser(&config->cache, json);
} }
if (!strcmp(json->string, "domestic")) { if (!strcmp(json->string, "domestic")) {
json_upstream_parser("domestic", &config->domestic, json); upstream_parser("domestic", &config->domestic, json);
} }
if (!strcmp(json->string, "foreign")) { if (!strcmp(json->string, "foreign")) {
json_upstream_parser("foreign", &config->foreign, json); upstream_parser("foreign", &config->foreign, json);
} }
if (!strcmp(json->string, "diverter")) { if (!strcmp(json->string, "diverter")) {
json_diverter_parser(&config->diverter, json); diverter_parser(&config->diverter, json);
} }
if (!strcmp(json->string, "adguard")) { if (!strcmp(json->string, "adguard")) {
json_adguard_parser(&config->adguard, json); adguard_parser(&config->adguard, json);
} }
if (!strcmp(json->string, "reject")) { if (!strcmp(json->string, "reject")) {
config->reject = json_uint32_list_value("reject", json, config->reject); config->reject = json_uint32_list_value("reject", json, config->reject);
@ -215,31 +150,20 @@ void json_config_parser(cleardns_config *config, const char *config_content) { /
cJSON_free(json); // free JSON struct cJSON_free(json); // free JSON struct
} }
void yaml_config_parser(cleardns_config *config, const char *config_content) { // YAML format configure
// TODO: change YAML -> JSON
char *json_content = string_init(config_content); // just demo for now
json_config_parser(config, json_content);
}
uint8_t is_json_suffix(const char *file_name) {
if (strlen(file_name) <= 5) { // `.json`
return FALSE;
}
if (!strcmp(file_name + strlen(file_name) - 5, ".json")) {
return TRUE;
}
return FALSE;
}
void config_parser(cleardns_config *config, const char *config_file) { void config_parser(cleardns_config *config, const char *config_file) {
char *config_content = read_file(config_file); char *config_content = read_file(config_file);
if (is_json_suffix(config_file)) { if (is_json_suffix(config_file)) { // JSON format
log_info("Start JSON configure parser"); log_info("Start JSON configure parser");
json_config_parser(config, config_content); cleardns_parser(config, config_content); // configure parser
} else { } else { // YAML or TOML format
log_info("Start YAML configure parser"); log_info("Start configure parser");
yaml_config_parser(config, config_content); char *json_content = to_json(config_content); // convert to json format
if (json_content == NULL) {
log_fatal("Configure parser error");
}
cleardns_parser(config, json_content); // configure parser
free(json_content);
} }
free(config_content);
log_info("Configure parser success"); log_info("Configure parser success");
} }

77
src/utils/json.c

@ -4,6 +4,7 @@
#include "cJSON.h" #include "cJSON.h"
#include "logger.h" #include "logger.h"
#include "common.h" #include "common.h"
#include "structure.h"
char* to_json(const char *file) { char* to_json(const char *file) {
char flag[9]; char flag[9];
@ -36,6 +37,72 @@ void json_field_replace(cJSON *entry, const char *field, cJSON *content) {
} }
} }
int json_int_value(char *key, cJSON *json) { // json int or string value -> int
if (cJSON_IsNumber(json)) {
return json->valueint;
} else if (cJSON_IsString(json)) {
char *p;
int int_ret = (int)strtol(json->valuestring, &p, 10);
if (int_ret == 0 && strcmp(json->valuestring, "0") != 0) { // invalid number in string
log_fatal("`%s` not a valid number", key);
}
return int_ret;
} else {
log_fatal("`%s` must be number or string", key);
}
return 0; // never reach
}
char* json_string_value(char* key, cJSON *json) {
if (!cJSON_IsString(json)) {
log_fatal("`%s` must be string", key);
}
return string_init(json->valuestring);
}
char** json_string_list_value(char *key, cJSON *json, char **string_list) {
if (cJSON_IsString(json)) {
string_list = string_list_append(string_list, json->valuestring);
} else if (cJSON_IsArray(json)) {
json = json->child;
while (json != NULL) {
if (!cJSON_IsString(json)) {
log_fatal("`%s` must be string array", key);
}
string_list = string_list_append(string_list, json->valuestring);
json = json->next; // next field
}
} else if (!cJSON_IsNull(json)) {
log_fatal("`%s` must be array or string", key);
}
return string_list;
}
uint32_t** json_uint32_list_value(char *key, cJSON *json, uint32_t **uint32_list) {
if (cJSON_IsNumber(json)) {
uint32_list = uint32_list_append(uint32_list, json->valueint);
} else if (cJSON_IsArray(json)) {
json = json->child;
while (json != NULL) {
if (!cJSON_IsNumber(json)) {
log_fatal("`%s` must be number array", key);
}
uint32_list = uint32_list_append(uint32_list, json->valueint);
json = json->next; // next field
}
} else if (!cJSON_IsNull(json)) {
log_fatal("`%s` must be array or number", key);
}
return uint32_list;
}
uint8_t json_bool_value(char *key, cJSON *json) { // json bool value -> bool
if (!cJSON_IsBool(json)) {
log_fatal("`%s` must be boolean", key);
}
return json->valueint;
}
cJSON* json_field_get(cJSON *entry, const char *field) { cJSON* json_field_get(cJSON *entry, const char *field) {
cJSON *sub = entry->child; cJSON *sub = entry->child;
while (sub != NULL) { while (sub != NULL) {
@ -48,3 +115,13 @@ cJSON* json_field_get(cJSON *entry, const char *field) {
cJSON_AddItemToObject(entry, field, new); cJSON_AddItemToObject(entry, field, new);
return new; return new;
} }
uint8_t is_json_suffix(const char *file_name) {
if (strlen(file_name) <= 5) { // `.json`
return FALSE;
}
if (!strcmp(file_name + strlen(file_name) - 5, ".json")) {
return TRUE;
}
return FALSE;
}

1
src/utils/structure.c

@ -1,5 +1,4 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "structure.h" #include "structure.h"

Loading…
Cancel
Save