💾 Archived View for gemini.rmf-dev.com › repo › Vaati › gmi_proxy › files › b319efe88ba0d5f5e183176e… captured on 2023-04-26 at 13:30:49. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-04-19)
-=-=-=-=-=-=-
0 /* See LICENSE file for copyright and license details. */
1 #if defined(__OpenBSD__) || defined(__FreeBSD__)
2 #undef _POSIX_C_SOURCE
3 #include <sys/types.h>
4 #include <sys/sysctl.h>
5 #endif
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <poll.h>
12 #include <pthread.h>
13 #include <signal.h>
14 #include <fcntl.h>
15 #include <tls.h>
16 #include <netinet/in.h>
17 #include <netdb.h>
18 #include <sys/socket.h>
19 #ifdef __linux__
20 #include <sys/sysinfo.h>
21 #endif
22 #include "strlcpy.h"
23 #include "strnstr.h"
24 #include "util.h"
25 #include "server.h"
26 #include "conf.h"
27 #include "log.h"
28 #include "cert.h"
29 #include "sandbox.h"
30
31 #define MAX_THREADS 4096
32
33 #ifndef PATH_MAX
34 #define PATH_MAX 2048
35 #endif
36
37 #define MAX_CLIENTS 512
38
39 #define TIMEOUT_LAST 9
40 #define TIMEOUT_START 2
41
42 #define ALTERNATE
43
44 enum {
45 STATE_NEW, /* initial state after getting accepted */
46 STATE_TLS, /* tls accept completed */
47 STATE_HANDSHAKED, /* tls handshake completed */
48 STATE_READING, /* reading server response */
49 STATE_DONE
50 };
51
52 struct thread {
53 struct pollfd fds[MAX_CLIENTS + 1];
54 struct client clients[MAX_CLIENTS];
55 unsigned int last;
56 int pair[2];
57 pthread_t thread;
58 pthread_mutex_t mutex;
59 };
60
61 struct proxy {
62 struct tls_config *config;
63 struct tls *ctx;
64 int socket;
65 int pair[2];
66 bool running;
67 struct thread* threads;
68 int nthreads;
69 pthread_t listener;
70 pthread_t watch;
71 int watch_pair[2];
72 } proxy = {0};
73
74 /* hide query because it could be a password */
75 void sanitize_url(const char *url, char *out, size_t len) {
76
77 const char *ptr = strrchr(url, '?') + 1;
78 size_t i = ptr - url + 1;
79
80 strlcpy(out, url, MAX(len, i));
81 if (i >= len) return;
82 strlcpy(&out[i - 1], "<*>", len - i);
83 }
84
85
86 void lock_thread(struct thread* thread) {
87 if (thread)
88 pthread_mutex_lock(&thread->mutex);
89 }
90
91 void unlock_thread(struct thread* thread) {
92 if (thread)
93 pthread_mutex_unlock(&thread->mutex);
94 }
95
96 void proxy_clean() {
97
98 int id, i;
99
100 if (!proxy.running) return;
101 proxy.running = 0;
102 log_info("Shutting down server");
103 id = -1;
104 for (i = 0; i < proxy.nthreads; i++) {
105 int result;
106 send(proxy.threads[i].pair[1], &id, sizeof(id), 0);
107 close(proxy.threads[i].pair[1]);
108 result = pthread_mutex_trylock(&proxy.threads[i].mutex);
109 if (result && result != EBUSY) exit(-1);
110 pthread_mutex_unlock(&proxy.threads[i].mutex);
111 pthread_mutex_destroy(&proxy.threads[i].mutex);
112 }
113 send(proxy.pair[1], &id, sizeof(id), 0);
114 close(proxy.watch_pair[0]);
115 close(proxy.watch_pair[1]);
116 close(proxy.pair[0]);
117 close(proxy.pair[1]);
118 if (proxy.config) {
119 tls_config_free(proxy.config);
120 proxy.config = NULL;
121 }
122 if (proxy.ctx) {
123 tls_close(proxy.ctx);
124 tls_free(proxy.ctx);
125 proxy.ctx = NULL;
126 }
127 }
128
129 int proxy_bind(int port) {
130
131 struct sockaddr_in addr;
132
133 proxy.socket = socket(AF_INET, SOCK_STREAM, 0);
134 if (proxy.socket == -1) {
135 log_error("Failed to open socket : %s", strerror(errno));
136 return -1;
137 }
138
139 addr.sin_family = AF_INET;
140 addr.sin_port = htons(port);
141 addr.sin_addr.s_addr = INADDR_ANY;
142 if (bind(proxy.socket, (struct sockaddr *) &addr, sizeof(addr))) {
143 log_error("Failed to bind socket : %s", strerror(errno));
144 return-1;
145 }
146
147 if (listen(proxy.socket, 5)) {
148 log_error("Failed to listen : %s", strerror(errno));
149 return -1;
150 }
151
152 return 0;
153 }
154
155 int proxy_accept(struct client *client);
156 int proxy_new(struct thread* thread, int fd) {
157
158 struct client* client = NULL;
159 unsigned int id = -1, i;
160
161 for (i = 0; i < SIZEOF(thread->clients); i++) {
162 if (thread->clients[i].addr_len != 0) continue;
163 client = &thread->clients[i];
164 id = i;
165 break;
166 }
167 if (!client) return -1;
168 PZERO(client);
169 client->addr_len = sizeof(client->addr);
170 client->server_sock = -1;
171 client->sock = accept(fd, (struct sockaddr*)&client->addr,
172 &client->addr_len);
173 if (client->sock == -1) {
174 PZERO(client);
175 sleep(1); /* sleep in case of a shortage of file descriptors */
176 return -1;
177 }
178
179 client->state = STATE_NEW;
180 client->id = id + 1;
181 client->tid = thread - proxy.threads;
182 client->thread = thread;
183 client->last = client->start = time(NULL);
184 thread->fds[id + 1].events = POLLIN;
185 thread->fds[id + 1].fd = client->sock;
186
187 if (thread->last < id + 1)
188 thread->last = id + 1;
189 send(thread->pair[1], &client->id, sizeof(client->id), 0);
190 proxy_accept(client);
191 return 0;
192 }
193
194 int proxy_accept(struct client *client) {
195
196 if (tls_accept_socket(proxy.ctx, &client->ctx, client->sock)) {
197 return -1;
198 }
199
200 #ifdef DEBUG
201 log_debug("Incoming connection [%d, %d]", client->tid, client->id);
202 #endif
203 client->state = STATE_TLS;
204 return 0;
205 }
206
207 void* proxy_listen() {
208
209 struct pollfd fds[2];
210 int i, ready;
211
212 if (socketpair(AF_UNIX, SOCK_STREAM, 0, proxy.pair)) {
213 log_error("Initialization failure, socketpair: %s",
214 strerror(errno));
215 return NULL;
216 }
217
218 fds[0].events = POLLIN;
219 fds[0].fd = proxy.pair[0];
220 fds[1].events = POLLIN;
221 fds[1].fd = proxy.socket;
222 i = 0;
223 while (proxy.running) {
224 ready = poll(fds, 2, -1);
225 if (!proxy.running) break;
226 if (ready == -1) {
227 log_error("poll error: %s", strerror(errno));
228 proxy_clean();
229 break;
230 }
231 if (fds[0].revents & POLLIN) {
232 recv(fds[0].fd, &i, sizeof(i), 0);
233 if (!proxy.running) break;
234 ready--;
235 if (!ready) continue;
236 }
237 #ifdef DEBUG
238 log_debug("accepting new connection on thread %d (%d)",
239 i, ready);
240 #endif
241 if (fds[1].revents & POLLIN) {
242 proxy_new(&proxy.threads[i], proxy.socket);
243 }
244 i = (i + 1) % proxy.nthreads;
245 }
246 return NULL;
247 }
248
249 void proxy_close(struct client *client) {
250 client->thread->fds[client->id].fd = -1;
251 client->thread->fds[client->id].events = POLLIN;
252 #ifdef DEBUG
253 log_debug_r(client, "Closing connection [%d, %d]",
254 client->tid, client->id);
255 #endif
256 if (client->conn) {
257 tls_close(client->conn);
258 tls_free(client->conn);
259 }
260 if (client->server_sock > 0)
261 close(client->server_sock);
262 if (client->conn_config) {
263 tls_config_free(client->conn_config);
264 }
265 if (client->ctx) {
266 tls_close(client->ctx);
267 tls_free(client->ctx);
268 }
269 if (client->sock > 0)
270 close(client->sock);
271 PZERO(client);
272 }
273
274 void* proxy_watch() {
275 int code, i;
276 struct pollfd pfd;
277 socketpair(AF_UNIX, SOCK_STREAM, 0, proxy.watch_pair);
278 pfd.revents = POLLIN;
279 pfd.fd = proxy.watch_pair[1];
280 start:
281 if (poll(&pfd, 1, 2000) > 0)
282 recv(proxy.watch_pair[1], &code, sizeof(code), 0);
283 if (!proxy.running) return NULL;
284 for (i = 0; i < proxy.nthreads; i++) {
285 time_t now = time(NULL);
286 size_t j;
287 for (j = 0; j < SIZEOF(proxy.threads[i].clients); j++) {
288 struct client *client = &proxy.threads[i].clients[j];
289 if (proxy.threads[i].fds[j + 1].fd == -1) continue;
290 if ((!client->handshaked &&
291 client->last + TIMEOUT_START < now) ||
292 (client->last + TIMEOUT_LAST < now)) {
293 #ifdef DEBUG
294 log_debug_r(&proxy.threads[i].clients[j],
295 "Closing hanged connection");
296 #endif
297 lock_thread(&proxy.threads[i]);
298 proxy_close(&proxy.threads[i].clients[j]);
299 unlock_thread(&proxy.threads[i]);
300 send(proxy.threads[i].pair[1], &i,
301 sizeof(i), 0);
302 }
303 }
304 }
305 goto start;
306 }
307
308 int proxy_connect(struct client *client, const char *host, const char *port) {
309
310 int sock, addr_size, connected, failed;
311 int family = AF_INET;
312 struct addrinfo hints = {0}, *result;
313 struct sockaddr_in addr4 = {0};
314 struct sockaddr_in6 addr6 = {0};
315
316 sock = socket(family, SOCK_STREAM, 0);
317 if (sock == -1) {
318 log_error_r(client, "Failed to create socket: %s",
319 strerror(errno));
320 return -1;
321 }
322
323 hints.ai_family = AF_INET;
324 hints.ai_socktype = SOCK_STREAM;
325 hints.ai_flags |= AI_CANONNAME;
326 errno = 0;
327
328 if ((getaddrinfo(host, NULL, &hints, &result))) {
329 log_error_r(client, "Unknown domain name: %s, %s",
330 host, strerror(errno));
331 close(sock);
332 return -1;
333 }
334
335 if (result->ai_family == AF_INET) {
336 addr4.sin_addr =
337 ((struct sockaddr_in*)result->ai_addr)->sin_addr;
338 addr4.sin_family = AF_INET;
339 addr4.sin_port = htons(atoi(port));
340 } else if (result->ai_family == AF_INET6) {
341 addr6.sin6_addr =
342 ((struct sockaddr_in6*)result->ai_addr)->sin6_addr;
343 addr6.sin6_family = AF_INET6;
344 addr6.sin6_port = htons(atoi(port));
345 } else {
346 log_error_r(client,
347 "Unexpected error, invalid address family %s", host);
348 close(sock);
349 return -1;
350 }
351
352 family = result->ai_family;
353 addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) :
354 sizeof(struct sockaddr_in6);
355
356 failed = connect(sock, (family == AF_INET) ?
357 (struct sockaddr*)&addr4 :
358 (struct sockaddr*)&addr6, addr_size);
359 failed = failed ? (errno != EAGAIN && errno != EWOULDBLOCK &&
360 errno != EINPROGRESS && errno != EALREADY &&
361 errno != 0) : failed;
362 connected = 0;
363 while (!failed) {
364
365 struct pollfd fds[2];
366 int count, value, ret;
367 socklen_t len;
368
369 fds[0].fd = sock;
370 fds[0].events = POLLOUT;
371 count = poll(fds, 1, 2 * 1000);
372 if (count < 1 || fds[0].revents != POLLOUT)
373 break;
374
375 len = sizeof(value);
376 ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &value, &len);
377 connected = (value == 0 && ret == 0);
378 break;
379 }
380
381 freeaddrinfo(result);
382
383 if (!connected) {
384 log_error_r(client, "Connection to %s:%s timed out : %s",
385 host, port, strerror(errno));
386 close(sock);
387 return -1;
388 }
389
390 if (tls_connect_socket(client->conn, sock, host)) {
391 log_error_r(client, "Unable to connect to: %s:%s : %s",
392 host, port,
393 ERRNO_IF_NULL(tls_error(client->ctx)));
394 close(sock);
395 return -1;
396 }
397
398 if (tls_handshake(client->conn)) {
399 log_error_r(client, "Handshake failed with %s:%s : %s",
400 host, port,
401 ERRNO_IF_NULL(tls_error(client->ctx)));
402 close(sock);
403 return -1;
404 }
405
406 client->server_sock = sock;
407
408 return 0;
409 }
410
411 int proxy_create_cert(struct client *client) {
412
413 char crt[PATH_MAX];
414 char key[PATH_MAX];
415 const char* path;
416 const char* hash;
417 int fd;
418
419 hash = tls_peer_cert_hash(client->ctx);
420 if (!hash) return 0;
421 hash += 7; /* the hash start with 'SHA256:' */
422 path = conf.clients;
423 snprintf(crt, sizeof(crt), "%s/%s.crt", path, hash);
424 snprintf(key, sizeof(key), "%s/%s.key", path, hash);
425 fd = open(crt, O_RDONLY);
426 if (fd < 0 && cert_create(crt, key) < 0) {
427 if (fd > -1) close(fd);
428 log_error_r(client, "Failed to create client certificate");
429 return 0;
430 } else {
431 close(fd);
432 }
433 tls_config_set_keypair_file(client->conn_config, crt, key);
434 return 1;
435 }
436
437 int proxy_handshake(struct client *client) {
438
439 const char *servername;
440 int len;
441
442 if (tls_handshake(client->ctx)) return -1;
443
444 servername = tls_conn_servername(client->ctx);
445 if (!servername) {
446 log_error_r(client, "Failed to fetch server name");
447 return STRCPY(client->request, "53 Unknown domain\r\n");
448 }
449
450 client->server = conf_get(servername);
451 if (!client->server) {
452 log_error_r(client, "No virtual server for %s",
453 servername);
454 return STRCPY(client->request, "53 Invalid domain\r\n");
455 }
456
457 client->conn_config = tls_config_new();
458 if (!client->conn_config) {
459 log_error_r(client, "tls_config_new: %s", strerror(errno));
460 return STRCPY(client->request, "53 Bad gateway\r\n");
461 }
462 tls_config_insecure_noverifycert(client->conn_config);
463
464 client->conn = tls_client();
465 if (!client->conn) {
466 log_error_r(client, "tls_client: %s", strerror(errno));
467 return STRCPY(client->request, "53 Bad gateway\r\n");
468 }
469
470 if (client->server->client)
471 proxy_create_cert(client);
472
473 tls_configure(client->conn, client->conn_config);
474
475 len = proxy_connect(client, client->server->relayto,
476 client->server->relayto_port);
477 if (len < 0)
478 return STRCPY(client->request, "53 Bad gateway\r\n");
479
480 client->handshaked = 1;
481 client->state = STATE_HANDSHAKED;
482 #ifdef DEBUG
483 log_debug_r(client, "handshake completed");
484 #endif
485
486 return 0;
487 }
488
489 int proxy_read_request(struct client *client) {
490
491 int i;
492 char *ptr, hostname[1024], buf[1024], url[1024];
493
494 i = TLS_WANT_POLLIN;
495 i = tls_read(client->ctx, &client->request[client->len],
496 sizeof(client->request) - client->len);
497 if (i == TLS_WANT_POLLIN) return 0;
498 if (i <= 0) {
499 log_error_r(client, "Failed to read server data, %s",
500 tls_error(client->ctx));
501 return -1;
502 }
503 client->len += i;
504 if (client->request[client->len - 2] != '\r' ||
505 client->request[client->len - 1] != '\n') {
506 if (client->len < sizeof(client->request))
507 return 0;
508 log_error_r(client, "Client sent invalid request");
509 return -1;
510 }
511
512 ptr = strnstr(client->request, "gemini://", sizeof(client->request));
513 if (!ptr) {
514 log_error_r(client, "Client sent invalid request");
515 return STRCPY(client->request, "59 Request too long\r\n");
516 }
517 ptr += sizeof("gemini://") - 1;
518 client->request[client->len - 2] = '\0';
519 STRCPY(buf, ptr);
520 client->request[client->len - 2] = '\r';
521 ptr = strchr(buf, '/');
522 strlcpy(hostname, buf, ptr ?
523 (unsigned)(ptr - buf + 1) : sizeof(hostname));
524 if (strncmp(hostname, client->server->name, sizeof(hostname))) {
525 log_error_r(client, "Client requested invalid server name");
526 return STRCPY(client->request, "59 Wrong server name\r\n");
527 }
528 if (ptr) STRCPY(client->url, ptr);
529 else STRCPY(client->url, "/");
530
531 sanitize_url(client->url, url, sizeof(url));
532 log_info_r(client, "%s%s", client->server->relayto, url);
533
534 i = snprintf(buf, sizeof(buf), "gemini://%s%s\r\n",
535 client->server->relayto, client->url);
536 if (tls_write(client->conn, buf, i) != i) {
537 log_error_r(client, ERRNO_IF_NULL(tls_error(client->conn)));
538 return STRCPY(client->request, "53 Invalid response\r\n");
539 }
540
541 client->thread->fds[client->id].fd = client->server_sock;
542 client->state = STATE_READING;
543 #ifdef DEBUG
544 log_debug_r(client, "request sent");
545 #endif
546
547 return 0;
548 }
549
550 int proxy_read_server(struct client *client) {
551
552 int len;
553 char buf[1024];
554
555 len = tls_read(client->conn, buf, sizeof(buf));
556 if (!len) {
557 client->thread->fds[client->id].fd = client->sock;
558 client->thread->fds[client->id].events = POLLOUT;
559 #ifdef DEBUG
560 log_debug_r(client, "transfer completed");
561 #endif
562 client->state = STATE_DONE;
563 return 0;
564 }
565 if (len == TLS_WANT_POLLIN) return 0;
566 if (len > 0) {
567 if (tls_write(client->ctx, buf, len) != len)
568 return -1;
569 #ifdef ALTERNATE
570 client->thread->fds[client->id].events = POLLOUT;
571 client->thread->fds[client->id].fd = client->sock;
572 #endif
573 return 0;
574 }
575 log_error_r(client, ERRNO_IF_NULL(tls_error(client->conn)));
576 return STRCPY(client->request, "53 Invalid response\r\n");
577 }
578
579 int proxy_read(struct client *client) {
580
581 int len;
582
583 lock_thread(client->thread);
584 client->last = time(NULL);
585 len = 0;
586 switch (client->state) {
587 case STATE_NEW:
588 len = proxy_accept(client);
589 break;
590 case STATE_TLS:
591 len = proxy_handshake(client);
592 break;
593 case STATE_HANDSHAKED:
594 len = proxy_read_request(client);
595 break;
596 case STATE_READING:
597 len = proxy_read_server(client);
598 break;
599 }
600 if (len > 0) {
601 tls_write(client->ctx, client->request, len);
602 client->last = time(NULL);
603 client->thread->fds[client->id].events = POLLOUT;
604 }
605 unlock_thread(client->thread);
606 return -!!len;
607 }
608
609 void* proxy_thread(void *ptr) {
610 struct thread *thread = ptr;
611 while (proxy.running) {
612 unsigned int nfds = SIZEOF(thread->fds), i;
613 /* 1 + thread->last */
614 int ready = poll(thread->fds, nfds - 1, -1);
615 if (!proxy.running) break;
616 if (ready == -1) {
617 log_error("poll error: %s", strerror(errno));
618 proxy_clean();
619 break;
620 }
621 if (thread->fds[0].revents == POLLIN) {
622 char b;
623 recv(thread->fds[0].fd, &b, sizeof(b), 0);
624 ready--;
625 if (!proxy.running) break;
626 }
627 for (i = 1; i < nfds && ready > 0; i++) {
628 int id = i - 1;
629 if (thread->fds[i].fd == -1) continue;
630 ready--;
631 if (thread->fds[i].revents & POLLOUT) {
632 #ifdef ALTERNATE
633 if (thread->clients[id].state != STATE_DONE) {
634 thread->fds[i].events = POLLIN;
635 thread->fds[i].fd =
636 thread->clients[id].
637 server_sock;
638 continue;
639 }
640 #endif
641 proxy_close(&thread->clients[id]);
642 continue;
643 }
644 if (thread->fds[i].revents & POLLIN ||
645 thread->fds[i].revents & POLLRDNORM ||
646 thread->fds[i].revents & POLLRDBAND ) {
647 if (!proxy_read(&thread->clients[id]))
648 continue;
649 log_error_r(&thread->clients[id],
650 "Failed to read data from client");
651 }
652 proxy_close(&thread->clients[id]);
653 }
654 }
655 return NULL;
656 }
657
658 int proxy_init_thread() {
659
660 int i;
661 unsigned int j;
662
663 #if defined(__OpenBSD__) || defined(__FreeBSD__)
664 proxy.nthreads = 0;
665 if (conf.threads) {
666 proxy.nthreads = conf.threads;
667 } else {
668 int mib[2], maxproc;
669 size_t len;
670
671 mib[0] = CTL_KERN;
672 mib[1] = KERN_MAXPROC;
673 len = sizeof(maxproc);
674 if (!sysctl(mib, 2, &maxproc, &len, NULL, 0)) {
675 proxy.nthreads = maxproc;
676 }
677 }
678 #else
679 proxy.nthreads = conf.threads ? conf.threads : get_nprocs();
680 #endif
681 if (proxy.nthreads < 1) proxy.nthreads = 1;
682 if (proxy.nthreads > MAX_THREADS) proxy.nthreads = MAX_THREADS;
683 proxy.threads = malloc(sizeof(struct thread) * proxy.nthreads);
684 if (!proxy.threads) {
685 log_error("Memory allocation failure");
686 return -1;
687 }
688 memset(proxy.threads, 0, sizeof(struct thread) * proxy.nthreads);
689 for (i = 0; i < proxy.nthreads; i++) {
690 if (socketpair(AF_UNIX, SOCK_STREAM, 0, proxy.threads[i].pair))
691 return -1;
692 for (j = 0; j < SIZEOF(proxy.threads[i].fds); j++)
693 proxy.threads[i].fds[j].fd = -1;
694
695 proxy.threads[i].fds[0].fd = proxy.threads[i].pair[0];
696 proxy.threads[i].fds[0].events = POLLIN;
697 pthread_mutex_init(&proxy.threads[i].mutex, NULL);
698 pthread_create(&proxy.threads[i].thread, NULL,
699 proxy_thread, &proxy.threads[i]);
700 }
701 pthread_create(&proxy.listener, NULL, proxy_listen, NULL);
702 pthread_create(&proxy.watch, NULL, proxy_watch, NULL);
703 return 0;
704 }
705
706 void proxy_handler(int sig) {
707 if (!sig) return;
708 proxy_clean();
709 }
710
711 int proxy_init(int port) {
712
713 struct server *server;
714 int started;
715
716 signal(SIGPIPE, SIG_IGN);
717
718 if (tls_init()) {
719 log_error("tls_init: %s", strerror(errno));
720 return -1;
721 }
722
723 proxy.config = tls_config_new();
724 if (!proxy.config) {
725 log_error("tls_config_new: %s", strerror(errno));
726 return -1;
727 }
728 tls_config_verify_client_optional(proxy.config);
729
730
731 proxy.ctx = tls_server();
732 if (!proxy.ctx) {
733 log_error("tls_server: %s", strerror(errno));
734 return -1;
735 }
736
737 started = 0;
738 for (server = servers; server->exist != END_OF_ARRAY; server++) {
739 int ret;
740 if (!server->exist) continue;
741 ret = started ?
742 tls_config_add_keypair_file(proxy.config,
743 server->certificate, server->key) :
744 tls_config_set_keypair_file(proxy.config,
745 server->certificate, server->key);
746 started = 1;
747 if (ret) {
748 const char *error = tls_config_error(proxy.config);
749 log_error("%s", ERRNO_IF_NULL(error));
750 return -1;
751 }
752 }
753
754 if (sandbox()) {
755 log_error("Sandboxing failure: %s", strerror(errno));
756 return -1;
757 }
758
759 tls_config_insecure_noverifycert(proxy.config);
760
761 if (tls_configure(proxy.ctx, proxy.config)) {
762 const char *error = tls_error(proxy.ctx);
763 log_error("tls_configure: %s", ERRNO_IF_NULL(error));
764 return -1;
765 }
766
767 if (proxy_bind(port)) {
768 return -1;
769 }
770
771 proxy.running = 1;
772 if (proxy_init_thread()) {
773 return -1;
774 }
775 log_info("Server listening on port %d", port);
776 log_info("%d thread%s created", proxy.nthreads,
777 proxy.nthreads > 1 ? "s" : "");
778
779 signal(SIGINT, proxy_handler);
780
781 return 0;
782 }
783
784 void proxy_join() {
785 int i;
786 if (!proxy.threads) return;
787 for (i = 0; i < proxy.nthreads; i++) {
788 pthread_join(proxy.threads[i].thread, NULL);
789 }
790 pthread_join(proxy.listener, NULL);
791 pthread_join(proxy.watch, NULL);
792 free(proxy.threads);
793 log_info("Server stopped");
794 }
795