2019-02-12 19:33:12 +00:00
|
|
|
#include "donar_client.h"
|
|
|
|
|
|
|
|
void load_onion_services(struct donar_client_ctx* ctx, char* onion_file, int ports_count) {
|
|
|
|
tor_os_create (&(ctx->tos), onion_file, NULL, ports_count);
|
|
|
|
tor_os_read (&(ctx->tos));
|
|
|
|
}
|
|
|
|
|
2019-02-15 14:45:56 +00:00
|
|
|
void init_tcp_client(struct donar_client_ctx* ctx, int i) {
|
2019-02-18 13:35:09 +00:00
|
|
|
struct evt_core_cat cat = {0};
|
|
|
|
struct evt_core_fdinfo fdinfo = {0};
|
|
|
|
char url_buf[255];
|
|
|
|
int err;
|
2019-02-15 14:45:56 +00:00
|
|
|
|
|
|
|
ctx->ports[i] = 7500 + i;
|
2019-02-18 13:35:09 +00:00
|
|
|
cat.name = "configure-socks5";
|
|
|
|
fdinfo.cat = &cat;
|
|
|
|
fdinfo.url = url_buf;
|
2019-02-12 20:45:15 +00:00
|
|
|
|
2019-02-15 14:45:56 +00:00
|
|
|
while (1) {
|
2019-02-18 13:35:09 +00:00
|
|
|
fdinfo.fd = create_tcp_client("127.0.0.1", "9050");
|
|
|
|
if (fdinfo.fd < 0) goto failed_socks5;
|
|
|
|
ctx->client_sock[i].fd = fdinfo.fd;
|
2019-02-15 14:45:56 +00:00
|
|
|
ctx->client_sock[i].state = SOCKS5_STATE_NEW;
|
2019-02-18 13:35:09 +00:00
|
|
|
sprintf(url_buf, "socks5:dist:%d", i);
|
|
|
|
evt_core_add_fd (&(ctx->evts), &fdinfo);
|
|
|
|
//@FIXME: We suppose that we will be able to do the whole write at once which is wrong
|
|
|
|
err = socks5_handshake_syn(fdinfo.fd);
|
2019-02-15 14:45:56 +00:00
|
|
|
if (err) goto failed_socks5;
|
2019-02-12 20:45:15 +00:00
|
|
|
|
2019-02-15 14:45:56 +00:00
|
|
|
break;
|
2019-02-12 20:45:15 +00:00
|
|
|
failed_socks5:
|
|
|
|
fprintf(stderr, "Failed connection for socket %d/%d. Sleeping 2 seconds...\n",i+1, CLIENT_PORT_SIZE);
|
2019-02-18 13:35:09 +00:00
|
|
|
close(fdinfo.fd);
|
2019-02-12 20:45:15 +00:00
|
|
|
sleep(2);
|
|
|
|
}
|
2019-02-12 19:33:12 +00:00
|
|
|
}
|
|
|
|
|
2019-02-19 09:32:33 +00:00
|
|
|
void configure_tcp_clients(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) {
|
2019-02-15 14:45:56 +00:00
|
|
|
int err, pos;
|
2019-02-19 09:32:33 +00:00
|
|
|
struct donar_client_ctx* app_ctx = (struct donar_client_ctx*) fdinfo->cat->app_ctx;
|
2019-02-15 14:45:56 +00:00
|
|
|
|
|
|
|
pos = -1;
|
|
|
|
for (int i = 0; i < CLIENT_PORT_SIZE; i++) {
|
2019-02-19 09:32:33 +00:00
|
|
|
if (app_ctx->client_sock[i].fd == fdinfo->fd) {
|
2019-02-15 14:45:56 +00:00
|
|
|
pos = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char target_host[255];
|
|
|
|
if (strlen(app_ctx->tos.keys[pos].pub) > 254) {
|
|
|
|
fprintf(stderr, "Domain name is too long\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
sprintf(target_host, "%s.onion", app_ctx->tos.keys[pos].pub);
|
|
|
|
|
|
|
|
switch (app_ctx->client_sock[pos].state) {
|
|
|
|
case SOCKS5_STATE_NEW:
|
|
|
|
//@FIXME: We suppose that we will be able to do the whole read at once which is wrong
|
2019-02-19 09:32:33 +00:00
|
|
|
err = socks5_handshake_ack (fdinfo->fd);
|
2019-02-15 14:45:56 +00:00
|
|
|
if (err < 0) goto on_socks5_err;
|
|
|
|
//@FIXME: We suppose that we will be able to do the whole write at once which is wrong too
|
2019-02-19 09:32:33 +00:00
|
|
|
err = socks5_connect_dns(fdinfo->fd, target_host, app_ctx->ports[pos]);
|
2019-02-15 14:45:56 +00:00
|
|
|
if (err < 0) goto on_socks5_err;
|
|
|
|
app_ctx->client_sock[pos].state = SOCKS5_STATE_ACK;
|
|
|
|
printf("Socket %d/%d %s:%d is connecting...\n", pos+1, CLIENT_PORT_SIZE, target_host, app_ctx->ports[pos]);
|
|
|
|
break;
|
|
|
|
case SOCKS5_STATE_ACK:
|
|
|
|
//@FIXME: We suppose that we will be able to do the whole read at once which is wrong too
|
2019-02-19 09:32:33 +00:00
|
|
|
err = socks5_reply (fdinfo->fd);
|
2019-02-15 14:45:56 +00:00
|
|
|
if (err < 0) goto on_socks5_err;
|
|
|
|
app_ctx->client_sock[pos].state = SOCKS5_STATE_RDY;
|
|
|
|
int sock1, sock2;
|
2019-02-19 09:32:33 +00:00
|
|
|
sock1 = dup(fdinfo->fd);
|
|
|
|
sock2 = dup(fdinfo->fd);
|
2019-02-15 14:45:56 +00:00
|
|
|
if (sock1 < 0 || sock2 < 0) goto on_socks5_err;
|
2019-02-19 09:32:33 +00:00
|
|
|
void* fdcat = evt_core_rm_fd (ctx, fdinfo->fd);
|
2019-02-15 14:45:56 +00:00
|
|
|
if (fdcat == NULL) goto on_socks5_err;
|
2019-02-18 13:35:09 +00:00
|
|
|
|
|
|
|
struct evt_core_fdinfo fdinfo = {0};
|
|
|
|
struct evt_core_cat cat = {0};
|
|
|
|
char url[1024];
|
|
|
|
fdinfo.cat = &cat;
|
|
|
|
fdinfo.url = url;
|
|
|
|
|
|
|
|
fdinfo.cat->name = "tcp-write";
|
|
|
|
fdinfo.fd = sock1;
|
|
|
|
sprintf(fdinfo.url, "tcp:write:127.0.0.1:%d", app_ctx->ports[pos]);
|
|
|
|
evt_core_add_fd (ctx, &fdinfo);
|
|
|
|
|
|
|
|
fdinfo.cat->name = "tcp-read";
|
|
|
|
fdinfo.fd = sock2;
|
|
|
|
sprintf(fdinfo.url, "tcp:read:127.0.0.1:%d", app_ctx->ports[pos]);
|
|
|
|
evt_core_add_fd (ctx, &fdinfo);
|
|
|
|
|
2019-02-15 14:45:56 +00:00
|
|
|
printf("Socket %d/%d %s:%d has been added to the pool!\n", pos+1, CLIENT_PORT_SIZE, target_host, app_ctx->ports[pos]);
|
|
|
|
break;
|
|
|
|
case SOCKS5_STATE_RDY:
|
|
|
|
goto on_socks5_err;
|
|
|
|
break;
|
|
|
|
case SOCKS5_STATE_ERR:
|
|
|
|
goto on_socks5_err;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
on_socks5_err:
|
|
|
|
perror("An error occured while connecting to an Onion Service");
|
|
|
|
app_ctx->client_sock[pos].state = SOCKS5_STATE_ERR;
|
2019-02-19 09:32:33 +00:00
|
|
|
evt_core_rm_fd (ctx, fdinfo->fd);
|
2019-02-15 14:45:56 +00:00
|
|
|
init_tcp_client (app_ctx, pos);
|
|
|
|
}
|
|
|
|
|
2019-02-19 14:17:47 +00:00
|
|
|
void free_udp_t(void* v) {
|
|
|
|
struct udp_target* udp_t = v;
|
|
|
|
udp_t->ref_count--;
|
|
|
|
if (udp_t <= 0) {
|
|
|
|
free(udp_t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 17:09:51 +00:00
|
|
|
void init_udp_socket(char* port, struct donar_client_ctx* ctx) {
|
2019-02-12 21:07:47 +00:00
|
|
|
int sock1, sock2;
|
2019-02-18 13:35:09 +00:00
|
|
|
char url[1024];
|
|
|
|
struct evt_core_cat cat = {0};
|
|
|
|
struct evt_core_fdinfo fdinfo = {0};
|
2019-02-19 14:17:47 +00:00
|
|
|
|
|
|
|
// 1. Init shared parameters for the fdinfo structure
|
|
|
|
struct udp_target* udp_t = malloc(sizeof(struct udp_target));
|
|
|
|
if (udp_t == NULL) goto socket_failed;
|
|
|
|
memset(udp_t, 0, sizeof(struct udp_target));
|
|
|
|
udp_t->ref_count = 2;
|
|
|
|
|
2019-02-18 13:35:09 +00:00
|
|
|
fdinfo.cat = &cat;
|
|
|
|
fdinfo.url = url;
|
2019-02-19 14:17:47 +00:00
|
|
|
fdinfo.free_other = free_udp_t;
|
|
|
|
fdinfo.other = udp_t;
|
2019-02-18 13:35:09 +00:00
|
|
|
|
2019-02-19 14:17:47 +00:00
|
|
|
// 2. Duplicate sockets
|
2019-02-19 09:32:33 +00:00
|
|
|
sock1 = create_udp_server (port);
|
2019-02-12 21:07:47 +00:00
|
|
|
if (sock1 < 0) goto socket_failed;
|
|
|
|
sock2 = dup(sock1);
|
|
|
|
if (sock2 < 0) goto socket_failed;
|
2019-02-18 13:35:09 +00:00
|
|
|
|
2019-02-19 14:17:47 +00:00
|
|
|
// 3. Register them
|
2019-02-18 13:35:09 +00:00
|
|
|
fdinfo.cat->name = "udp-read";
|
|
|
|
fdinfo.fd = sock1;
|
|
|
|
sprintf(fdinfo.url, "udp:read:127.0.0.1:%s", port);
|
|
|
|
evt_core_add_fd (&(ctx->evts), &fdinfo);
|
|
|
|
|
|
|
|
fdinfo.cat->name = "udp-write";
|
|
|
|
fdinfo.fd = sock2;
|
|
|
|
sprintf(fdinfo.url, "udp:write:127.0.0.1:%s", port);
|
|
|
|
evt_core_add_fd (&(ctx->evts), &fdinfo);
|
2019-02-12 21:07:47 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
socket_failed:
|
2019-02-15 17:09:51 +00:00
|
|
|
fprintf(stderr, "UDP socket init failed\n");
|
2019-02-12 21:07:47 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2019-02-15 17:09:51 +00:00
|
|
|
void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, char* onion_file, GPtrArray* ports) {
|
2019-02-12 19:33:12 +00:00
|
|
|
evt_core_init (&(ctx->evts));
|
2019-02-15 14:45:56 +00:00
|
|
|
struct evt_core_cat init_socks5 = {
|
|
|
|
.app_ctx = ctx,
|
|
|
|
.free_app_ctx = NULL,
|
|
|
|
.cb = configure_tcp_clients,
|
|
|
|
.name = "configure-socks5",
|
|
|
|
.flags = EPOLLIN | EPOLLET,
|
|
|
|
.socklist = NULL
|
|
|
|
};
|
|
|
|
evt_core_add_cat (&(ctx->evts), &init_socks5);
|
2019-02-12 19:33:12 +00:00
|
|
|
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_co));
|
|
|
|
evt_core_add_cat (&(ctx->evts), &(algo->on_udp_read));
|
|
|
|
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_read));
|
|
|
|
evt_core_add_cat (&(ctx->evts), &(algo->on_udp_write));
|
|
|
|
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_write));
|
|
|
|
printf("--- Categories created\n");
|
|
|
|
|
|
|
|
load_onion_services (ctx, onion_file, CLIENT_PORT_SIZE);
|
|
|
|
printf("--- Onion services loaded\n");
|
2019-02-14 14:40:05 +00:00
|
|
|
|
2019-02-15 14:45:56 +00:00
|
|
|
for (int i = 0; i < CLIENT_PORT_SIZE; i++) {
|
|
|
|
init_tcp_client(ctx, i);
|
|
|
|
}
|
2019-02-12 20:45:15 +00:00
|
|
|
printf("--- TCP Clients Connected\n");
|
2019-02-14 14:40:05 +00:00
|
|
|
|
2019-02-15 17:09:51 +00:00
|
|
|
g_ptr_array_foreach (ports, (void(*)(void*, void*))init_udp_socket, ctx);
|
|
|
|
printf("--- UDP Sockets are configured\n");
|
2019-02-12 21:07:47 +00:00
|
|
|
|
|
|
|
evt_core_loop(&(ctx->evts));
|
|
|
|
|
|
|
|
tor_os_free (&(ctx->tos));
|
2019-02-12 19:33:12 +00:00
|
|
|
}
|