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"
|
||||
#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);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
void donar_client() {}
|
|
@ -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;
|
||||
|
|
|
@ -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, ¤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) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ struct evt_core_cat {
|
|||
evt_core_cb cb;
|
||||
char* name;
|
||||
int flags;
|
||||
GHashTable* socklist;
|
||||
GArray* socklist;
|
||||
};
|
||||
|
||||
struct evt_core_ctx {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue