tor_multipath_voip/src/donar_server.c

152 lines
4.6 KiB
C
Raw Normal View History

2019-02-11 09:23:38 +00:00
#include "donar_server.h"
2019-02-11 15:23:20 +00:00
void create_onion_services(struct tor_os_str* tos, struct tor_ctl* tctl, uint16_t* ports, int ports_count) {
2019-02-11 09:23:38 +00:00
tor_os_create (tos, "onion_services.pub", "onion_services.txt", ports_count);
tor_os_read (tos);
int err = 0;
err = tor_ctl_connect (tctl, "127.0.0.1", "9051");
if (err < 0) {
fprintf(stderr, "Unable to open Tor Socket\n");
exit(EXIT_FAILURE);
}
err = tor_ctl_add_onion (tctl, tos, ports);
if (err != 0) {
fprintf(stderr, "Unable to create Onion Services (error: %d)\n", err);
exit(EXIT_FAILURE);
}
}
void destroy_resources(struct tor_os_str* tos, struct tor_ctl* tctl) {
tor_ctl_close (tctl);
tor_os_free (tos);
}
2019-02-11 15:23:20 +00:00
void init_tcp_servers(struct donar_server_ctx* ctx) {
char buffer[6];
int err = 0;
for (int i = 0; i < ctx->connection_count; i++) {
sprintf (buffer, "%d", ctx->ports[i]);
ctx->tcp_socks[i] = create_tcp_server (buffer);
if (ctx->tcp_socks[i] < 0) goto socket_create_err;
// Might be needed only with EPOLLET - might not be needed at all
//err = make_socket_non_blocking (ctx->tcp_socks[i]);
//if (err != 0) goto socket_create_err;
err = listen(ctx->tcp_socks[i], SOMAXCONN);
if (err != 0) goto socket_create_err;
}
return;
2019-02-11 09:23:38 +00:00
2019-02-11 15:23:20 +00:00
socket_create_err:
fprintf(stderr, "Unable to create a TCP socket\n");
exit(EXIT_FAILURE);
}
int is_listening_socket(struct donar_server_ctx* ctx, int sock) {
int i;
for (i = 0; i < ctx->connection_count && ctx->is_server; i++) {
if (sock == ctx->tcp_socks[i]) return 1;
}
return 0;
}
void handle_new_tcp_client_connection(struct donar_server_ctx* ctx, struct epoll_event* evt) {
int conn_sock, err;
struct sockaddr in_addr;
socklen_t in_len;
struct epoll_event current_event;
in_len = sizeof(in_addr);
conn_sock = accept(evt->data.fd, &in_addr, &in_len);
if (conn_sock == -1) goto co_error;
err = make_socket_non_blocking (conn_sock);
if (err == -1) goto co_error;
current_event.events = EPOLLIN | EPOLLET;
current_event.data.fd = conn_sock;
if (epoll_ctl(ctx->epollfd, EPOLL_CTL_ADD, conn_sock, &current_event) == -1)
goto co_error;
return;
co_error:
perror("Failed to handle new connection");
exit(EXIT_FAILURE);
}
void handle_new_tcp_client_rw(struct donar_server_ctx* ctx, struct epoll_event* evt) {
char buffer[128];
int nread, nwrite;
while(1) {
nread = read(evt->data.fd, buffer, sizeof(buffer));
if (nread == 0) break;
if (nread == -1 && errno == EAGAIN) break;
if (nread == -1) goto co_error;
nwrite = write(evt->data.fd, buffer, nread);
if (nwrite == -1 && errno == EAGAIN) {
printf("Lost data EAGAIN\n");
break;
}
if (nwrite == -1) goto co_error;
if (nwrite != nread) {
printf("Lost data not everything has been written\n");
break;
}
}
return;
co_error:
perror("Failed to handle read write");
exit(EXIT_FAILURE);
}
void donar_server(struct donar_server_ctx* ctx) {
ctx->is_server = 1;
ctx->connection_count = PORT_SIZE;
for (uint16_t i = 0; i < ctx->connection_count ; i++) {
ctx->ports[i] = 7500 + i;
}
create_onion_services (&(ctx->tos), &(ctx->tctl), ctx->ports, ctx->connection_count);
printf("--- Onion services created\n");
init_tcp_servers(ctx);
ctx->epollfd = epoll_create1(0);
if (ctx->epollfd == -1) {
perror("Failed to create epoll file descriptor epoll_create1");
exit(EXIT_FAILURE);
}
struct epoll_event current_event, events[MAX_EVENTS];
for (int i = 0; i < ctx->connection_count; i++) {
current_event.events = EPOLLIN;
current_event.data.fd = ctx->tcp_socks[i];
if (epoll_ctl (ctx->epollfd, EPOLL_CTL_ADD, ctx->tcp_socks[i], &current_event) == -1) {
perror("Failed to add a file descriptor to epoll with epoll_ctl");
exit(EXIT_FAILURE);
}
}
2019-02-11 16:04:12 +00:00
printf("--- Start main loop\n");
2019-02-11 15:23:20 +00:00
int num_fd, n = 0;
while(1) {
num_fd = epoll_wait(ctx->epollfd, events, MAX_EVENTS, -1);
if (num_fd == -1) {
perror("Failed to epoll_wait");
exit(EXIT_FAILURE);
}
2019-02-11 16:04:12 +00:00
2019-02-11 15:23:20 +00:00
for (n = 0 ; n < num_fd; n++) {
if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP) || (!(events[n].events & EPOLLIN))) {
/* An error has occured on this fd, or the socket is not
ready for reading (why were we notified then?) */
fprintf (stderr, "epoll error\n");
close (events[n].data.fd);
continue;
}
else if (is_listening_socket (ctx, events[n].data.fd)) handle_new_tcp_client_connection (ctx, &(events[n]));
else handle_new_tcp_client_rw(ctx, &(events[n]));
}
}
destroy_resources (&(ctx->tos), &(ctx->tctl));
2019-02-11 09:23:38 +00:00
}