Browse Source

update: server daemon of ClearDNS

dev
dnomd343 3 years ago
parent
commit
b766d77595
  1. 1
      include/process.h
  2. 8
      src/CMakeLists.txt
  3. 27
      src/cleardns.c
  4. 2
      src/common.c
  5. 121
      src/process.c

1
include/process.h

@ -1,6 +1,7 @@
#ifndef _PROCESS_H_
#define _PROCESS_H_
void server_daemon();
void init_server(char *init_script, char *custom_script);
#endif

8
src/CMakeLists.txt

@ -1,7 +1,13 @@
cmake_minimum_required(VERSION 2.8.12)
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(/usr/lib/i386-linux-gnu/glib-2.0/include)
include_directories(/usr/lib/x86_64-linux-gnu/glib-2.0/include)
include_directories(/usr/lib/aarch64-linux-gnu/glib-2.0/include)
include_directories(/usr/lib64/glib-2.0/include)
include_directories(/usr/lib/glib-2.0/include)
include_directories(/usr/include/glib-2.0)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
add_executable(cleardns ${SRC})
#target_link_libraries(cleardns glib-2.0)
target_link_libraries(cleardns glib-2.0)

27
src/cleardns.c

@ -3,8 +3,6 @@
#include "common.h"
#include "process.h"
int debug_mode = 0;
char *init_script = "/usr/bin/load";
char *custom_script = "/etc/cleardns/custom.sh";
@ -14,14 +12,19 @@ char *upstream_config = "/etc/cleardns/upstream.json";
void show_command(char *title, char **command) {
int num = 0;
fprintf(stderr, "\n%s => ", title);
fprintf(stderr, "%s => \"", title);
while(command[num] != NULL) {
fprintf(stderr, "%s", command[num++]);
if (command[num] != NULL) {
fprintf(stderr, " ");
}
}
fprintf(stderr, "\n");
fprintf(stderr, "\"\n");
}
int main(int argc, char *argv[]) {
int debug_mode = 0;
fprintf(stderr, "[ClearDNS] Server start.\n");
for (char **p = argv; p < argv + argc; ++p) {
if (!strcmp(*p, "--debug")) { // --debug option
++debug_mode;
@ -30,17 +33,15 @@ int main(int argc, char *argv[]) {
load_start_command(adguard_workdir, overture_config, upstream_config, debug_mode); // generate commands
if (debug_mode) { // show exec command
char *line = "----------------------------------------------------------------";
fprintf(stderr, "\n%s%s\n", line, line);
show_command("crond", crond_command);
show_command("AdGuard", adguard_command);
show_command("overture", overture_command);
show_command("dnsproxy (domestic)", domestic_dnsproxy_command);
show_command("dnsproxy (foreign)", foreign_dnsproxy_command);
fprintf(stderr, "\n%s%s\n", line, line);
fprintf(stderr, "[ClearDNS] Debug mode.\n");
show_command("[ClearDNS] crond", crond_command);
show_command("[ClearDNS] adguard", adguard_command);
show_command("[ClearDNS] overture", overture_command);
show_command("[ClearDNS] dnsproxy (domestic)", domestic_dnsproxy_command);
show_command("[ClearDNS] dnsproxy (foreign)", foreign_dnsproxy_command);
}
init_server(init_script, custom_script);
server_daemon();
return 0;
}

2
src/common.c

@ -16,7 +16,7 @@ char** dnsproxy_config(char *port, cJSON *json, int is_debug);
void load_start_command(char *adguard_workdir, char *overture_config, char *upstream_config, int is_debug);
void error_exit(char *message) { // exit with code 1
fprintf(stderr, "%s\n", message);
fprintf(stderr, "[ClearDNS] %s\n", message);
exit(1);
}

121
src/process.c

@ -1,11 +1,102 @@
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include "common.h"
void process_exec() {
int exiting = 0;
pid_t crond_pid = 0;
pid_t adguard_pid = 0;
pid_t overture_pid = 0;
pid_t domestic_dnsproxy_pid = 0;
pid_t foreign_dnsproxy_pid = 0;
void server_exit();
void get_sub_exit();
void server_daemon();
pid_t process_exec(char **command);
void init_server(char *init_script, char *custom_script);
void server_exit() { // kill sub-process and exit
int status, ret;
exiting = 1;
fprintf(stderr, "[ClearDNS] Get exit signal.\n");
if (domestic_dnsproxy_pid != 0) {
fprintf(stderr, "[ClearDNS] Kill domestic dnsproxy. (pid = %d)\n", domestic_dnsproxy_pid);
kill(domestic_dnsproxy_pid, SIGTERM);
}
if (foreign_dnsproxy_pid != 0) {
fprintf(stderr, "[ClearDNS] Kill foreign dnsproxy. (pid = %d)\n", foreign_dnsproxy_pid);
kill(foreign_dnsproxy_pid, SIGTERM);
}
while ((ret = wait(&status)) != -1) {
fprintf(stderr, "[ClearDNS] Subprocess exit. (pid = %d)\n", ret);
}
printf("[ClearDNS] Exit successfully.\n");
exit(0);
}
void get_sub_exit() { // catch child process die
int ret, status;
int wait_time = 3; // seconds for wait before restart
if (exiting) { return; } // server daemon is exiting
if (domestic_dnsproxy_pid != 0) { // check domestic dnsproxy
ret = waitpid(domestic_dnsproxy_pid, &status, WNOHANG); // non-blocking
if (ret == -1) {
perror("[ClearDNS] Waitpid error");
server_exit();
} else if (ret) { // process exit
domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command);
fprintf(stderr, "[ClearDNS] Catch domestic dnsproxy exit and restart it. (pid = %d)\n", domestic_dnsproxy_pid);
sleep(wait_time); // reduce restart frequency
return;
}
}
if (foreign_dnsproxy_pid != 0) { // check foreign dnsproxy
ret = waitpid(foreign_dnsproxy_pid, &status, WNOHANG); // non-blocking
if (ret == -1) {
perror("[ClearDNS] Waitpid error");
server_exit();
} else if (ret) { // process exit
foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command);
fprintf(stderr, "[ClearDNS] Catch foreign dnsproxy exit and restart it. (pid = %d)\n", foreign_dnsproxy_pid);
sleep(wait_time); // reduce restart frequency
return;
}
}
ret = waitpid(-1, &status, WNOHANG); // waitpid for all sub-process (non-blocking)
if (ret == -1) {
perror("[ClearDNS] Waitpid error");
server_exit();
} else if (ret) { // process exit
fprintf(stderr, "[ClearDNS] Catch subprocess exit. (pid = %d)\n", ret);
return;
}
fprintf(stderr, "[ClearDNS] Subprocess not found.\n"); // get SIGCHLD signal but not exited subprocess found
}
pid_t process_exec(char **command) {
pid_t pid;
char **env = {NULL};
if ((pid = fork()) < 0) {
perror("[ClearDNS] Fork error");
exit(2);
} else if (pid == 0) { // child process
prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process
if (execvpe(command[0], command, env) < 0) {
perror("[ClearDNS] Exec error");
exit(3);
}
}
return pid;
}
void init_server(char *init_script, char *custom_script) { // run init script (blocking) / custom script (non-blocking)
@ -13,32 +104,48 @@ void init_server(char *init_script, char *custom_script) { // run init script (b
pid_t init_pid, custom_pid;
if ((init_pid = fork()) < 0) {
perror("Fork error");
perror("[ClearDNS] Fork error");
exit(2);
} else if (init_pid == 0) { // child process
prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process
if (execlp("/bin/sh", "/bin/sh", init_script, NULL)) {
perror("Init error");
perror("[ClearDNS] Init error");
exit(3);
}
}
wait(&status); // blocking wait
fprintf(stderr, "Init complete\n");
fprintf(stderr, "[ClearDNS] Init complete.\n");
if (access(custom_script, F_OK) >= 0) { // custom script exist
fprintf(stderr, "[ClearDNS] Running custom script.\n");
if ((custom_pid = fork()) < 0) {
perror("Fork error");
perror("[ClearDNS] Fork error");
exit(2);
} else if (custom_pid == 0) { // child process
prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process
if (execlp("/bin/sh", "/bin/sh", custom_script, NULL)) {
perror("Custom script error");
perror("[ClearDNS] Custom script error");
exit(3);
}
}
sleep(1); // wait a moment
}
}
void server_daemon() {
void server_daemon() { // run as a daemon of cleardns
int wait_us_time = 200 * 1000; // 200ms
signal(SIGINT, server_exit); // catch Ctrl + C (2)
signal(SIGTERM, server_exit); // catch exit signal (15)
signal(SIGCHLD, get_sub_exit); // callback when child process die
domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command);
fprintf(stderr, "[ClearDNS] Exec domestic dnsproxy. (pid = %d)\n", domestic_dnsproxy_pid);
usleep(wait_us_time);
foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command);
fprintf(stderr, "[ClearDNS] Exec foreign dnsproxy. (pid = %d)\n", foreign_dnsproxy_pid);
usleep(wait_us_time);
GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(main_loop);
}

Loading…
Cancel
Save