2017-07-12 12:29:56 +08:00
|
|
|
|
#include "http.h"
|
|
|
|
|
#include "dns.h"
|
2018-12-07 09:29:41 +08:00
|
|
|
|
#include "timeout.h"
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
2019-03-10 05:23:50 +08:00
|
|
|
|
#define SSL_RSP_CONNECT "HTTP/1.1 200 Connection established\r\nServer: SpecialProxy_CuteBi\r\nConnection: keep-alive\r\n\r\n"
|
|
|
|
|
#define SSL_RSP_HTTP "HTTP/1.1 200 OK\r\nContent-length: 99999999\r\nServer: SpecialProxy_CuteBi\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: keep-alive\r\n\r\n"
|
|
|
|
|
#define SSL_RSP_WEBSOCKET "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: SpecialProxy_CuteBi\r\n\r\n"
|
2017-07-12 12:29:56 +08:00
|
|
|
|
#define HTTP_TYPE 0
|
|
|
|
|
#define OTHER_TYPE 1
|
|
|
|
|
|
|
|
|
|
conn_t cts[MAX_CONNECTION];
|
|
|
|
|
char *local_header, *proxy_header, *ssl_proxy;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
int lisFd, proxy_header_len, local_header_len, ignore_host_before_count;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
uint8_t strict_spilce, sslEncodeCode;
|
|
|
|
|
|
|
|
|
|
/* 对数据进行编码 */
|
|
|
|
|
static void dataEncode(char *data, int data_len)
|
|
|
|
|
{
|
2019-01-26 11:53:32 +08:00
|
|
|
|
if (sslEncodeCode)
|
|
|
|
|
while (data_len-- > 0)
|
|
|
|
|
data[data_len] ^= sslEncodeCode;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
}
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
2019-01-26 11:53:32 +08:00
|
|
|
|
int8_t connectionToServer(in_addr_t ip, conn_t *server)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
2019-01-26 11:53:32 +08:00
|
|
|
|
struct sockaddr_in addr;
|
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
server->fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
|
if (server->fd < 0)
|
|
|
|
|
return 1;
|
2018-10-14 11:58:56 +08:00
|
|
|
|
fcntl(server->fd, F_SETFL, O_NONBLOCK);
|
2019-01-26 11:53:32 +08:00
|
|
|
|
addr.sin_family = AF_INET;
|
|
|
|
|
addr.sin_addr.s_addr = ip;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
addr.sin_port = htons(server->destPort);
|
2018-10-14 11:58:56 +08:00
|
|
|
|
if (connect(server->fd, (struct sockaddr *)&addr, sizeof(addr)) != 0 && errno != EINPROGRESS)
|
|
|
|
|
return 1;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
ev.data.ptr = server;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
epoll_ctl(efd, EPOLL_CTL_ADD, server->fd, &ev);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void close_connection(conn_t *conn)
|
|
|
|
|
{
|
|
|
|
|
epoll_ctl(efd, EPOLL_CTL_DEL, conn->fd, NULL);
|
|
|
|
|
close(conn->fd);
|
|
|
|
|
if ((conn - cts) & 1)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
char *server_data;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
server_data = conn->ready_data;
|
|
|
|
|
memset(conn, 0, sizeof(conn_t));
|
|
|
|
|
conn->ready_data = server_data;
|
|
|
|
|
conn-- ->fd = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
struct dns *d;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
d = dns_list + ((conn - cts) >> 1);
|
|
|
|
|
d->request_len = d->sent_len = 0;
|
|
|
|
|
free(conn->ready_data);
|
|
|
|
|
free(conn->incomplete_data);
|
|
|
|
|
memset(conn, 0, sizeof(conn_t));
|
|
|
|
|
conn++ ->fd = -1;
|
|
|
|
|
}
|
|
|
|
|
if (conn->fd >= 0)
|
|
|
|
|
close_connection(conn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 判断请求类型 */
|
|
|
|
|
static int8_t request_type(char *data)
|
|
|
|
|
{
|
|
|
|
|
if (strncmp(data, "GET", 3) == 0 ||
|
|
|
|
|
strncmp(data, "POST", 4) == 0 ||
|
|
|
|
|
strncmp(data, "CONNECT", 7) == 0 ||
|
|
|
|
|
strncmp(data, "HEAD", 4) == 0 ||
|
|
|
|
|
strncmp(data, "PUT", 3) == 0 ||
|
|
|
|
|
strncmp(data, "OPTIONS", 7) == 0 ||
|
|
|
|
|
strncmp(data, "MOVE", 4) == 0 ||
|
|
|
|
|
strncmp(data, "COPY", 4) == 0 ||
|
|
|
|
|
strncmp(data, "TRACE", 5) == 0 ||
|
|
|
|
|
strncmp(data, "DELETE", 6) == 0 ||
|
|
|
|
|
strncmp(data, "LINK", 4) == 0 ||
|
|
|
|
|
strncmp(data, "UNLINK", 6) == 0 ||
|
|
|
|
|
strncmp(data, "PATCH", 5) == 0 ||
|
|
|
|
|
strncmp(data, "WRAPPED", 7) == 0)
|
|
|
|
|
return HTTP_TYPE;
|
|
|
|
|
return OTHER_TYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *read_data(conn_t *in, char *data, int *data_len)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
char *new_data;
|
|
|
|
|
int read_len;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
new_data = (char *)realloc(data, *data_len + BUFFER_SIZE + 1);
|
|
|
|
|
if (new_data == NULL)
|
|
|
|
|
{
|
|
|
|
|
free(data);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
data = new_data;
|
|
|
|
|
read_len = read(in->fd, data + *data_len, BUFFER_SIZE);
|
|
|
|
|
/* 判断是否关闭连接 */
|
|
|
|
|
if (read_len <= 0)
|
|
|
|
|
{
|
|
|
|
|
if (read_len == 0 || *data_len == 0 || errno != EAGAIN)
|
|
|
|
|
{
|
|
|
|
|
free(data);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*data_len += read_len;
|
|
|
|
|
} while (read_len == BUFFER_SIZE);
|
|
|
|
|
*(data + *data_len) = '\0';
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *get_host(char *data)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
char *hostEnd, *host;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
int i;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
host = strstr(data, local_header);
|
|
|
|
|
if (host != NULL)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
char *local_host;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
host += local_header_len;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
while (*host == ' ' || *host == '\t')
|
2017-07-12 12:29:56 +08:00
|
|
|
|
host++;
|
|
|
|
|
for (hostEnd = host; *hostEnd < 58 && *hostEnd > 48; hostEnd++);
|
|
|
|
|
//判断该头域是否正确使用
|
|
|
|
|
if (hostEnd - host > 5 || *hostEnd != '\r')
|
|
|
|
|
return NULL;
|
|
|
|
|
local_host = (char *)malloc(16);
|
|
|
|
|
if (local_host == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
strcpy(local_host, "127.0.0.1:");
|
2018-10-14 11:58:56 +08:00
|
|
|
|
memcpy(local_host + 10, host, hostEnd - host);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
local_host[10 + (hostEnd - host)] = '\0';
|
|
|
|
|
return local_host;
|
|
|
|
|
}
|
|
|
|
|
host= strstr(data, proxy_header);
|
|
|
|
|
if (host == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
host += proxy_header_len;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
while (*host == ' ' || *host == '\t')
|
2017-07-12 12:29:56 +08:00
|
|
|
|
host++;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
for (i = 0; i < ignore_host_before_count; i++)
|
|
|
|
|
if (host[i] == '\0') //防止越界
|
|
|
|
|
break;
|
|
|
|
|
host += i;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
hostEnd = strchr(host, '\r');
|
2019-01-26 11:53:32 +08:00
|
|
|
|
return hostEnd ? strndup(host, hostEnd - host) : strdup(host);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 删除请求头中的头域 */
|
|
|
|
|
static void del_hdr(char *header, int *header_len)
|
|
|
|
|
{
|
2019-01-26 11:53:32 +08:00
|
|
|
|
char *line_begin, *line_end;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
for (line_begin = strchr(header, '\n'); line_begin++ && *line_begin != '\r'; line_begin = line_end)
|
|
|
|
|
{
|
2019-01-26 11:53:32 +08:00
|
|
|
|
line_end = strchr(line_begin, '\n');
|
|
|
|
|
if (strncasecmp(line_begin, "host:", 5) == 0 || strncasecmp(line_begin, local_header + 1, local_header_len - 1) == 0 || strncasecmp(line_begin, proxy_header + 1, proxy_header_len - 1) == 0)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
|
|
|
|
if (line_end++)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
memmove(line_begin, line_end, *header_len - (line_end - header) + 1);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
(*header_len) -= line_end - line_begin;
|
|
|
|
|
line_end = line_begin - 1; //新行前一个字符
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*line_begin = '\0';
|
|
|
|
|
*header_len = line_begin - header;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 构建新请求头 */
|
|
|
|
|
static char *build_request(char *client_data, int *data_len, char *host)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
char *uri, *url, *p, *lf, *header, *new_data, *proxy_host;
|
|
|
|
|
int len;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
header = client_data;
|
|
|
|
|
proxy_host = host;
|
|
|
|
|
do {
|
2017-07-12 12:52:46 +08:00
|
|
|
|
del_hdr(client_data, data_len);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
/* 将完整url转换为uri */
|
|
|
|
|
url = strchr(header, ' ');
|
|
|
|
|
lf = strchr(header, '\n');
|
|
|
|
|
if (url == NULL || lf == NULL || lf - 10 <= header)
|
|
|
|
|
return client_data;
|
|
|
|
|
if (url < lf && *(++url) != '/')
|
|
|
|
|
{
|
|
|
|
|
uri = strchr(url + 7, '/');
|
|
|
|
|
p = lf - 10; //指向HTTP版本前面的空格
|
|
|
|
|
if (uri != NULL && uri < p)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
memmove(url, uri, *data_len - (uri - client_data) + 1);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
*data_len -= uri - url;
|
|
|
|
|
lf -= uri - url;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*url++ = '/';
|
2018-10-14 11:58:56 +08:00
|
|
|
|
memmove(url, p, *data_len - (p - client_data) + 1);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
*data_len -= p - url;
|
|
|
|
|
lf -= p - url;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*data_len += strlen(proxy_host) + 8; //8为 "Host: " + "\r\n"的长度
|
|
|
|
|
new_data = (char *)malloc(*data_len + 1);
|
|
|
|
|
if (new_data == NULL)
|
|
|
|
|
{
|
|
|
|
|
if (proxy_host != host)
|
|
|
|
|
free(proxy_host);
|
|
|
|
|
free(client_data);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
/* 请求行后面添加Host行 */
|
|
|
|
|
len = lf + 1 - client_data;
|
|
|
|
|
memcpy(new_data, client_data, len); //复制请求行
|
|
|
|
|
strcpy(new_data + len, "Host: ");
|
|
|
|
|
strcpy(new_data + len + 6, proxy_host);
|
|
|
|
|
len += strlen(proxy_host) + 6;
|
|
|
|
|
new_data[len++] = '\r';
|
|
|
|
|
new_data[len++] = '\n';
|
|
|
|
|
//len += sprintf(new_data + len, "Host: %s\r\n", proxy_host);
|
|
|
|
|
memcpy(new_data + len, lf + 1, *data_len - len + 1);
|
|
|
|
|
free(client_data);
|
|
|
|
|
if (proxy_host != host)
|
|
|
|
|
free(proxy_host);
|
|
|
|
|
if (strict_spilce == 0)
|
|
|
|
|
return new_data;
|
|
|
|
|
client_data = new_data;
|
|
|
|
|
//如果请求头只有一个头域,则必须-1才能搜索到\n\r
|
|
|
|
|
header = strstr(client_data + len - 1, "\n\r");
|
|
|
|
|
//如果是连续的多个请求头,则全部修改
|
|
|
|
|
if (header == NULL || request_type(header + 3) == OTHER_TYPE)
|
|
|
|
|
return client_data;
|
|
|
|
|
header += 3;
|
|
|
|
|
proxy_host = get_host(header);
|
|
|
|
|
if (proxy_host == NULL)
|
|
|
|
|
proxy_host = host;
|
|
|
|
|
} while (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 解析Host */
|
2018-12-21 19:13:07 +08:00
|
|
|
|
static int8_t parse_host(conn_t *server, char *host)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
char *port, *p;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
port = strchr(host, ':');
|
|
|
|
|
if (port)
|
|
|
|
|
{
|
|
|
|
|
server->destPort = atoi(port+1);
|
|
|
|
|
*port = '\0';
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
server->destPort = 80; //默认80端口
|
|
|
|
|
for (p = host; (*p > 47 && *p < 58) || *p == '.'; p++);
|
|
|
|
|
if (*p == '\0')
|
|
|
|
|
{
|
2019-01-26 11:53:32 +08:00
|
|
|
|
if (connectionToServer(inet_addr(host), server) != 0)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if (build_dns_req(dns_list + ((server - cts) >> 1), host) == -1)
|
|
|
|
|
return 1;
|
|
|
|
|
if (port)
|
|
|
|
|
*port = ':';
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 读取到的数据全部就绪,将incomplete_data复制到ready_data */
|
|
|
|
|
static int8_t copy_data(conn_t *ct)
|
|
|
|
|
{
|
2018-12-21 19:13:07 +08:00
|
|
|
|
dataEncode(ct->incomplete_data, ct->incomplete_data_len);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
if (ct->ready_data)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
char *new_data;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
new_data = (char *)realloc(ct->ready_data, ct->ready_data_len + ct->incomplete_data_len);
|
|
|
|
|
if (new_data == NULL)
|
|
|
|
|
return 1;
|
|
|
|
|
ct->ready_data = new_data;
|
|
|
|
|
memcpy(new_data + ct->ready_data_len, ct->incomplete_data, ct->incomplete_data_len);
|
|
|
|
|
ct->ready_data_len += ct->incomplete_data_len;
|
|
|
|
|
free(ct->incomplete_data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ct->ready_data = ct->incomplete_data;
|
|
|
|
|
ct->ready_data_len = ct->incomplete_data_len;
|
|
|
|
|
}
|
|
|
|
|
ct->incomplete_data = NULL;
|
|
|
|
|
ct->incomplete_data_len = 0;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void serverToClient(conn_t *server)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
conn_t *client;
|
|
|
|
|
int write_len;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
client = server - 1;
|
|
|
|
|
while ((server->ready_data_len = read(server->fd, server->ready_data, BUFFER_SIZE)) > 0)
|
|
|
|
|
{
|
2018-12-21 19:13:07 +08:00
|
|
|
|
dataEncode(server->ready_data, server->ready_data_len);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
write_len = write(client->fd, server->ready_data, server->ready_data_len);
|
2018-12-21 19:13:07 +08:00
|
|
|
|
if (write_len <= 0)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
2018-12-21 19:13:07 +08:00
|
|
|
|
if (write_len == 0 || errno != EAGAIN)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
close_connection(server);
|
|
|
|
|
else
|
|
|
|
|
server->sent_len = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (write_len < server->ready_data_len)
|
|
|
|
|
{
|
|
|
|
|
server->sent_len = write_len;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
ev.data.ptr = client;
|
|
|
|
|
epoll_ctl(efd, EPOLL_CTL_MOD, client->fd, &ev);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-10-14 11:58:56 +08:00
|
|
|
|
if (server->ready_data_len < BUFFER_SIZE)
|
|
|
|
|
break;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
}
|
2018-10-14 11:58:56 +08:00
|
|
|
|
//判断是否关闭连接
|
2018-12-21 19:13:07 +08:00
|
|
|
|
if (server->ready_data_len == 0 || (server->ready_data_len == -1 && errno != EAGAIN))
|
2017-07-12 12:29:56 +08:00
|
|
|
|
close_connection(server);
|
|
|
|
|
else
|
|
|
|
|
server->ready_data_len = server->sent_len = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tcp_out(conn_t *to)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
conn_t *from;
|
|
|
|
|
int write_len;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
|
|
|
|
if (to->fd == -1)
|
|
|
|
|
return;
|
|
|
|
|
else if ((to - cts) & 1)
|
|
|
|
|
from = to - 1;
|
|
|
|
|
else
|
|
|
|
|
from = to + 1;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
from->timer = to->timer = 0;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
write_len = write(to->fd, from->ready_data + from->sent_len, from->ready_data_len - from->sent_len);
|
|
|
|
|
if (write_len == from->ready_data_len - from->sent_len)
|
|
|
|
|
{
|
|
|
|
|
//服务端的数据可能没全部写入到客户端
|
|
|
|
|
if ((from - cts) & 1)
|
|
|
|
|
{
|
|
|
|
|
serverToClient(from);
|
|
|
|
|
if (from->fd >= 0 && from->ready_data_len == 0)
|
|
|
|
|
{
|
2018-12-21 19:13:07 +08:00
|
|
|
|
ev.events = EPOLLIN|EPOLLET;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
ev.data.ptr = to;
|
|
|
|
|
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-12-21 19:13:07 +08:00
|
|
|
|
ev.events = EPOLLIN|EPOLLET;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
ev.data.ptr = to;
|
|
|
|
|
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
|
|
|
|
|
free(from->ready_data);
|
|
|
|
|
from->ready_data = NULL;
|
|
|
|
|
from->ready_data_len = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (write_len > 0)
|
|
|
|
|
{
|
|
|
|
|
from->sent_len += write_len;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
ev.data.ptr = to;
|
|
|
|
|
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
|
|
|
|
|
}
|
|
|
|
|
else if (errno != EAGAIN)
|
|
|
|
|
{
|
|
|
|
|
close_connection(to);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-10 05:23:50 +08:00
|
|
|
|
/* ssl代理回应 */
|
|
|
|
|
static int respond_sslStatus(conn_t *in)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
可能客户端使用http请求伪装CONNECT代理
|
|
|
|
|
这时候即使fd是非阻塞也只需要判断返回值是否小于0
|
|
|
|
|
正常情况非阻塞也可以全部发送,懒得写代码了
|
|
|
|
|
*/
|
|
|
|
|
if (memcmp(in->incomplete_data, "CON", 3) == 0)
|
|
|
|
|
return (write(in->fd, SSL_RSP_CONNECT, sizeof(SSL_RSP_CONNECT)-1) <= 0);
|
|
|
|
|
else if (*in->incomplete_data == 'G' && (strstr(in->incomplete_data, "websocket") || strstr(in->incomplete_data, "WebSocket")))
|
|
|
|
|
return (write(in->fd, SSL_RSP_WEBSOCKET, sizeof(SSL_RSP_WEBSOCKET)-1) <= 0);
|
|
|
|
|
|
|
|
|
|
return (write(in->fd, SSL_RSP_HTTP, sizeof(SSL_RSP_HTTP)-1) <= 0);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
void tcp_in(conn_t *in)
|
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
conn_t *server;
|
|
|
|
|
char *host, *headerEnd;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
if (in->fd < 0)
|
|
|
|
|
return;
|
2017-07-12 12:52:46 +08:00
|
|
|
|
//如果in - cts是奇数,那么是服务端触发事件
|
2017-07-12 12:29:56 +08:00
|
|
|
|
if ((in - cts) & 1)
|
|
|
|
|
{
|
2019-01-26 11:53:32 +08:00
|
|
|
|
in->timer = (in-1)->timer = 0;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
if (in->ready_data_len <= 0)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
serverToClient(in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
|
|
|
|
in->timer = (in+1)->timer = 0;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
in->incomplete_data = read_data(in, in->incomplete_data, &in->incomplete_data_len);
|
|
|
|
|
if (in->incomplete_data == NULL)
|
|
|
|
|
{
|
|
|
|
|
close_connection(in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
server = in + 1;
|
2018-10-14 11:58:56 +08:00
|
|
|
|
server->request_type = in->request_type = request_type(in->incomplete_data);
|
|
|
|
|
if (in->request_type == OTHER_TYPE)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
|
|
|
|
//如果是第一次读取数据,并且不是HTTP请求的,关闭连接。复制数据失败的也关闭连接
|
|
|
|
|
if (in->reread_data == 0 || copy_data(in) != 0)
|
|
|
|
|
{
|
|
|
|
|
close_connection(in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
goto handle_data_complete;
|
|
|
|
|
}
|
2018-12-07 09:29:41 +08:00
|
|
|
|
headerEnd = strstr(in->incomplete_data, "\n\r");
|
2017-07-12 12:29:56 +08:00
|
|
|
|
//请求头不完整,等待下次读取
|
|
|
|
|
if (headerEnd == NULL)
|
|
|
|
|
return;
|
|
|
|
|
host = get_host(in->incomplete_data);
|
|
|
|
|
if (host == NULL)
|
|
|
|
|
{
|
|
|
|
|
close_connection(in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-12-21 19:13:07 +08:00
|
|
|
|
dataEncode(host, strlen(host));
|
2017-07-12 12:29:56 +08:00
|
|
|
|
/* 第一次读取数据 */
|
|
|
|
|
if (in->reread_data == 0)
|
|
|
|
|
{
|
|
|
|
|
in->reread_data = 1;
|
|
|
|
|
if (parse_host(server, host) != 0)
|
|
|
|
|
{
|
|
|
|
|
free(host);
|
|
|
|
|
close_connection(in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (strstr(in->incomplete_data, ssl_proxy))
|
|
|
|
|
{
|
2019-03-10 05:23:50 +08:00
|
|
|
|
if (respond_sslStatus(in) != 0)
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
|
|
|
|
free(host);
|
|
|
|
|
close_connection(in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-12-07 09:29:41 +08:00
|
|
|
|
headerEnd += 3;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
if (headerEnd - in->incomplete_data < in->incomplete_data_len)
|
|
|
|
|
{
|
|
|
|
|
in->incomplete_data_len -= headerEnd - in->incomplete_data;
|
2018-10-14 11:58:56 +08:00
|
|
|
|
memmove(in->incomplete_data, headerEnd, in->incomplete_data_len + 1);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
if (request_type(in->incomplete_data) == OTHER_TYPE)
|
|
|
|
|
{
|
|
|
|
|
copy_data(in);
|
|
|
|
|
free(host);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
free(in->incomplete_data);
|
|
|
|
|
in->incomplete_data = NULL;
|
|
|
|
|
in->incomplete_data_len = 0;
|
|
|
|
|
free(host);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
in->incomplete_data = build_request(in->incomplete_data, &in->incomplete_data_len, host);
|
|
|
|
|
free(host);
|
|
|
|
|
if (in->incomplete_data == NULL || copy_data(in) != 0)
|
|
|
|
|
{
|
|
|
|
|
close_connection(in);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//数据处理完毕,可以发送
|
|
|
|
|
handle_data_complete:
|
2018-10-14 11:58:56 +08:00
|
|
|
|
//这个判断是防止 多次读取客户端数据,但是没有和服务端建立连接,导致报错
|
2017-07-12 12:29:56 +08:00
|
|
|
|
if (server->fd >= 0)
|
|
|
|
|
tcp_out(server);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-21 19:13:07 +08:00
|
|
|
|
void accept_client()
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
2018-10-14 11:58:56 +08:00
|
|
|
|
struct epoll_event epollEvent;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
struct sockaddr_in addr;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
conn_t *client;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
socklen_t addr_len = sizeof(addr);
|
|
|
|
|
|
2018-12-21 19:13:07 +08:00
|
|
|
|
/* 偶数为客户端,奇数为服务端 */
|
|
|
|
|
for (client = cts; client - cts < MAX_CONNECTION; client += 2)
|
|
|
|
|
if (client->fd < 0)
|
|
|
|
|
break;
|
|
|
|
|
if (client - cts >= MAX_CONNECTION)
|
|
|
|
|
return;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
client->timer = (client+1)->timer = 0;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
client->fd = accept(lisFd, (struct sockaddr *)&addr, &addr_len);
|
|
|
|
|
if (client->fd < 0)
|
|
|
|
|
return;
|
|
|
|
|
fcntl(client->fd, F_SETFL, O_NONBLOCK);
|
2018-10-14 11:58:56 +08:00
|
|
|
|
epollEvent.events = EPOLLIN|EPOLLET;
|
2018-12-21 19:13:07 +08:00
|
|
|
|
epollEvent.data.ptr = client;
|
|
|
|
|
epoll_ctl(efd, EPOLL_CTL_ADD, client->fd, &epollEvent);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void create_listen(char *ip, int port)
|
|
|
|
|
{
|
2019-01-26 11:53:32 +08:00
|
|
|
|
struct sockaddr_in addr;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
int optval = 1;
|
|
|
|
|
|
|
|
|
|
if ((lisFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
|
|
|
|
{
|
|
|
|
|
perror("socket");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2019-01-26 11:53:32 +08:00
|
|
|
|
addr.sin_family = AF_INET;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
addr.sin_port = htons(port);
|
|
|
|
|
addr.sin_addr.s_addr = inet_addr(ip);
|
|
|
|
|
if (setsockopt(lisFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)
|
|
|
|
|
{
|
|
|
|
|
perror("setsockopt");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
if (bind(lisFd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
|
|
|
|
|
{
|
|
|
|
|
perror("bind");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
if (listen(lisFd, 500) != 0)
|
|
|
|
|
{
|
|
|
|
|
perror("listen");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|