forked from pagekite/libpagekite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pagekitec.c
304 lines (274 loc) · 8.61 KB
/
pagekitec.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
/******************************************************************************
pagekitec.c - A high-performance PageKite connector in C.
Usage: pagekitec [options] LPORT PROTO NAME.pagekite.me PPORT SECRET ...
*******************************************************************************
This file is Copyright 2011-2015, The Beanstalks Project ehf.
This program is free software: you can redistribute it and/or modify it under
the terms of the Apache License 2.0 as published by the Apache Software
Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the Apache License for more details.
You should have received a copy of the Apache License along with this program.
If not, see: <http://www.apache.org/licenses/>
Note: For alternate license terms, see the file COPYING.md.
******************************************************************************/
/* FIXME! */
#define HAVE_OPENSSL 1
#define HAVE_LUA 1
#define HAVE_IPV6 1
#include <pagekite.h>
#include <pkcommon.h>
#define EXIT_ERR_MANAGER_INIT 1
#define EXIT_ERR_USAGE 2
#define EXIT_ERR_ADD_KITE 3
#define EXIT_ERR_FRONTENDS 4
#define EXIT_ERR_START_THREAD 5
#define EXIT_ERR_ADD_LISTENER 6
#define MAX_PLUGIN_ARGS 128
pagekite_mgr m;
void usage(int ecode) {
fprintf(stderr, "This is pagekitec.c from libpagekite %s.\n\n", PK_VERSION);
fprintf(stderr, "Usage:\tpagekitec [options] LPORT PROTO"
" NAME.pagekite.me PPORT SECRET ...\n"
"Options:\n"
"\t-q\tDecrease verbosity (less log output)\n"
"\t-v\tIncrease verbosity (more log output)\n");
#ifdef HAVE_OPENSSL
fprintf(stderr, "\t-I\tConnect insecurely, without SSL.\n");
#endif
fprintf(stderr, "\t-S\tStatic setup, disable FE failover and DDNS updates\n"
"\t-w D\tWhite-label configuration using domain D.\n"
"\t-c N\tSet max connection count to N (default = 25)\n"
"\t-n N\tAlways connect to N spare frontends (default = 0)\n"
"\t-B N\tBail out (abort) after N logged errors\n"
"\t-E N\tAllow eviction of streams idle for >N seconds\n"
"\t-F x\tUse x (a DNS name) as frontend pool\n"
"\t-R\tChoose frontends at random, instead of pinging\n"
"\t-N\tDisable DNS-based updates of available frontends\n"
"\t-4\tDisable IPv4 frontends\n");
#ifdef HAVE_IPV6
fprintf(stderr, "\t-6\tDisable IPv6 frontends\n");
#endif
fprintf(stderr, "\t-C\tDisable auto-adding current DNS IP as a front-end\n"
"\t-W\tEnable watchdog thread (dumps core if we lock up)\n"
"\t-H\tDo not add X-Forwarded-Proto and X-Forwarded-For\n");
#ifdef HAVE_LUA
fprintf(stderr, "\t-o S=N\tEnable Lua plugin S with argument N\n"
"\t-L\tDisable by default all Lua plugins\n");
#endif
fprintf(stderr, "\n");
exit(ecode);
}
void raise_log_level(int sig) {
if (sig) pagekite_set_log_mask(NULL, PK_LOG_ALL);
}
void shutdown_pagekite(int sig) {
if (sig) pagekite_thread_stop(m);
}
void safe_exit(int code) {
#ifdef _MSC_VER
fprintf(stderr, "Exiting with status code %d.\n", code);
#endif
fclose(stderr);
exit(code);
}
int main(int argc, char **argv) {
unsigned int bail_on_errors = 0;
unsigned int conn_eviction_idle_s = 0;
char* proto;
char* kitename;
char* secret;
char* lua_settings[MAX_PLUGIN_ARGS+1];
char* whitelabel_tld = NULL;
int lua_settingc = 0;
int lua_no_defaults = 0;
int gotargs = 0;
int verbosity = 0;
int use_current = 1;
int use_fake_ping = 0;
int use_watchdog = 0;
int modify_http_headers = 1;
int max_conns = 25;
int spare_frontends = 0;
char* fe_hostname = NULL;
char* ddns_url = PAGEKITE_NET_DDNS;
int ac;
int pport;
int lport;
int flags = (PK_WITH_SSL | PK_WITH_IPV4 | PK_WITH_DYNAMIC_FE_LIST);
#ifdef HAVE_IPV6
flags |= PK_WITH_IPV6;
#endif
/* FIXME: Is this too lame? */
srand(time(0) ^ getpid());
while (-1 != (ac = getopt(argc, argv, "46c:B:CE:F:HIo:LNn:qRSvWw:Z"))) {
switch (ac) {
case '4':
flags &= ~PK_WITH_IPV4;
break;
#ifdef HAVE_IPV6
case '6':
flags &= ~PK_WITH_IPV6;
break;
#endif
case 'N':
flags &= ~PK_WITH_DYNAMIC_FE_LIST;
break;
case 'C':
use_current = 0;
break;
case 'v':
verbosity++;
break;
case 'q':
verbosity--;
break;
case 'I':
flags &= ~PK_WITH_SSL;
break;
case 'R':
use_fake_ping = 1;
break;
case 'S':
ddns_url = NULL;
break;
case 'W':
use_watchdog = 1;
break;
case 'H':
modify_http_headers = 0;
break;
case 'w':
gotargs++;
whitelabel_tld = strdup(optarg);
break;
case 'F':
gotargs++;
assert(fe_hostname == NULL);
fe_hostname = strdup(optarg);
break;
case 'B':
gotargs++;
if (1 == sscanf(optarg, "%u", &bail_on_errors)) break;
usage(EXIT_ERR_USAGE);
case 'c':
gotargs++;
if (1 == sscanf(optarg, "%d", &max_conns)) break;
usage(EXIT_ERR_USAGE);
case 'E':
gotargs++;
if (1 == sscanf(optarg, "%u", &conn_eviction_idle_s)) break;
usage(EXIT_ERR_USAGE);
case 'o':
if (lua_settingc >= MAX_PLUGIN_ARGS) usage(EXIT_ERR_USAGE);
gotargs++;
lua_settings[lua_settingc++] = strdup(optarg);
break;
case 'L':
lua_no_defaults = 1;
break;
case 'n':
gotargs++;
if (1 == sscanf(optarg, "%d", &spare_frontends)) break;
usage(EXIT_ERR_USAGE);
default:
usage(EXIT_ERR_USAGE);
}
gotargs++;
}
lua_settings[lua_settingc] = NULL;
if ((argc-1-gotargs) < 5 || ((argc-1-gotargs) % 5) != 0) {
usage(EXIT_ERR_USAGE);
}
#ifndef _MSC_VER
signal(SIGUSR1, &raise_log_level);
signal(SIGQUIT, &shutdown_pagekite);
signal(SIGINT, &shutdown_pagekite);
#endif
if (whitelabel_tld != NULL)
{
if (NULL == (m = pagekite_init_whitelabel(
"pagekitec",
1 + (argc-1-gotargs)/5, /* Kites */
max_conns,
flags,
verbosity,
whitelabel_tld)))
{
pagekite_perror(m, argv[0]);
safe_exit(EXIT_ERR_MANAGER_INIT);
}
}
else if (NULL == (m = pagekite_init(
"pagekitec",
1 + (argc-1-gotargs)/5, /* Kites */
PAGEKITE_NET_FE_MAX,
max_conns,
ddns_url,
flags,
verbosity)))
{
pagekite_perror(m, argv[0]);
safe_exit(EXIT_ERR_MANAGER_INIT);
}
/* Set all the parameters */
pagekite_want_spare_frontends(m, spare_frontends);
pagekite_enable_watchdog(m, use_watchdog);
pagekite_enable_http_forwarding_headers(m, modify_http_headers);
pagekite_enable_fake_ping(m, use_fake_ping);
pagekite_set_bail_on_errors(m, bail_on_errors);
pagekite_set_conn_eviction_idle_s(m, conn_eviction_idle_s);
pagekite_enable_lua_plugins(m, !lua_no_defaults, lua_settings);
for (ac = gotargs; ac+5 < argc; ac += 5) {
if ((1 != sscanf(argv[ac+1], "%d", &lport)) ||
(1 != sscanf(argv[ac+4], "%d", &pport))) {
pagekite_free(m);
usage(EXIT_ERR_USAGE);
}
proto = argv[ac+2];
kitename = argv[ac+3];
secret = argv[ac+5];
if ((0 > pagekite_add_kite(m, proto, kitename, pport, secret,
"localhost", lport)) ||
(use_current && (0 > (pagekite_add_frontend(m, kitename, pport)))))
{
pagekite_perror(m, argv[0]);
pagekite_free(m);
safe_exit(EXIT_ERR_ADD_KITE);
}
}
/* The API could do this stuff on INIT, but since we allow for manually
specifying a front-end hostname, we do things by hand. */
if (fe_hostname) {
if (0 > pagekite_lookup_and_add_frontend(m, fe_hostname, 443,
flags & PK_WITH_DYNAMIC_FE_LIST))
{
pagekite_perror(m, argv[0]);
pagekite_free(m);
safe_exit(EXIT_ERR_FRONTENDS);
}
}
else if (whitelabel_tld != NULL) {
if (0 > pagekite_add_whitelabel_frontends(m, flags, whitelabel_tld)) {
pagekite_perror(m, argv[0]);
pagekite_free(m);
safe_exit(EXIT_ERR_FRONTENDS);
}
}
else if (ddns_url != NULL) {
if (0 > pagekite_add_service_frontends(m, flags)) {
pagekite_perror(m, argv[0]);
pagekite_free(m);
safe_exit(EXIT_ERR_FRONTENDS);
}
}
if (0 > pagekite_thread_start(m)) {
pagekite_perror(m, argv[0]);
pagekite_free(m);
safe_exit(EXIT_ERR_START_THREAD);
}
pagekite_thread_wait(m);
pagekite_free(m);
return 0;
}