-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathserver.c
438 lines (331 loc) · 13.3 KB
/
server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ev.h>
#include "net.h"
#include "linklist.h"
#include "rbtree.h"
#include "server.h"
#include "mptunnel.h"
#include "buffer.h"
#include "client.h"
#define UDP_KEEP_ALIVE 300
/**
* 一个 UDP 连接上,最后收到包的时间与最后发送包的时间的最大时间差
*/
#define UDP_INTERACTIVE_TIMEOUT 60
static struct ev_loop * g_ev_reactor = NULL;
static struct list_head g_buffers = LIST_HEAD_INIT(g_buffers);
static struct list_head g_bridge_list = LIST_HEAD_INIT(g_bridge_list);
static pthread_mutex_t g_bridge_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_listen_fd = -1;
static int g_target_fd = -1;
static int g_listen_port = 0;
static char *g_target_host = NULL;
static int g_target_port = 0;
extern int g_config_encrypt;
/**
* 收到远程桥发来的数据时的处理函数
*/
void recv_bridge_callback(struct ev_loop* reactor, ev_io* w, int events) {
char* buf;
int buflen = 65536;
int readb;
struct sockaddr_in baddr;
static received_t *received = NULL;
if (received == NULL) {
received = malloc(sizeof(*received));
received_init(received);
}
buf = malloc(buflen);
memset(buf, 0x00, buflen);
bridge_t* b = (bridge_t*)malloc(sizeof(bridge_t));
memset(b, 0x00, sizeof(*b));
b->st_time = time(NULL);
b->addrlen = sizeof(b->addr);
baddr = *(struct sockaddr_in*)&b->addr;
//LOGD("收到从桥端(fd=%d)发来的数据\n", w->fd);
readb = recvfrom(w->fd, buf, buflen, 0, &b->addr, &b->addrlen);
if (readb < 0) {
LOGW(_("Bridge(fd=%d) may close the connection: %s\n"), w->fd, strerror(errno));
free(buf); free(b);
return;
}
else if (readb == 0) {
LOGW(_("Can't received packet from bridge(fd=%d),bridge may close the connection\n"), w->fd);
free(buf); free(b);
return;
}
else {
//LOGD("从桥端(:%u)收取了 %d 字节数据:%s\n", htons(baddr.sin_port), readb, (char*)buf + sizeof(packet_t));
int exists = 0;
bridge_t *lb;
struct list_head *l;
pthread_mutex_lock(&g_bridge_list_mutex);
list_for_each(l, &g_bridge_list) {
lb = list_entry(l, bridge_t, list);
if (memcmp(&lb->addr, &b->addr, sizeof(struct sockaddr)) == 0) {
exists = 1;
free(b);
b = lb;
break;
}
}
b->rc_time = time(NULL);
if (exists != 1) {
/// 这是一个新客户端,将其添加到客户端列表中
LOGI(_("Got a new client, add it to Client List\n"));
list_add(&b->list, &g_bridge_list);
}
pthread_mutex_unlock(&g_bridge_list_mutex);
}
/// 解包,然后发送给目标服务器
packet_t* p;
mpdecrypt(buf);
p = (packet_t*)buf;
if (p->type == PKT_TYPE_CTL) {
//LOGD("从桥端(:%u)收取了 %d 字节数据编号为 %d 的数据包,但这是一个控制包,丢弃之\n", htons(baddr.sin_port), readb, p->id);
LOGD(_("Received control packet from bridge (:%u) of %d bytes, packet ID is %d, drop it\n"), htons(baddr.sin_port), readb, p->id);
free(buf);
return;
}
else if (p->type != PKT_TYPE_DATA) {
//LOGD("从桥端(:%u)收取了 %d 字节编号为 %d 的数据包,但这是一个未知类型的数据包,丢弃之\n", htons(baddr.sin_port), readb, p->id);
LOGD(_("Received packet from bridge (:%u) of %d bytes, packet ID is %d, but packet type is unknown, drop it.\n"), htons(baddr.sin_port), readb, p->id);
free(buf);
return;
}
else {
//LOGD("从桥端(:%u)收取了 %d 字节编号为 %d 的数据包\n", htons(baddr.sin_port), readb, p->id);
}
buflen = p->buflen;
buf = (char*)buf + sizeof(*p);
if (received_is_received(received, p->id) == 1) {
//LOGD("从桥端(:%u)收取了 %d 字节编号为 %d 的曾经收取过的数据包,丢弃之\n", htons(baddr.sin_port), readb, p->id);
LOGD(_("Received packet from bridge (:%u) of %d bytes which was received, packet ID is %d, drop it\n"), htons(baddr.sin_port), readb, p->id);
free(p);
//received_destroy(received);
//free(received);
//received = NULL;
return;
}
else {
//LOGD("从桥端(:%u)收取了 %d 字节编号为 %d 的数据包,转发该包\n", htons(baddr.sin_port), readb, p->id);
LOGD(_("Received packet from bridge (:%u) of %d bytes, ID is %d, forward it\n"), htons(baddr.sin_port), readb, p->id);
received_add(received, p->id);
}
if (received != NULL) {
received_try_dropdead(received, 30);
}
/// 发送给目标服务器
int sendb;
sendb = send(g_target_fd, buf, buflen, MSG_DONTWAIT);
if (sendb < 0) {
///LOGW("无法向目标服务器发送编号为 %d 的数据包:%s\n", p->id, strerror(errno));
LOGW(_("Can't send packet #%d to target server: %s\n"), p->id, strerror(errno));
}
else if (sendb == 0) {
//LOGW("目标服务器可能已经断开了连接,无法转发 %d 号数据包\n", p->id);
LOGW(_("Connection to target server seems closed, can't forward packet #%d\n"), p->id);
}
else {
//LOGD("成功向目标服务器发送了 %d 字节数据:%s\n", buflen, buf);
}
free(p);
return;
}
/**
* ev 处理线程
*/
void* ev_thread(void* ptr) {
int port = 3002;
LOGD(_("libev thread started\n"));
g_listen_fd = net_bind("0.0.0.0", port, SOCK_DGRAM);
if (g_listen_fd < 0) {
LOGE(_("Can't listen port %d: %s\n"), port, strerror(errno));
exit(0);
}
g_ev_reactor = ev_loop_new(EVFLAG_AUTO);
ev_io* w = (ev_io*)malloc(sizeof(ev_io));
ev_io_init(w, recv_bridge_callback, g_listen_fd, EV_READ);
ev_io_start(g_ev_reactor, w);
ev_run(g_ev_reactor, 0);
LOGW(_("libev thread exited\n"));
}
/**
* 向桥们发送数据
*/
int send_to_servers(char* buf, int buflen) {
struct sockaddr* addr;
struct sockaddr_in *baddr;
socklen_t addrlen;
int sendb;
char ipstr[128] = {0};
static int id = 0;
if (buflen > MAX_PACKET_SIZE) {
int ret = 0;
int split = buflen / 2;
//LOGI("要发送的数据大小为 %d 字节,超过最大包大小(%d 字节),将该包拆分为两个小包后再尝试发送\n", buflen, MAX_PACKET_SIZE);
LOGI(_("Packet is %d bytes, which excees max packet size limit (%d bytes), spilt the packet into two smaller packets before send.\n"), buflen, MAX_PACKET_SIZE);
ret += send_to_servers(buf, split);
ret += send_to_servers(buf + split, buflen - split);
return ret;
}
packet_t* p;
packet_t rawp;
p = (packet_t*)malloc(sizeof(*p) + buflen);
p->type = PKT_TYPE_DATA;
p->id = ++id;
p->buflen = buflen;
memcpy(((char*)p) + sizeof(*p), buf, buflen);
rawp = *p;
mpencrypt((char*)p, buflen + sizeof(*p));
int ts = time(NULL);
bridge_t *b;
struct list_head *l, *tmp;
list_for_each_safe(l, tmp, &g_bridge_list) {
b = list_entry(l, bridge_t, list);
baddr = (struct sockaddr_in*)&b->addr;
/// 1. 检查连接是否超时
if (ts - b->rc_time > UDP_KEEP_ALIVE) {
//LOGD("桥(%s:%u)空闲了 %d 秒,认为此桥已经断开,不向其转发数据包 %d\n", ipstr, ntohs(baddr->sin_port), ts - b->rc_time, p->id);
LOGD(_("No packet received from bridge (%s:%u) for %d seconds, assume the connection is closed, stop forward packet to it %d\n"), ipstr, ntohs(baddr->sin_port), ts - b->rc_time, p->id);
list_del(l);
free(l);
continue;
}
if (abs(b->rc_time - b->st_time) > UDP_INTERACTIVE_TIMEOUT) {
//LOGD("桥(%s:%u)最后发包与收包时间之差超过了 %d 秒(实际:%d),认为此桥已经断开,不向其转发数据包 %d\n", ipstr, ntohs(baddr->sin_port), UDP_INTERACTIVE_TIMEOUT, b->rc_time - b->st_time, p->id);
LOGD(_("The time difference between packet received and packet sent of bridge %s:%u is larger than %d seconds (Actually %d seconds), assume the connection is broken, stop forward packet to it %d\n"), ipstr, ntohs(baddr->sin_port), UDP_INTERACTIVE_TIMEOUT, b->rc_time - b->st_time, p->id);
list_del(l);
free(l);
continue;
}
b->st_time = time(NULL);
/// 2. 发送数据包
sendb = sendto(g_listen_fd, p, buflen + sizeof(*p), 0, &b->addr, b->addrlen);
if (sendb < 0) {
//LOGW("无法向桥(%s:%d)发送 %d 字节数据,包编号 %d: %s\n", ipstr, ntohs(baddr->sin_port), buflen, rawp.id, strerror(errno));
LOGW(_("Can't send packet to bridge(%s:%d) of %d bytes, packet ID is %d: %s\n"), ipstr, ntohs(baddr->sin_port), buflen, rawp.id, strerror(errno));
}
else if (sendb == 0) {
LOGW("Can't send packet to bridge, bridge may close the connection\n");
}
else {
//LOGD("向桥(端口:%u)发送了 %d 字节数据,包编号 %d\n", ntohs(baddr->sin_port), sendb, rawp.id);
LOGD(_("Forward packet to bridge(port %u) of %d bytes, packet ID is %d\n"), ntohs(baddr->sin_port), sendb, rawp.id);
}
}
free(p);
return 0;
}
/**
* 用于转发服务器消息到客户端的线程
*/
void* server_thread(void* ptr) {
int readb, sendb, buflen;
char* buf;
LOGD(_("Thread which forward packet from server to bridge is started\n"));
buflen = 65536;
buf = malloc(buflen);
g_target_fd = net_connect(g_target_host, g_target_port, SOCK_DGRAM);
if (g_target_fd < 0) {
LOGE(_("Could not connect to target server:%s\n"), strerror(errno));
return NULL;
}
while (1) {
memset(buf, 0x00, sizeof(buflen));
readb = recv(g_target_fd, buf, buflen, 0);
if (readb < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue;
}
else {
LOGI(_("Target server close the connection: %s\n"), strerror(errno));
g_target_fd = net_connect(g_target_host, g_target_port, SOCK_DGRAM);
continue;
}
}
else if (readb == 0) {
LOGW(_("Can't received packet from server, server close the connection\n"));
g_target_fd = net_connect(g_target_host, g_target_port, SOCK_DGRAM);
continue;
}
else {
/// 收到了数据,将数据转发给桥
send_to_servers(buf, readb);
}
}
free(buf);
LOGD(_("Thread which forward packet from server to bridge exited\n"));
return NULL;
}
int main(int argc, char** argv) {
int clientfd, listenfd;
setlocale(LC_ALL, "");
bindtextdomain("mptunnel", "locale");
textdomain("mptunnel");
if (argc <= 3) {
fprintf(stderr, _("Usage: <%s> <listen_port> <target_ip> <target_port>\n"), argv[0]);
fprintf(stderr, _("To disable encryption, set environment variable MPTUNNEL_ENCRYPT=0\n"));
exit(-1);
}
else {
/// 载入配置信息
g_listen_port = atoi(argv[1]);
g_target_host = strdup(argv[2]);
g_target_port = atoi(argv[3]);
if (g_listen_port <= 0 || g_listen_port >= 65536) {
LOGE("Invalid listen port `%s'\n", argv[1]);
exit(-2);
}
if (g_target_port <= 0 || g_target_port >= 65536) {
LOGE("Invalid target port `%s'\n", argv[3]);
exit(-3);
}
if (getenv("MPTUNNEL_ENCRYPT") == NULL) {
g_config_encrypt = 1;
}
else if(atoi(getenv("MPTUNNEL_ENCRYPT")) == 0) {
g_config_encrypt = 0;
}
else {
g_config_encrypt = 1;
}
LOGD(_("Configuration: Encryption %s\n"), (g_config_encrypt) ? _("enabled") : _("disabled"));
LOGD(_("Configuration: Local listening port: %d\n"), g_listen_port);
LOGD(_("Configuration: server:%s:%d\n"), g_target_host, g_target_port);
}
LOGD(_("Initializing libev thread\n"));
pthread_t tid;
pthread_create(&tid, NULL, ev_thread, NULL);
pthread_detach(tid);
/// 创建转发数据到目标服务器的线程
int* ptr = malloc(sizeof(int));
*ptr = clientfd;
pthread_create(&tid, NULL, server_thread, NULL);
pthread_detach(tid);
while (1) {
sleep(100);
}
return 0;
}
/**
* 初始化一个接收器 ev,用来处理收到的数据
*/
ev_io* init_recv_ev(int fd) {
ev_io *watcher = (ev_io*)malloc(sizeof(ev_io));
memset(watcher, 0x00, sizeof(*watcher));
ev_io_init(watcher, recv_bridge_callback, fd, EV_READ);
ev_io_start(g_ev_reactor, watcher);
return watcher;
}