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_init();
void adguard_free(adguard *info);
process* adguard_load(adguard *info, const char *dir);
#endif

1
include/applet/dnsproxy.h

@ -16,6 +16,7 @@ typedef struct {
char **primary;
} dnsproxy;
void dnsproxy_free(dnsproxy *info);
dnsproxy* dnsproxy_init(uint16_t port);
void dnsproxy_add_primary(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_init();
void overture_free(overture *info);
process* overture_load(overture *info, const char *file);
#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);
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

2
include/loader/config.h

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

5
include/loader/loader.h

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

29
src/applet/adguard.c

@ -7,9 +7,16 @@
void adguard_dump(adguard *info);
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));
char *port_str = uint32_to_string(DIVERTER_PORT);
char *port_str = uint32_to_string(DIVERTER_PORT); // diverter port in string
info->debug = FALSE;
info->dns_port = DNS_PORT;
info->web_port = ADGUARD_PORT;
@ -20,7 +27,7 @@ adguard* adguard_init() {
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 dns port -> %u", info->dns_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");
}
cJSON *user_config = cJSON_CreateObject();
cJSON *user_config = cJSON_CreateObject(); // setting up username and password
cJSON *users_config = cJSON_CreateArray();
char *password = gen_bcrypt(info->password);
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);
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_AddItemToArray(upstream, cJSON_CreateString(info->upstream));
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, "bootstrap_dns", cJSON_CreateArray());
char *config = cJSON_Print(json);
char *config = cJSON_Print(json); // generate json string
cJSON_free(json);
return config;
}
process* adguard_load(adguard *info, const char *dir) {
process* adguard_load(adguard *info, const char *dir) { // load adguard options
adguard_dump(info);
if (!check_port(info->dns_port)) { // invalid 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);
}
create_folder(dir);
create_folder(dir); // ensure adguard work dir exist
char *adguard_config_ret;
char *adguard_config_file = string_join(dir, "AdGuardHome.yaml");
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
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);
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, dir);
process_add_arg(proc, "--port");
process_add_arg(proc, "--port"); // web server port
process_add_arg(proc, port_str);
if (info->debug) {
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);
}
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 *info = (dnsproxy *)malloc(sizeof(dnsproxy));
info->port = port;
@ -34,7 +41,7 @@ dnsproxy* dnsproxy_init(uint16_t port) { // init dnsproxy options
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;
log_debug("%s port -> %u", caption, info->port);
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);
}
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);
if (!check_port(info->port)) { // invalid server 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);
}
create_folder(WORK_DIR);
char *config = dnsproxy_config(info); // string config (JSON format)
create_folder(WORK_DIR); // ensure work dir exist
char *config = dnsproxy_config(info); // string config with json format
char *config_file = string_join(WORK_DIR, file);
save_file(config_file, config); // load dnsproxy configure
free(config_file);
free(config);
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);
if (info->debug) {
process_add_arg(proc, "--verbose"); // dnsproxy enable debug mode

22
src/applet/overture.c

@ -8,11 +8,21 @@
void overture_dump(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 *info = (overture *)malloc(sizeof(overture));
info->port = DIVERTER_PORT;
info->debug = FALSE;
info->timeout = DIVERTER_TIMEOUT; // default timeout -> 6s
info->timeout = DIVERTER_TIMEOUT; // default timeout
info->ttl_file = NULL;
info->host_file = NULL;
info->foreign_port = FOREIGN_PORT;
@ -25,7 +35,7 @@ overture* overture_init() { // init overture options
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);
log_debug("Overture port -> %u", info->port);
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);
}
process* overture_load(overture *info, const char *file) {
process* overture_load(overture *info, const char *file) { // load overture options
overture_dump(info);
if (!check_port(info->port)) { // invalid server 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");
}
create_folder(WORK_DIR);
create_folder(WORK_DIR); // ensure work dir exist
char *config = overture_config(info); // string config (JSON format)
char *config_file = string_join(WORK_DIR, file);
save_file(config_file, config);
free(config_file);
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, file);
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);
// load_config("test.json");
//
load_config("test.json");
// dnsproxy_load("Domestic", loader.domestic, "domestic.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);
adguard *filter = adguard_init();
filter->debug = TRUE;
filter->dns_port = 54;
filter->web_port = 8080;
filter->upstream = "127.0.0.1:5454";
filter->username = "dnomd343";
filter->password = "password";
process *p = adguard_load(filter, "/cleardns/adguard/");
log_info("cmd -> %s", string_list_dump(p->cmd));
log_info("env -> %s", string_list_dump(p->env));
log_info("cwd -> %s", p->cwd);
// adguard *filter = adguard_init();
//
// filter->debug = TRUE;
// filter->dns_port = 54;
// filter->web_port = 8080;
// filter->upstream = "127.0.0.1:5454";
//
// filter->username = "dnomd343";
// filter->password = "password";
//
// process *p = adguard_load(filter, "/cleardns/adguard/");
// log_info("cmd -> %s", string_list_dump(p->cmd));
// log_info("env -> %s", string_list_dump(p->env));
// log_info("cwd -> %s", p->cwd);
// int debug_mode = 0;

1
src/loader/CMakeLists.txt

@ -1,3 +1,4 @@
cmake_minimum_required(VERSION 2.8.12)
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 "common.h"
#include "config.h"
#include "common.h"
#include "logger.h"
#include "structure.h"
cleardns_config* config_init() { // init config struct of cleardns
cleardns_config *config = (cleardns_config *)malloc(sizeof(cleardns_config));
config->port = DNS_PORT;
config->cache.size = 0;
config->cache.size = 0; // disable cache in default
config->cache.enable = FALSE;
config->cache.optimistic = FALSE;

23
src/loader/loader.c

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

124
src/loader/parser.c

@ -4,75 +4,8 @@
#include "common.h"
#include "logger.h"
#include "config.h"
#include "structure.h"
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 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
void cache_parser(cache_config *config, cJSON *json) { // cache options parser
if (!cJSON_IsObject(json)) {
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)) {
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)) {
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)) {
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);
}
if (!strcmp(json->string, "username")) {
free(config->username);
config->username = json_string_value("adguard.username", json);
}
if (!strcmp(json->string, "password")) {
free(config->password);
config->password = json_string_value("adguard.password", json);
}
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);
if (json == NULL) {
log_fatal("JSON configure format error");
log_fatal("ClearDNS configure format error");
}
json = json->child;
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);
}
if (!strcmp(json->string, "cache")) {
json_cache_parser(&config->cache, json);
cache_parser(&config->cache, json);
}
if (!strcmp(json->string, "domestic")) {
json_upstream_parser("domestic", &config->domestic, json);
upstream_parser("domestic", &config->domestic, json);
}
if (!strcmp(json->string, "foreign")) {
json_upstream_parser("foreign", &config->foreign, json);
upstream_parser("foreign", &config->foreign, json);
}
if (!strcmp(json->string, "diverter")) {
json_diverter_parser(&config->diverter, json);
diverter_parser(&config->diverter, json);
}
if (!strcmp(json->string, "adguard")) {
json_adguard_parser(&config->adguard, json);
adguard_parser(&config->adguard, json);
}
if (!strcmp(json->string, "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
}
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) {
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");
json_config_parser(config, config_content);
} else {
log_info("Start YAML configure parser");
yaml_config_parser(config, config_content);
cleardns_parser(config, config_content); // configure parser
} else { // YAML or TOML format
log_info("Start configure parser");
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");
}

77
src/utils/json.c

@ -4,6 +4,7 @@
#include "cJSON.h"
#include "logger.h"
#include "common.h"
#include "structure.h"
char* to_json(const char *file) {
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 *sub = entry->child;
while (sub != NULL) {
@ -48,3 +115,13 @@ cJSON* json_field_get(cJSON *entry, const char *field) {
cJSON_AddItemToObject(entry, field, 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 <string.h>
#include <stdlib.h>
#include "structure.h"

Loading…
Cancel
Save