#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)); } void init_tcp_client(struct donar_client_ctx* ctx, int i) { ctx->ports[i] = 7500 + i; int sock1, err; while (1) { sock1 = create_tcp_client("127.0.0.1", "9050"); if (sock1 < 0) goto failed_socks5; ctx->client_sock[i].fd = sock1; ctx->client_sock[i].state = SOCKS5_STATE_NEW; evt_core_add_fd (&(ctx->evts), "configure-socks5", sock1); //@FIXME: We suppose that we will be able to do the whole write at once which is wrong too err = socks5_handshake_syn(sock1); if (err) goto failed_socks5; break; failed_socks5: fprintf(stderr, "Failed connection for socket %d/%d. Sleeping 2 seconds...\n",i+1, CLIENT_PORT_SIZE); close(sock1); sleep(2); } } void configure_tcp_clients(struct evt_core_ctx* ctx, struct evt_core_cat* cat, int fd) { int err, pos; struct donar_client_ctx* app_ctx = (struct donar_client_ctx*) cat->app_ctx; pos = -1; for (int i = 0; i < CLIENT_PORT_SIZE; i++) { if (app_ctx->client_sock[i].fd == fd) { 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 err = socks5_handshake_ack (fd); 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 err = socks5_connect_dns(fd, target_host, app_ctx->ports[pos]); 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 err = socks5_reply (fd); if (err < 0) goto on_socks5_err; app_ctx->client_sock[pos].state = SOCKS5_STATE_RDY; int sock1, sock2; sock1 = dup(fd); sock2 = dup(fd); if (sock1 < 0 || sock2 < 0) goto on_socks5_err; void* fdcat = evt_core_rm_fd (ctx, fd); if (fdcat == NULL) goto on_socks5_err; evt_core_add_fd (ctx, "tcp-write", sock1); evt_core_add_fd (ctx, "tcp-read", sock2); 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; evt_core_rm_fd (ctx, fd); init_tcp_client (app_ctx, pos); } void init_udp_socket(char* port, struct donar_client_ctx* ctx) { int sock1, sock2; sock1 = create_udp_client ("127.0.0.1", port); if (sock1 < 0) goto socket_failed; sock2 = dup(sock1); if (sock2 < 0) goto socket_failed; evt_core_add_fd (&(ctx->evts), "udp-read", sock1); evt_core_add_fd (&(ctx->evts), "udp-write", sock2); return; socket_failed: fprintf(stderr, "UDP socket init failed\n"); exit(EXIT_FAILURE); } void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, char* onion_file, GPtrArray* ports) { evt_core_init (&(ctx->evts)); 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); 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"); for (int i = 0; i < CLIENT_PORT_SIZE; i++) { init_tcp_client(ctx, i); } printf("--- TCP Clients Connected\n"); g_ptr_array_foreach (ports, (void(*)(void*, void*))init_udp_socket, ctx); printf("--- UDP Sockets are configured\n"); evt_core_loop(&(ctx->evts)); tor_os_free (&(ctx->tos)); }