168 lines
4.5 KiB
C
168 lines
4.5 KiB
C
#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;
|
||
}
|