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"
#define NAIVE_BUFFER 128
struct naive_ctx {
char buffer[NAIVE_BUFFER];
int start;
int end;
};
void free_naive(void* 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) {
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);
if (app_ctx->end == 0) return;
if (app_ctx->end == -1 && errno == EAGAIN) return;
if (app_ctx->end == -1) goto co_error;
app_ctx->start = write(fd, app_ctx->buffer, app_ctx->end);
if (app_ctx->end == -1 && errno == EAGAIN) {
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(udp_fd, buffer, nread);
if (nwrite == -1 && errno == EAGAIN) {
printf("Lost data EAGAIN\n");
return;
}
if (app_ctx->end == -1) goto co_error;
if (app_ctx->start != app_ctx->end) {
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");
perror("Failed to handle read write for tcp-data");
exit(EXIT_FAILURE);
}
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) {
as->on_tcp_data.name = "tcp-data";
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.cb = on_tcp_data;
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.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.cb = on_udp_data;
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");
exit(EXIT_FAILURE);
}
}*/
}

View file

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

View file

@ -10,23 +10,38 @@
int main(int argc, char** argv) {
printf("~ Donar ~\n");
int opt, is_server, is_client = 0;
while ((opt = getopt(argc, argv, "cs")) != -1) {
int opt, is_server, is_client;
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) {
case 's':
is_server = 1;
break;
case 'h':
host = strdup(optarg);
break;
case 'p':
port = strdup(optarg);
break;
case 'o':
onion_file = strdup(optarg);
break;
case 'c':
is_client = 1;
break;
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);
}
}
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);
}
@ -34,11 +49,19 @@ int main(int argc, char** argv) {
struct donar_server_ctx ctx;
struct algo_skel 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) {
donar_client();
}
free(onion_file);
free(port);
free(host);
return 0;
/*
int sock;

View file

@ -39,62 +39,17 @@ socket_create_err:
fprintf(stderr, "Unable to create a TCP socket\n");
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;
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) {
void donar_server(struct donar_server_ctx* ctx, struct algo_skel* algo, char* udp_host, char* udp_port) {
evt_core_init (&(ctx->evts));
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_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++) {
ctx->ports[i] = 7500 + i;
}

View file

@ -18,4 +18,4 @@ struct donar_server_ctx {
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) {
struct evt_core_cat* cat = (struct evt_core_cat*) vcat;
cat->free_app_ctx(cat->app_ctx);
g_array_free(cat->socklist, TRUE);
free(cat->name);
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) {
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;
dyn = malloc(sizeof(struct evt_core_cat));
if (dyn == NULL) {
@ -72,6 +79,7 @@ void evt_core_add_fd(struct evt_core_ctx* ctx, char* name, int fd) {
exit(EXIT_FAILURE);
}
g_array_append_val (cat->socklist, fd);
g_hash_table_insert(ctx->socklist, key, cat);
add_fd_to_epoll(ctx->epollfd, fd);
}

View file

@ -22,7 +22,7 @@ struct evt_core_cat {
evt_core_cb cb;
char* name;
int flags;
GHashTable* socklist;
GArray* socklist;
};
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
// (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;
struct addrinfo conf;
struct addrinfo *result, *cursor;
memset(&conf, 0, sizeof(struct addrinfo));
conf.ai_family = AF_UNSPEC;
conf.ai_socktype = SOCK_STREAM;
conf.ai_socktype = type;
conf.ai_flags = 0;
conf.ai_protocol = 0;
err = getaddrinfo(host, service, &conf, &result);
if (err != 0) {
fprintf(stderr, "Error with getaddrinfo()\n");
fprintf(stderr, "Error with getaddrinfo() for %s:%s\n",host,service);
exit(EXIT_FAILURE);
}
@ -37,6 +37,14 @@ int create_tcp_client(char* host, char* service) {
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 err, sock;
struct addrinfo conf;

View file

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