SpecialProxy/main.c
2017-07-12 12:29:56 +08:00

216 lines
6.1 KiB
C
Raw 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 "main.h"
#include "http.h"
#include "dns.h"
#include <pthread.h>
#define VERSION "0.1"
#define DEFAULT_DNS_IP "114.114.114.114"
struct epoll_event evs[MAX_CONNECTION + 2], ev;
struct sockaddr_in addr;
socklen_t addr_len;
int efd;
static void usage()
{
puts("SpecialProxy(" VERSION "):\n"
" -l [listenip:]listenport \033[35G default ip is 0.0.0.0\n"
" -p proxy header \033[35G default is 'Host'\n"
" -L local proxy header \033[35G default is 'Local'\n"
" -d dns query address \033[35G default is " DEFAULT_DNS_IP "\n"
" -s ssl proxy string \033[35G default is 'CONNECT'\n"
" -a \033[35G all http requests repeat spilce\n"
" -h display this infomaction\n"
" -w worker process\n");
exit(0);
}
static void server_loop()
{
pthread_t thread_id;
int n;
//单独进程accept多进程并发环境下不会惊群
pthread_create(&thread_id, NULL, accept_loop, NULL);
ev.events = EPOLLIN;
ev.data.fd = dnsFd;
epoll_ctl(efd, EPOLL_CTL_ADD, dnsFd, &ev);
while (1)
{
n = epoll_wait(efd, evs, MAX_CONNECTION + 2, -1);
while (n-- > 0)
{
if (evs[n].data.fd == dnsFd)
{
if (evs[n].events & EPOLLIN)
read_dns_rsp();
if (evs[n].events & EPOLLOUT)
dns_query();
}
else
{
if (evs[n].events & EPOLLIN)
tcp_in((conn_t *)evs[n].data.ptr);
if (evs[n].events & EPOLLOUT)
tcp_out((conn_t *)evs[n].data.ptr);
}
}
}
}
static void initializate(int argc, char **argv)
{
struct sockaddr_in dnsAddr;
char *p;
int opt, i, workers = 1;
addr_len = sizeof(addr);
lisFd = -1;
efd = epoll_create(MAX_CONNECTION + 2);
if (efd < 0)
{
perror("epoll_create");
exit(1);
}
dnsAddr.sin_family = addr.sin_family = AF_INET;
//默认dns地址
dnsAddr.sin_addr.s_addr = inet_addr(DEFAULT_DNS_IP);
dnsAddr.sin_port = htons(53);
dns_connect(&dnsAddr); //主进程中的fd
strict_spilce = 0;
local_header = NULL;
ssl_proxy = (char *)"CONNECT";
local_header = (char *)"\nLocal:";
proxy_header = (char *)"\nHost:";
proxy_header_len = strlen(proxy_header);
local_header_len = strlen(local_header);
/* 读取命令行参数 */
while ((opt = getopt(argc, argv, "d:l:p:s:w:L:ah")) != -1)
{
switch (opt)
{
case 'd':
p = strchr(optarg, ':');
if (p)
{
*p = '\0';
dnsAddr.sin_port = htons(atoi(p+1));
}
else
{
dnsAddr.sin_port = htons(53);
}
dnsAddr.sin_addr.s_addr = inet_addr(optarg);
connect(dnsFd, (struct sockaddr *)&dnsAddr, sizeof(dnsAddr));
break;
case 'l':
p = strchr(optarg, ':');
if (p)
{
*p = '\0';
create_listen(optarg, atoi(p+1));
}
else
{
create_listen((char *)"0.0.0.0", atoi(optarg));
}
break;
case 'p':
//假如选项值为 "Proxy", proxy_header设置为 "\nProxy:"
proxy_header_len = strlen(optarg) + 2;
if (optarg[proxy_header_len] == ':')
optarg[proxy_header_len--] = '\0';
proxy_header = (char *)malloc(proxy_header_len + 1);
if (proxy_header == NULL)
{
fputs("out of memory.\n", stderr);
exit(1);
}
sprintf(proxy_header, "\n%s:", optarg);
break;
case 'L':
local_header_len = strlen(optarg) + 2;
if (optarg[local_header_len] == ':')
optarg[local_header_len--] = '\0';
local_header = (char *)malloc(local_header_len + 1);
if (local_header == NULL)
{
fputs("out of memory.\n", stderr);
exit(1);
}
sprintf(local_header, "\n%s:", optarg);
break;
case 's':
ssl_proxy = optarg;
break;
case 'a':
strict_spilce = 1;
break;
case 'w':
workers = atoi(optarg);
break;
default:
usage();
break;
}
}
if (lisFd < 0)
{
fputs("no listen address\n", stderr);
exit(1);
}
memset(cts, 0, sizeof(cts));
for (i = MAX_CONNECTION; i--; )
cts[i].fd = -1;
//为服务端的结构体分配内存
for (i = 1; i < MAX_CONNECTION; i += 2)
{
cts[i].ready_data = (char *)malloc(BUFFER_SIZE);
if (cts[i].ready_data == NULL)
{
fputs("out of memory.", stderr);
exit(1);
}
}
memset(dns_list, 0, sizeof(dns_list));
for (i = MAX_CONNECTION / 2; i--; )
{
memcpy(dns_list[i].request, &i, sizeof(uint16_t));
dns_list[i].request[2] = 1;
dns_list[i].request[3] = 0;
dns_list[i].request[4] = 0;
dns_list[i].request[5] = 1;
dns_list[i].request[6] = 0;
dns_list[i].request[7] = 0;
dns_list[i].request[8] = 0;
dns_list[i].request[9] = 0;
dns_list[i].request[10] = 0;
dns_list[i].request[11] = 0;
}
signal(SIGPIPE, SIG_IGN);
while (workers-- > 1 && fork() == 0)
//子进程中的dnsFd必须重新申请不然epoll监听可能读取到其他进程得到的数据
dns_connect(&dnsAddr);
}
int main(int argc, char **argv)
{
initializate(argc, argv);
//if (daemon(1, 1))
if (daemon(1, 0))
{
perror("daemon");
return 1;
}
server_loop();
return 0;
}