HttpDNS/main.c
2021-06-12 09:50:56 +08:00

168 lines
4.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <dirent.h>
#include <pthread.h>
#include "main.h"
#define SERVICE_TYPE_STOP 1
#define SERVICE_TYPE_STATUS 2
#define SERVICE_TYPE_STATUS_NOT_PRINT 3
struct global global;
uint16_t tcp_listen_port;
struct httpudp udp;
static char *get_proc_name(char *path)
{
char proc_name[257];
FILE *fp;
int readsize;
fp = fopen(path, "r");
if (fp == NULL)
return NULL;
readsize = fread(proc_name, 1, 256, fp);
fclose(fp);
return strndup(proc_name, readsize - 1);
}
static int8_t additional_service(char *self_name, uint8_t service_type)
{
char commpath[270];
DIR *DP;
struct dirent *dp;
char *proc_name;
pid_t self_pid;
DP = opendir("/proc");
if (DP == NULL)
return 1;
proc_name = strrchr(self_name, '/');
if (proc_name)
self_name = proc_name + 1;
self_pid = getpid();
while ((dp = readdir(DP)) != NULL) {
if (dp->d_type != DT_DIR)
continue;
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0 || atoi(dp->d_name) == self_pid)
continue;
sprintf(commpath, "/proc/%s/comm", dp->d_name);
proc_name = get_proc_name(commpath);
if (proc_name == NULL)
continue;
if (strcmp(proc_name, self_name) == 0) {
if (service_type == SERVICE_TYPE_STOP)
kill(atoi(dp->d_name), SIGTERM);
else {
free(proc_name);
closedir(DP);
if (service_type != SERVICE_TYPE_STATUS_NOT_PRINT)
LOG(RED "%s(" VERSION ") 正在运行\n" NONE, self_name);
return 0;
}
}
free(proc_name);
}
closedir(DP);
if (service_type == SERVICE_TYPE_STATUS)
LOG(RED "%s(" VERSION ") 没有运行\n" NONE, self_name);
else if (service_type == SERVICE_TYPE_STATUS_NOT_PRINT)
return 1;
return 0;
}
void *timeout_check(void *nullPtr)
{
while (1) {
sleep(60);
if (global.dns_listen_fd >= 0)
dns_timeout_check();
}
return NULL;
}
/* 初始化变量 */
static void initVariable()
{
memset(&global, 0, sizeof(global));
memset(&httpdns, 0, sizeof(httpdns));
//saveHdrs = NULL;
httpdns.dst.sin_family = AF_INET;
//http.dst.sin_family = https.dst.sin_family = httpdns.dst.sin_family = AF_INET;
global.tcp_listen_fd = global.dns_listen_fd = global.udp_listen_fd = global.uid = -1;
}
static void handle_cmd(int argc, char **argv)
{
/* 命令行选项 */
if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
printf(RED "HttpDNS(" VERSION ")\n"
"Author: aixiao@aixiao.me, mmmdbybyd.\n"
"\n"
"启动命令:\n httpdns httpdns.conf\n"
"结束命令:\n httpdns stop\n"
"检测命令:\n httpdns status\n"
"重启命令:\n httpdns restart httpdns.conf\n"
"\n" NONE);
exit(argc < 2 ? 1 : 0);
}
if (strcasecmp(argv[1], "stop") == 0)
exit(additional_service(argv[0], SERVICE_TYPE_STOP));
else if (strcasecmp(argv[1], "status") == 0)
exit(additional_service(argv[0], SERVICE_TYPE_STATUS));
else if (strcasecmp(argv[1], "restart") == 0) {
additional_service(argv[0], SERVICE_TYPE_STOP);
while (additional_service(argv[0], SERVICE_TYPE_STATUS_NOT_PRINT) == 0) ;
argv++;
}
read_conf(argv[1]);
}
static void server_init()
{
/* 忽略PIPE信号 */
signal(SIGPIPE, SIG_IGN);
//不能用setgid和setuid这两个函数不能切换回root可能导致HTTPUDP代理失败
if (global.uid > -1 && (setegid(global.uid) == -1 || seteuid(global.uid) == -1)) {
perror("setegid(or seteuid)");
exit(1);
}
#ifndef DEBUG
if (daemon(1, 1) == -1) {
perror("daemon");
exit(1);
}
#endif
/*
一个进程只开一个子进程,
程序结束时子进程先写入dns缓存
之后主进程再写入,
否则可能导致缓存文件格式错误
*/
while (global.procs-- > 1 && (child_pid = fork()) == 0) ;
}
static void start_server_loop()
{
pthread_t thread_id;
if (global.timeout_m)
pthread_create(&thread_id, NULL, &timeout_check, NULL);
if (global.dns_listen_fd >= 0) {
dns_init();
dns_loop(NULL);
}
}
int main(int argc, char *argv[])
{
initVariable();
handle_cmd(argc, argv);
server_init();
start_server_loop();
return 0;
}