diff --git a/CMakeLists.txt b/CMakeLists.txt index 25996eb..daf4ff9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ list(APPEND CSOURCES add_executable(donar ${CSOURCES} src/donar.c) add_executable(measlat ${CSOURCES} src/meas_lat.c) +add_executable(udpecho ${CSOURCES} src/udp_echo.c) find_package(PkgConfig REQUIRED) pkg_search_module(GLIB REQUIRED glib-2.0) @@ -41,6 +42,9 @@ target_link_libraries(donar ${GLIB_LDFLAGS}) target_include_directories(measlat PRIVATE ${GLIB_INCLUDE_DIRS}) target_link_libraries(measlat ${GLIB_LDFLAGS}) -install(TARGETS donar measlat +target_include_directories(udpecho PRIVATE ${GLIB_INCLUDE_DIRS}) +target_link_libraries(udpecho ${GLIB_LDFLAGS}) + +install(TARGETS donar measlat udpecho RUNTIME DESTINATION bin LIBRARY DESTINATION lib) \ No newline at end of file diff --git a/src/donar_client.c b/src/donar_client.c index 088d124..1bcb021 100644 --- a/src/donar_client.c +++ b/src/donar_client.c @@ -109,6 +109,7 @@ on_socks5_err: evt_core_rm_fd (ctx, fdinfo->fd); sleep(2); init_tcp_client (app_ctx, pos); + return 1; } void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, diff --git a/src/donar_init.c b/src/donar_init.c index 8a7c79b..d6dce07 100644 --- a/src/donar_init.c +++ b/src/donar_init.c @@ -26,7 +26,7 @@ void init_udp_remote(char* port, struct evt_core_ctx* evts) { fdinfo.other = udp_t; // 2. Duplicate sockets - sock1 = create_udp_server (port); + sock1 = create_udp_server ("127.13.3.7", port); if (sock1 < 0) goto socket_failed; sock2 = dup(sock1); if (sock2 < 0) goto socket_failed; diff --git a/src/donar_server.c b/src/donar_server.c index 7ac07b9..6f93804 100644 --- a/src/donar_server.c +++ b/src/donar_server.c @@ -33,7 +33,7 @@ void init_tcp_servers(struct donar_server_ctx* ctx) { int err, sock = 0; for (int i = 0; i < PORT_SIZE; i++) { sprintf (buffer, "%d", ctx->ports[i]); - sock = create_tcp_server (buffer); + sock = create_tcp_server ("127.13.3.7", buffer); if (sock < 0) goto socket_create_err; err = listen(sock, SOMAXCONN); if (err != 0) goto socket_create_err; diff --git a/src/net_tools.c b/src/net_tools.c index eb96f06..dbee61d 100644 --- a/src/net_tools.c +++ b/src/net_tools.c @@ -51,7 +51,7 @@ int create_udp_client(char* host, char* service) { return create_ip_client (host, service, SOCK_DGRAM); } -int create_ip_server(char* service, int type) { +int create_ip_server(char* host, char* service, int type) { int err, sock, enable; struct addrinfo conf; struct addrinfo *result, *cursor; @@ -63,7 +63,7 @@ int create_ip_server(char* service, int type) { conf.ai_protocol = 0; enable = 1; - err = getaddrinfo("127.13.3.7", service, &conf, &result); + err = getaddrinfo(host, service, &conf, &result); if (err != 0) { fprintf(stderr, "Error with getaddrinfo()\n"); exit(EXIT_FAILURE); @@ -92,12 +92,12 @@ int create_ip_server(char* service, int type) { return sock; } -int create_tcp_server(char* service) { - return create_ip_server (service, SOCK_STREAM); +int create_tcp_server(char* host, char* service) { + return create_ip_server (host, service, SOCK_STREAM); } -int create_udp_server(char* service) { - return create_ip_server (service, SOCK_DGRAM); +int create_udp_server(char* host, char* service) { + return create_ip_server (host, service, SOCK_DGRAM); } /* diff --git a/src/net_tools.h b/src/net_tools.h index b0105b8..9756c12 100644 --- a/src/net_tools.h +++ b/src/net_tools.h @@ -10,8 +10,8 @@ int create_tcp_client(char* host, char* service); int create_udp_client(char* host, char* service); -int create_tcp_server(char* service); -int create_udp_server(char* service); +int create_tcp_server(char* host, char* service); +int create_udp_server(char* host, char* service); int make_socket_non_blocking(int fd); void add_fd_to_epoll(int epollfd, int fd, uint32_t flags); int read_entity(int fd, void* entity, int size); diff --git a/src/udp_echo.c b/src/udp_echo.c new file mode 100644 index 0000000..beb3c2f --- /dev/null +++ b/src/udp_echo.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include "evt_core.h" +#include "net_tools.h" + +int on_udp(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { + char buffer[1500]; + ssize_t nread, nwritten; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + + nread = recvfrom(fdinfo->fd, buffer, sizeof(buffer), MSG_TRUNC, (struct sockaddr*)&addr, &addrlen); + if (nread == -1 && errno == EAGAIN) return 1; // Read done + if (nread <= 0 || nread > sizeof(buffer)) { + fprintf(stderr, "Message is either truncated or an error occured. nread=%ld\n", nread); + perror("read errno"); + exit(EXIT_FAILURE); + } + + nwritten = sendto(fdinfo->fd, buffer, nread, 0, (struct sockaddr*)&addr, addrlen); + // @FIXME don't support EAGAIN on write. Could be intended, you don't think so? + if (nwritten != nread) { + fprintf(stderr, "Didn't write the same number of bytes as read. nread=%ld, nwritten=%ld\n", nread, nwritten); + perror("write errno"); + exit(EXIT_FAILURE); + } + return 0; +} + +int main(int argc, char** argv) { + printf("~ udpecho ~\n"); + + int opt, udp_sock, verbose = 0; + char *port = NULL; + struct evt_core_ctx evts = {0}; + + // 1. Parse parameters + while ((opt = getopt(argc, argv, "p:v")) != -1) { + switch(opt) { + case 'v': + verbose = 1; + break; + case 'p': + port = optarg; + break; + default: + goto usage; + } + } + + // 2. Register category + struct evt_core_cat udp_read = { + .app_ctx = NULL, + .free_app_ctx = NULL, + .cb = on_udp, + .err_cb = NULL, + .name = "udp-read", + .flags = EPOLLIN | EPOLLET, + .socklist = NULL + }; + evt_core_init(&evts); + evt_core_add_cat(&evts, &udp_read); + + // 3. Register UDP socket + udp_sock = create_udp_server ("127.0.0.1", port); + + char url[1024]; + struct evt_core_cat cat = {0}; + struct evt_core_fdinfo fdinfo = {0}; + fdinfo.cat = &cat; + fdinfo.url = url; + + fdinfo.fd = udp_sock; + sprintf(url, "udp:rw:127.0.0.1:%s", port); + fdinfo.cat->name = "udp-read"; + evt_core_add_fd(&evts, &fdinfo); + + // 4. Start main loop + evt_core_loop (&evts); + + return 0; +usage: + fprintf(stderr, "Usage: %s -p [-v]\n", argv[0]); +} diff --git a/udp-echo.py b/udp-echo.py deleted file mode 100755 index 08aa9d9..0000000 --- a/udp-echo.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 -""" -A simple UDP echo server. -""" -import argparse -import itertools -import logging -import socket - -logger = logging.getLogger(__name__) - -# the buffer for receiving incoming messages -BUFFER_SIZE = 4096 - -def receive_next(sock): - "Repeatedly tries receiving on the given socket until some data comes in." - logger.debug("Waiting to receive data...") - while True: - try: - return sock.recvfrom(BUFFER_SIZE) - except socket.timeout: - logger.debug("No data received yet: retrying.") - pass - -def receive_and_send_one(sock): - "Waits for a single datagram over the socket and echoes it back." - input_data, addr = receive_next(sock) - print(input_data) - #message = input_data.decode() - #logger.info("Received message from %s: %s (%s bytes).", addr, message, len(input_data)) - output_len = sock.sendto(input_data, addr) - #logger.info("Echoed message back to %s: %s (%s bytes).", addr, message, output_len) - -def start(args): - "Runs the server." - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.settimeout(5) # seconds - sock.bind((args.host, args.port)) - logger.info("Listening on %s:%s.", args.host, args.port) - try: - for i in itertools.count(1): - receive_and_send_one(sock) - finally: - logger.info("Shutting down.") - sock.close() - -if __name__ == "__main__": - parser = argparse.ArgumentParser(__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument('--host', help='The host that the server socket should bind to.', default="0.0.0.0") - parser.add_argument('--port', help='The port that the server socket should bind to.', type=int, default=123) - parser.add_argument('--verbose', '-v', help="Increases the logging verbosity level.", action='count') - args = parser.parse_args() - logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO, - format='%(asctime)s %(levelname)s %(message)s') - start(args)