WIP UDP Server implementation
This commit is contained in:
parent
a786b69856
commit
f93853f974
9 changed files with 98 additions and 79 deletions
|
@ -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);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
void donar_client() {}
|
|
@ -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;
|
||||||
|
|
|
@ -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, ¤t_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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue