WIP UDP Server implementation

This commit is contained in:
Quentin 2019-02-11 23:40:37 +01:00
parent a786b69856
commit f93853f974
9 changed files with 98 additions and 79 deletions

View file

@ -1,12 +1,6 @@
#include "algo_skel.h" #include "algo_skel.h"
#define NAIVE_BUFFER 128 #define NAIVE_BUFFER 128
struct naive_ctx {
char buffer[NAIVE_BUFFER];
int start;
int end;
};
void free_naive(void* app_ctx) { void free_naive(void* app_ctx) {
if (app_ctx != NULL) free(app_ctx); if (app_ctx != NULL) free(app_ctx);
} }
@ -34,37 +28,66 @@ co_error:
} }
void on_tcp_data(struct evt_core_ctx* ctx, struct evt_core_cat* cat, int fd) { void on_tcp_data(struct evt_core_ctx* ctx, struct evt_core_cat* cat, int fd) {
struct naive_ctx* app_ctx = (struct naive_ctx*) (cat->app_ctx); struct evt_core_cat* udp = g_hash_table_lookup (ctx->catlist, "udp-data");
if (udp == NULL || udp->socklist->len < 1) goto co_error;
int udp_fd = g_array_index(udp->socklist, int, 0);
app_ctx->end = read(fd, app_ctx->buffer, sizeof(char) * NAIVE_BUFFER); char buffer[NAIVE_BUFFER];
if (app_ctx->end == 0) return; int nread, nwrite;
if (app_ctx->end == -1 && errno == EAGAIN) return; nread = read(fd, buffer, sizeof(char) * NAIVE_BUFFER);
if (app_ctx->end == -1) goto co_error; if (nread == 0) return;
app_ctx->start = write(fd, app_ctx->buffer, app_ctx->end); //if (nread == -1 && errno == EAGAIN) return;
if (app_ctx->end == -1 && errno == EAGAIN) { if (nread == -1) goto co_error;
nwrite = write(udp_fd, buffer, nread);
if (nwrite == -1 && errno == EAGAIN) {
printf("Lost data EAGAIN\n"); printf("Lost data EAGAIN\n");
return; return;
} }
if (app_ctx->end == -1) goto co_error; if (nwrite == -1) goto co_error;
if (app_ctx->start != app_ctx->end) { if (nread != nwrite) {
printf("Lost data not everything has been written\n"); printf("Lost data not everything has been written\n");
return; return;
} }
return; return;
co_error: co_error:
perror("Failed to handle read write"); perror("Failed to handle read write for tcp-data");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
void on_udp_data(struct evt_core_ctx* ctx, struct evt_core_cat* cat, int fd) { void on_udp_data(struct evt_core_ctx* ctx, struct evt_core_cat* cat, int fd) {
struct evt_core_cat* tcp = g_hash_table_lookup (ctx->catlist, "tcp-data");
if (tcp == NULL || tcp->socklist->len < 1) goto co_error;
int tcp_fd = g_array_index(tcp->socklist, int, 0);
char buffer[NAIVE_BUFFER];
int nread, nwrite;
nread = read(fd, buffer, sizeof(char) * NAIVE_BUFFER);
if (nread == 0) return;
//if (nread == -1 && errno == EAGAIN) return;
if (nread == -1) goto co_error;
nwrite = write(tcp_fd, buffer, nread);
if (nwrite == -1 && errno == EAGAIN) {
printf("Lost data EAGAIN\n");
return;
}
if (nwrite == -1) goto co_error;
if (nread != nwrite) {
printf("Lost data not everything has been written\n");
return;
}
return;
co_error:
perror("Failed to handle read write for udp-data");
exit(EXIT_FAILURE);
} }
void algo_naive(struct algo_skel* as) { void algo_naive(struct algo_skel* as) {
as->on_tcp_data.name = "tcp-data"; as->on_tcp_data.name = "tcp-data";
as->on_tcp_data.flags = 0; as->on_tcp_data.flags = 0;
as->on_tcp_data.app_ctx = malloc(sizeof(struct naive_ctx)); as->on_tcp_data.app_ctx = NULL;
as->on_tcp_data.free_app_ctx = free_naive; as->on_tcp_data.free_app_ctx = free_naive;
as->on_tcp_data.cb = on_tcp_data; as->on_tcp_data.cb = on_tcp_data;
as->on_tcp_data.socklist = NULL; as->on_tcp_data.socklist = NULL;
@ -78,13 +101,13 @@ void algo_naive(struct algo_skel* as) {
as->on_udp_data.name = "udp-data"; as->on_udp_data.name = "udp-data";
as->on_udp_data.flags = 0; as->on_udp_data.flags = 0;
as->on_udp_data.app_ctx = malloc(sizeof(struct naive_ctx)); as->on_udp_data.app_ctx = NULL;
as->on_udp_data.free_app_ctx = free_naive; as->on_udp_data.free_app_ctx = free_naive;
as->on_udp_data.cb = on_udp_data; as->on_udp_data.cb = on_udp_data;
as->on_udp_data.socklist = NULL; as->on_udp_data.socklist = NULL;
if (as->on_tcp_data.app_ctx == NULL || as->on_udp_data.app_ctx == NULL) { /*if (as->on_tcp_data.app_ctx == NULL || as->on_udp_data.app_ctx == NULL) {
fprintf(stderr, "Failed to malloc naive_ctx\n"); fprintf(stderr, "Failed to malloc naive_ctx\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }*/
} }

View file

@ -0,0 +1 @@
void donar_client() {}

View file

@ -10,23 +10,38 @@
int main(int argc, char** argv) { int main(int argc, char** argv) {
printf("~ Donar ~\n"); printf("~ Donar ~\n");
int opt, is_server, is_client = 0; int opt, is_server, is_client;
while ((opt = getopt(argc, argv, "cs")) != -1) { char *host, *port, *onion_file;
host = NULL;
port = NULL;
onion_file = NULL;
is_server = 0;
is_client = 0;
while ((opt = getopt(argc, argv, "csh:p:o:")) != -1) {
switch(opt) { switch(opt) {
case 's': case 's':
is_server = 1; is_server = 1;
break; break;
case 'h':
host = strdup(optarg);
break;
case 'p':
port = strdup(optarg);
break;
case 'o':
onion_file = strdup(optarg);
break;
case 'c': case 'c':
is_client = 1; is_client = 1;
break; break;
default: default:
fprintf(stderr, "Usage: %s [-c | -s]\n", argv[0]); fprintf(stderr, "Usage: %s [-c -p <udp port> -o <onion service file> | -s -h <udp host> -p <udp port>]\n", argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (!(is_server ^ is_client)) { if (!(is_server ^ is_client)) {
fprintf(stderr, "2Usage: %s [-c | -s]\n", argv[0]); fprintf(stderr, "You need to choose between client and server\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -34,11 +49,19 @@ int main(int argc, char** argv) {
struct donar_server_ctx ctx; struct donar_server_ctx ctx;
struct algo_skel as; struct algo_skel as;
algo_naive (&as); algo_naive (&as);
donar_server(&ctx, &as); if (host == NULL || port == NULL) {
fprintf(stderr, "You need to set a host -h and a port -p\n");
exit(EXIT_FAILURE);
}
printf("params: %s:%s\n", host, port);
donar_server(&ctx, &as, host, port);
} else if (is_client) { } else if (is_client) {
donar_client(); donar_client();
} }
free(onion_file);
free(port);
free(host);
return 0; return 0;
/* /*
int sock; int sock;

View file

@ -39,62 +39,17 @@ socket_create_err:
fprintf(stderr, "Unable to create a TCP socket\n"); fprintf(stderr, "Unable to create a TCP socket\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/*
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; void donar_server(struct donar_server_ctx* ctx, struct algo_skel* algo, char* udp_host, char* udp_port) {
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, struct algo_skel* algo) {
evt_core_init (&(ctx->evts)); evt_core_init (&(ctx->evts));
evt_core_add_cat (&(ctx->evts), &(algo->on_udp_data)); evt_core_add_cat (&(ctx->evts), &(algo->on_udp_data));
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_data)); evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_data));
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_co)); evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_co));
int sock = create_udp_client (udp_host, udp_port);
evt_core_add_fd (&(ctx->evts), "udp-data", sock);
for (uint16_t i = 0; i < PORT_SIZE ; i++) { for (uint16_t i = 0; i < PORT_SIZE ; i++) {
ctx->ports[i] = 7500 + i; ctx->ports[i] = 7500 + i;
} }

View file

@ -18,4 +18,4 @@ struct donar_server_ctx {
uint16_t ports[PORT_SIZE]; uint16_t ports[PORT_SIZE];
}; };
void donar_server(struct donar_server_ctx* ctx, struct algo_skel* algo); void donar_server(struct donar_server_ctx* ctx, struct algo_skel* algo, char* udp_host, char* udp_port);

View file

@ -13,6 +13,7 @@ void free_char(void* c) {
void free_cat(void* vcat) { void free_cat(void* vcat) {
struct evt_core_cat* cat = (struct evt_core_cat*) vcat; struct evt_core_cat* cat = (struct evt_core_cat*) vcat;
cat->free_app_ctx(cat->app_ctx); cat->free_app_ctx(cat->app_ctx);
g_array_free(cat->socklist, TRUE);
free(cat->name); free(cat->name);
free(cat); free(cat);
} }
@ -29,6 +30,12 @@ void evt_core_init(struct evt_core_ctx* ctx) {
} }
void evt_core_add_cat(struct evt_core_ctx* ctx, struct evt_core_cat* cat) { void evt_core_add_cat(struct evt_core_ctx* ctx, struct evt_core_cat* cat) {
if (cat->socklist != NULL) {
fprintf(stderr, "cat->socklist must be null. What have you done?\n");
exit(EXIT_FAILURE);
}
cat->socklist = g_array_new (FALSE, FALSE, sizeof(int));
struct evt_core_cat* dyn = NULL; struct evt_core_cat* dyn = NULL;
dyn = malloc(sizeof(struct evt_core_cat)); dyn = malloc(sizeof(struct evt_core_cat));
if (dyn == NULL) { if (dyn == NULL) {
@ -72,6 +79,7 @@ void evt_core_add_fd(struct evt_core_ctx* ctx, char* name, int fd) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
g_array_append_val (cat->socklist, fd);
g_hash_table_insert(ctx->socklist, key, cat); g_hash_table_insert(ctx->socklist, key, cat);
add_fd_to_epoll(ctx->epollfd, fd); add_fd_to_epoll(ctx->epollfd, fd);
} }

View file

@ -22,7 +22,7 @@ struct evt_core_cat {
evt_core_cb cb; evt_core_cb cb;
char* name; char* name;
int flags; int flags;
GHashTable* socklist; GArray* socklist;
}; };
struct evt_core_ctx { struct evt_core_ctx {

View file

@ -3,20 +3,20 @@
// some code is inspired by https://github.com/millken/c-example/blob/master/epoll-example.c // some code is inspired by https://github.com/millken/c-example/blob/master/epoll-example.c
// (which seems to be copied from https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/epoll-example.c ) // (which seems to be copied from https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/epoll-example.c )
int create_tcp_client(char* host, char* service) { int create_ip_client(char* host, char* service, int type) {
int err, sock; int err, sock;
struct addrinfo conf; struct addrinfo conf;
struct addrinfo *result, *cursor; struct addrinfo *result, *cursor;
memset(&conf, 0, sizeof(struct addrinfo)); memset(&conf, 0, sizeof(struct addrinfo));
conf.ai_family = AF_UNSPEC; conf.ai_family = AF_UNSPEC;
conf.ai_socktype = SOCK_STREAM; conf.ai_socktype = type;
conf.ai_flags = 0; conf.ai_flags = 0;
conf.ai_protocol = 0; conf.ai_protocol = 0;
err = getaddrinfo(host, service, &conf, &result); err = getaddrinfo(host, service, &conf, &result);
if (err != 0) { if (err != 0) {
fprintf(stderr, "Error with getaddrinfo()\n"); fprintf(stderr, "Error with getaddrinfo() for %s:%s\n",host,service);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -37,6 +37,14 @@ int create_tcp_client(char* host, char* service) {
return sock; return sock;
} }
int create_tcp_client(char* host, char* service) {
return create_ip_client (host, service, SOCK_STREAM);
}
int create_udp_client(char* host, char* service) {
return create_ip_client (host, service, SOCK_DGRAM);
}
int create_tcp_server(char* service) { int create_tcp_server(char* service) {
int err, sock; int err, sock;
struct addrinfo conf; struct addrinfo conf;

View file

@ -9,6 +9,7 @@
#include <sys/epoll.h> #include <sys/epoll.h>
int create_tcp_client(char* host, char* service); int create_tcp_client(char* host, char* service);
int create_udp_client(char* host, char* service);
int create_tcp_server(char* service); int create_tcp_server(char* service);
int make_socket_non_blocking(int fd); int make_socket_non_blocking(int fd);
void add_fd_to_epoll(int epollfd, int fd); void add_fd_to_epoll(int epollfd, int fd);