diff options
author | LAN-TW <lantw44@gmail.com> | 2013-12-22 03:07:39 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-12-22 03:07:39 +0800 |
commit | 0651f1f727b6f33e9b8655aaf90ed9250eea41ae (patch) | |
tree | 1ac24224302337978d422af9b7f6135313016fb5 | |
parent | 3c7cd856722378cb0ed0cba0f4a33eaa05a8dc0d (diff) | |
download | cn2013-0651f1f727b6f33e9b8655aaf90ed9250eea41ae.tar.gz cn2013-0651f1f727b6f33e9b8655aaf90ed9250eea41ae.tar.zst cn2013-0651f1f727b6f33e9b8655aaf90ed9250eea41ae.zip |
HW2: 修正各種錯誤,並完成基本的連線操作
-rw-r--r-- | hw2/Makefile.am | 5 | ||||
-rw-r--r-- | hw2/agent-main.c | 22 | ||||
-rw-r--r-- | hw2/trans-loop.c | 86 | ||||
-rw-r--r-- | hw2/trans-loop.h | 9 | ||||
-rw-r--r-- | hw2/trans-main.c | 88 | ||||
-rw-r--r-- | hw2/ump-app.c | 56 | ||||
-rw-r--r-- | hw2/ump-app.h | 37 | ||||
-rw-r--r-- | hw2/ump-common.h | 4 | ||||
-rw-r--r-- | hw2/ump-gai.c | 52 | ||||
-rw-r--r-- | hw2/ump-gai.h | 3 | ||||
-rw-r--r-- | hw2/ump-pkt.c | 24 | ||||
-rw-r--r-- | hw2/ump-pkt.h | 9 | ||||
-rw-r--r-- | hw2/ump-sched.c | 286 | ||||
-rw-r--r-- | hw2/ump-sched.h | 61 |
14 files changed, 673 insertions, 69 deletions
diff --git a/hw2/Makefile.am b/hw2/Makefile.am index ff08425..c719a3f 100644 --- a/hw2/Makefile.am +++ b/hw2/Makefile.am @@ -12,9 +12,10 @@ liblbs_a_SOURCES = \ libump_a_SOURCES = \ ump-common.h \ - ump-app.h ump-app.c \ + ump-app.c ump-app.h \ ump-gai.c ump-gai.h \ ump-pkt.c ump-pkt.h \ + ump-sched.c ump-sched.h \ $(NULL) ump_agent_SOURCES = \ @@ -23,5 +24,7 @@ ump_agent_SOURCES = \ ump_agent_LDADD = $(top_builddir)/liblbs.a $(top_builddir)/libump.a ump_trans_SOURCES = \ + trans-main.c \ + trans-loop.c trans-loop.h \ $(NULL) ump_trans_LDADD = $(top_builddir)/liblbs.a $(top_builddir)/libump.a diff --git a/hw2/agent-main.c b/hw2/agent-main.c index b113537..81fce40 100644 --- a/hw2/agent-main.c +++ b/hw2/agent-main.c @@ -62,14 +62,8 @@ int main (int argc, char* argv[]) { lbs_logger_init (agent_log, LBS_LOGGER_FILE_STDOUT, LBS_LOGGER_COLOR_AUTO, argv[0], "UMP_AGENT_FILE", "UMP_AGENT_COLOR"); - struct addrinfo gai_hints; - memset (&gai_hints, 0, sizeof (gai_hints)); - gai_hints.ai_family = AF_UNSPEC; - gai_hints.ai_socktype = SOCK_DGRAM; - gai_hints.ai_flags = AI_ADDRCONFIG; - int gai_errno; - int udp_fd = ump_gai (agent_log, argv[1], argv[2], &gai_hints, &gai_errno); + int udp_fd = ump_gai (agent_log, argv[1], argv[2], true, NULL, NULL, &gai_errno); if (udp_fd < 0) { if (gai_errno) { fprintf (stderr, "%s: %s\n", argv[0], gai_strerror (gai_errno)); @@ -106,6 +100,12 @@ int main (int argc, char* argv[]) { } ssize_t app_len = pkt_len - ump_pkt_get_data_offset (pkt); + pkt->app_data_len = app_len; + + if (!ump_pkt_verify_checksum (pkt)) { + lbs_logger_string (agent_log, "invalid checksum (dropped)"); + continue; + } UmpApp* app_data = UMP_APP (ump_pkt_get_app_data (pkt)); if (!ump_app_check_size (app_data, app_len)) { @@ -131,19 +131,21 @@ int main (int argc, char* argv[]) { } #endif - if (ump_app_fill_src_with_sockaddr (app_data, SOCKADDR (src)) < 0) { + if (ump_app_fill_src_with_sockaddr (app_data, pkt, SOCKADDR (src)) < 0) { lbs_logger_string (agent_log, "incompatible address (dropped)"); continue; } + ump_pkt_fill_checksum (pkt); struct sockaddr_storage dest_struct; struct sockaddr_storage* dest = &dest_struct; socklen_t dest_len; memset (&dest_struct, 0, sizeof (dest_struct)); - ump_app_fill_sockaddr_with_dest (app_data, SOCKADDR (dest), &dest_len); + ump_app_fill_sockaddr_with_dest ( + app_data, pkt, SOCKADDR (dest), &dest_len); do_sendto: - if (sendto (udp_fd, &pkt, pkt_len, 0, SOCKADDR (dest), dest_len) < 0) { + if (sendto (udp_fd, pkt, pkt_len, 0, SOCKADDR (dest), dest_len) < 0) { if (errno == EAGAIN || errno == EINTR) { goto do_sendto; } diff --git a/hw2/trans-loop.c b/hw2/trans-loop.c new file mode 100644 index 0000000..1d01d25 --- /dev/null +++ b/hw2/trans-loop.c @@ -0,0 +1,86 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "l4logger.h" +#include "ump-sched.h" +#include "trans-loop.h" + +int ump_trans_sender (LbsLogger* lbs_log, + char** dest, char** files, char** agents) { + + int i; + int files_count; + int agents_count; + + lbs_logger_string (lbs_log, "Dump sender arguments:"); + lbs_logger_format (lbs_log, "dest_addr = %s", dest[0]); + lbs_logger_format (lbs_log, "dest_port = %s", dest[1]); + + for (i = 0; strcmp (files[i], "--"); i++) { + lbs_logger_format (lbs_log, "files[%d] = %s", i, files[i]); + } + files_count = i; + lbs_logger_format (lbs_log, "files_count = %d", files_count); + + for (i = 0; agents[i] != NULL; i += 2) { + lbs_logger_format (lbs_log, "agents[%d].addr = %s", i, agents[i]); + lbs_logger_format (lbs_log, "agents[%d].port = %s", i, agents[i + 1]); + } + agents_count = i / 2; + lbs_logger_format (lbs_log, "agents_count = %d", agents_count); + + UmpSched* sched = ump_sched_new (lbs_log, UMP_SCHED_TYPE_SENDER, + agents, agents_count); + if (sched == NULL) { + lbs_logger_string (lbs_log, "Cannot construct schedular (terminated)"); + return 2; + } + + for (i = 0; i < files_count; i++) { + lbs_logger_format (lbs_log, "==> File %d: %s", i, files[i]); + if (ump_sched_connect (sched, dest) < 0) { + lbs_logger_string (lbs_log, "Connot connect to remote host"); + continue; + } + + lbs_logger_string (lbs_log, "--> Connected to remote host!"); + + lbs_logger_string (lbs_log, "--> Shutting down connection ..."); + ump_sched_shutdown (sched); + } + + ump_sched_free (sched); + return 0; +} + +int ump_trans_receiver (LbsLogger* lbs_log, char** bind_ptr) { + + lbs_logger_string (lbs_log, "Dump receiver arguments:"); + lbs_logger_format (lbs_log, "bind_addr = %s", bind_ptr[0]); + lbs_logger_format (lbs_log, "bind_port = %s", bind_ptr[1]); + + UmpSched* sched = ump_sched_new (lbs_log, UMP_SCHED_TYPE_RECEIVER, NULL, 0); + if (sched == NULL) { + lbs_logger_string (lbs_log, "Cannot construct schedular (terminated)"); + return 2; + } + + if (ump_sched_listen (sched, bind_ptr) < 0) { + lbs_logger_format (lbs_log, "Cannot listen on host (terminated)"); + ump_sched_free (sched); + return 3; + } + + while (true) { + if (ump_sched_accept (sched) < 0) { + lbs_logger_string (lbs_log, "==> Bad connection"); + continue; + } + + lbs_logger_string (lbs_log, "==> New connection accepted"); + } + + ump_sched_free (sched); + return 0; +} diff --git a/hw2/trans-loop.h b/hw2/trans-loop.h new file mode 100644 index 0000000..a8d70a5 --- /dev/null +++ b/hw2/trans-loop.h @@ -0,0 +1,9 @@ +#ifndef TRANS_LOOP_H +#define TRANS_LOOP_H + +#include "l4logger.h" + +int ump_trans_sender (LbsLogger* log, char** dest, char** files, char** agents); +int ump_trans_receiver (LbsLogger* log, char** bind_ptr); + +#endif /* TRANS_LOOP_H */ diff --git a/hw2/trans-main.c b/hw2/trans-main.c new file mode 100644 index 0000000..93cf431 --- /dev/null +++ b/hw2/trans-main.c @@ -0,0 +1,88 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "l4logger.h" +#include "trans-loop.h" + +#include <locale.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +static void show_usage (const char* name) { + fprintf (stderr, + "\n <<<Sender Usage>>>\n" + "%s dest_addr dest_port filenames ... -- agent_addr agent_port ...\n" + "\n <<<Receiver Usage>>>\n" + "%s bind_addr bind_port\n" + , name, name); + exit (1); +} + +static int find_separator (char* argv[]) { + for (int i = 1; argv[i] != NULL; i++) { + if (strcmp (argv[i], "--") == 0) { + return i; + } + } + return -1; +} + +static void ignore_alarm (int signo) { + return; +} + +int main (int argc, char* argv[]) { + setlocale (LC_ALL, ""); + tzset (); + srand (time (NULL)); + + if (argc < 3) { + show_usage (argv[0]); + return 1; + } + + struct sigaction sa = { + .sa_handler = ignore_alarm, + .sa_flags = 0 + }; + sigemptyset (&sa.sa_mask); + sigaction (SIGALRM, &sa, NULL); + + LbsLogger trans_log_struct; + LbsLogger* trans_log = &trans_log_struct; + lbs_logger_init (trans_log, LBS_LOGGER_FILE_STDOUT, LBS_LOGGER_COLOR_AUTO, + argv[0], "UMP_TRANS_FILE", "UMP_TRANS_COLOR"); + + int sep, rval; + if ((sep = find_separator (argv)) < 0) { + if (argc > 3) { + fprintf (stderr, "%s: Too many argument: %s\n", argv[0], argv[3]); + show_usage (argv[0]); + } + + rval = ump_trans_receiver (trans_log, &argv[1]); + } else { + if (sep <= 3) { + fprintf (stderr, "%s: No filename!\n", argv[0]); + show_usage (argv[0]); + } + if (sep + 1 == argc) { + fprintf (stderr, "%s: No agent!\n", argv[0]); + show_usage (argv[0]); + } + if ((argc - 1 - sep) % 2) { + fprintf (stderr, "%s: Agents port is missing", argv[0]); + show_usage (argv[0]); + } + + rval = ump_trans_sender (trans_log, &argv[1], &argv[3], &argv[sep + 1]); + } + + lbs_logger_destroy (trans_log); + + return rval; +} diff --git a/hw2/ump-app.c b/hw2/ump-app.c index 943fea0..8e2b71d 100644 --- a/hw2/ump-app.c +++ b/hw2/ump-app.c @@ -9,29 +9,71 @@ #include <netinet/in.h> int ump_app_fill_src_with_sockaddr ( - UmpApp* app_data, const struct sockaddr* addr) { + UmpApp* app_data, UmpPkt* pkt, const struct sockaddr* addr) { if (ump_app_get_is_ipv6 (app_data)) { if (SOCKADDR_IN6 (addr)->sin6_family != AF_INET6) { return -1; } - ump_app_set_src_port (app_data, SOCKADDR_IN6 (addr)->sin6_port); + ump_pkt_set_src_port (pkt, SOCKADDR_IN6 (addr)->sin6_port); ump_app_set_src_ip_addr (app_data, SOCKADDR_IN6 (addr)->sin6_addr.s6_addr); } else { if (SOCKADDR_IN (addr)->sin_family != AF_INET) { return -1; } - ump_app_set_src_port (app_data, SOCKADDR_IN (addr)->sin_port); + ump_pkt_set_src_port (pkt, SOCKADDR_IN (addr)->sin_port); ump_app_set_src_ip_addr (app_data, &(SOCKADDR_IN (addr)->sin_addr.s_addr)); } return 0; } +int ump_app_fill_dest_with_sockaddr ( + UmpApp* app_data, UmpPkt* pkt, const struct sockaddr* addr) { + if (ump_app_get_is_ipv6 (app_data)) { + if (SOCKADDR_IN6 (addr)->sin6_family != AF_INET6) { + return -1; + } + ump_pkt_set_dest_port (pkt, SOCKADDR_IN6 (addr)->sin6_port); + ump_app_set_dest_ip_addr (app_data, SOCKADDR_IN6 (addr)->sin6_addr.s6_addr); + } else { + if (SOCKADDR_IN (addr)->sin_family != AF_INET) { + return -1; + } + ump_pkt_set_dest_port (pkt, SOCKADDR_IN (addr)->sin_port); + ump_app_set_dest_ip_addr (app_data, &(SOCKADDR_IN (addr)->sin_addr.s_addr)); + } + return 0; +} + +void ump_app_fill_sockaddr_with_src ( + UmpApp* app_data, UmpPkt* pkt, struct sockaddr* addr, socklen_t* addr_len) { + + if (ump_app_get_is_ipv6 (app_data)) { + SOCKADDR_IN6 (addr)->sin6_family = AF_INET6; + SOCKADDR_IN6 (addr)->sin6_port = ump_pkt_get_src_port (pkt); + memcpy ( + SOCKADDR_IN6 (addr)->sin6_addr.s6_addr, + ump_app_get_src_ip_addr (app_data), + UMP_COMMON_IPV6_ADDRLEN); + if (addr_len != NULL) { + *addr_len = sizeof (struct sockaddr_in6); + } + } else { + SOCKADDR_IN (addr)->sin_family = AF_INET; + SOCKADDR_IN (addr)->sin_port = ump_pkt_get_src_port (pkt); + SOCKADDR_IN (addr)->sin_addr.s_addr = + *(uint32_t*)(ump_app_get_src_ip_addr (app_data)); + if (addr_len != NULL) { + *addr_len = sizeof (struct sockaddr_in); + } + } +} + void ump_app_fill_sockaddr_with_dest ( - UmpApp* app_data, struct sockaddr* addr, socklen_t* addr_len) { + UmpApp* app_data, UmpPkt* pkt, struct sockaddr* addr, socklen_t* addr_len) { if (ump_app_get_is_ipv6 (app_data)) { SOCKADDR_IN6 (addr)->sin6_family = AF_INET6; - SOCKADDR_IN6 (addr)->sin6_port = ump_app_get_dest_port (app_data); + SOCKADDR_IN6 (addr)->sin6_port = ump_pkt_get_dest_port (pkt); memcpy ( SOCKADDR_IN6 (addr)->sin6_addr.s6_addr, ump_app_get_dest_ip_addr (app_data), @@ -41,7 +83,7 @@ void ump_app_fill_sockaddr_with_dest ( } } else { SOCKADDR_IN (addr)->sin_family = AF_INET; - SOCKADDR_IN (addr)->sin_port = ump_app_get_dest_port (app_data); + SOCKADDR_IN (addr)->sin_port = ump_pkt_get_dest_port (pkt); SOCKADDR_IN (addr)->sin_addr.s_addr = *(uint32_t*)(ump_app_get_dest_ip_addr (app_data)); if (addr_len != NULL) { @@ -49,5 +91,3 @@ void ump_app_fill_sockaddr_with_dest ( } } } - -#include "ump-app.h" diff --git a/hw2/ump-app.h b/hw2/ump-app.h index fb67ad7..b914f4d 100644 --- a/hw2/ump-app.h +++ b/hw2/ump-app.h @@ -15,9 +15,7 @@ /* application layer data structure: * offset 0, length 1 : IPv4 / IPv6 - * offset 1, length 2 : source port - * offset 3, length 2 : destination port - * offset 5, length ? : src IP addr -> dest IP addr -> data */ + * offset 1, length ? : src IP addr -> dest IP addr -> data */ #define UMP_APP(x) ((UmpApp*)(x)) #define UMP_APP_SIZE (UMP_PKT_SIZE - (((1 << 5) - 1) * 4)) @@ -44,11 +42,8 @@ static inline void ump_app_set_is_ipv6 (UmpApp* app_data, bool is_ipv6) { } } -UMP_COMMON_DEFINE_BOTH (UmpApp, ump_app, src_port, 1, uint16_t); -UMP_COMMON_DEFINE_BOTH (UmpApp, ump_app, dest_port, 3, uint16_t); - static inline void* ump_app_get_src_ip_addr (UmpApp* app_data) { - return UMP_COMMON_MOVE_POINTER (app_data, 5); + return UMP_COMMON_MOVE_POINTER (app_data, 1); } static inline void ump_app_set_src_ip_addr (UmpApp* app_data, void* data) { if (ump_app_get_is_ipv6 (app_data)) { @@ -61,9 +56,9 @@ static inline void ump_app_set_src_ip_addr (UmpApp* app_data, void* data) { } static inline void* ump_app_get_dest_ip_addr (UmpApp* app_data) { if (ump_app_get_is_ipv6 (app_data)) { - return UMP_COMMON_MOVE_POINTER (app_data, 5 + UMP_COMMON_IPV6_ADDRLEN); + return UMP_COMMON_MOVE_POINTER (app_data, 1 + UMP_COMMON_IPV6_ADDRLEN); } else { - return UMP_COMMON_MOVE_POINTER (app_data, 5 + UMP_COMMON_IPV4_ADDRLEN); + return UMP_COMMON_MOVE_POINTER (app_data, 1 + UMP_COMMON_IPV4_ADDRLEN); } } static inline void ump_app_set_dest_ip_addr (UmpApp* app_data, void* data) { @@ -79,10 +74,10 @@ static inline void ump_app_set_dest_ip_addr (UmpApp* app_data, void* data) { static inline void* ump_app_get_real_data (UmpApp* app_data) { if (ump_app_get_is_ipv6 (app_data)) { return UMP_COMMON_MOVE_POINTER ( - app_data, 5 + UMP_COMMON_IPV6_ADDRLEN * 2); + app_data, 1 + UMP_COMMON_IPV6_ADDRLEN * 2); } else { return UMP_COMMON_MOVE_POINTER ( - app_data, 5 + UMP_COMMON_IPV4_ADDRLEN * 2); + app_data, 1 + UMP_COMMON_IPV4_ADDRLEN * 2); } } static inline size_t ump_app_get_real_data_len (UmpApp* app_data) { @@ -99,17 +94,29 @@ static inline void ump_app_set_real_data ( app_data->real_data_len = len; } +static inline size_t ump_app_calc_size (UmpApp* app_data) { + if (ump_app_get_is_ipv6 (app_data)) { + return 1 + UMP_COMMON_IPV6_ADDRLEN * 2 + app_data->real_data_len; + } else { + return 1 + UMP_COMMON_IPV4_ADDRLEN * 2 + app_data->real_data_len; + } +} + static inline bool ump_app_check_size (UmpApp* app_data, size_t size) { if (ump_app_get_is_ipv6 (app_data)) { - return (5 + UMP_COMMON_IPV6_ADDRLEN * 2 >= size); + return (1 + UMP_COMMON_IPV6_ADDRLEN * 2 >= size); } else { - return (5 + UMP_COMMON_IPV4_ADDRLEN * 2 >= size); + return (1 + UMP_COMMON_IPV4_ADDRLEN * 2 >= size); } } int ump_app_fill_src_with_sockaddr ( - UmpApp* app_data, const struct sockaddr* addr); + UmpApp* app_data, UmpPkt* pkt, const struct sockaddr* addr); +int ump_app_fill_dest_with_sockaddr ( + UmpApp* app_data, UmpPkt* pkt, const struct sockaddr* addr); +void ump_app_fill_sockaddr_with_src ( + UmpApp* app_data, UmpPkt* pkt, struct sockaddr* addr, socklen_t* addr_len); void ump_app_fill_sockaddr_with_dest ( - UmpApp* app_data, struct sockaddr* addr, socklen_t* addr_len); + UmpApp* app_data, UmpPkt* pkt, struct sockaddr* addr, socklen_t* addr_len); #endif /* UMP_TCP_H */ diff --git a/hw2/ump-common.h b/hw2/ump-common.h index 264d628..6f6d195 100644 --- a/hw2/ump-common.h +++ b/hw2/ump-common.h @@ -38,9 +38,9 @@ static inline void func_ns ## _set_ ## name (struct_type* pkt, uint8_t x) { \ uint8_t* d = UMP_COMMON_MOVE_POINTER (pkt, offset); \ if (x) { \ - *d &= ~(UMP_COMMON_UINT8_ONE << bit); \ - } else { \ *d |= (UMP_COMMON_UINT8_ONE << bit); \ + } else { \ + *d &= ~(UMP_COMMON_UINT8_ONE << bit); \ } \ } #define UMP_COMMON_DEFINE_BOTH_FLAG(struct_type,func_ns,name,offset,bit) \ diff --git a/hw2/ump-gai.c b/hw2/ump-gai.c index 74a3cae..f97ba06 100644 --- a/hw2/ump-gai.c +++ b/hw2/ump-gai.c @@ -17,12 +17,19 @@ #include <unistd.h> int ump_gai (LbsLogger* lbs_log, const char* host, const char* port, - const struct addrinfo* hints, int *error) { + bool try_bind, struct sockaddr_storage* addr, socklen_t* addr_len, + int *error) { lbs_logger_format (lbs_log, "getaddrinfo: host %s, port %s",host, port); + struct addrinfo hints; + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_ADDRCONFIG; + struct addrinfo* result; - int gai_errno = getaddrinfo (host, port, hints, &result); + int gai_errno = getaddrinfo (host, port, &hints, &result); if (gai_errno != 0) { lbs_logger_format (lbs_log, "getaddrinfo: %s", gai_strerror (gai_errno)); *error = gai_errno; @@ -30,18 +37,33 @@ int ump_gai (LbsLogger* lbs_log, const char* host, const char* port, } for (struct addrinfo* iter = result; iter != NULL; iter = iter->ai_next) { - int sockfd = socket (iter->ai_family, SOCK_DGRAM, 0); - if (sockfd < 0) { - freeaddrinfo (result); - lbs_logger_format (lbs_log, "socket: %s", strerror (errno)); - *error = 0; - return -1; + int sockfd; + if (try_bind) { + sockfd = socket (iter->ai_family, SOCK_DGRAM, 0); + if (sockfd < 0) { + freeaddrinfo (result); + lbs_logger_format (lbs_log, "socket: %s", strerror (errno)); + *error = 0; + return -1; + } } if (iter->ai_family == AF_INET6) { lbs_logger_string (lbs_log, "host address is IPv6"); + if (addr != NULL) { + memcpy (addr, iter->ai_addr, sizeof (struct sockaddr_in6)); + } + if (addr_len != NULL) { + *addr_len = iter->ai_addrlen; + } } else { lbs_logger_string (lbs_log, "host address is IPv4"); + if (addr != NULL) { + memcpy (addr, iter->ai_addr, sizeof (struct sockaddr_in)); + } + if (addr_len != NULL) { + *addr_len = iter->ai_addrlen; + } } size_t ip_str_len = xmax (INET_ADDRSTRLEN, INET6_ADDRSTRLEN); @@ -58,21 +80,25 @@ int ump_gai (LbsLogger* lbs_log, const char* host, const char* port, ip_str, ip_str_len) == NULL) { lbs_logger_format (lbs_log, - "bind to unknown host, port %" PRIu16, udp_port); + "unknown host, port %" PRIu16, udp_port); } else { lbs_logger_format (lbs_log, - "bind to host %s, port %" PRIu16, ip_str, udp_port); + "host %s, port %" PRIu16, ip_str, udp_port); } free (ip_str); - if (bind (sockfd, iter->ai_addr, iter->ai_addrlen) < 0) { + if (try_bind && bind (sockfd, iter->ai_addr, iter->ai_addrlen) < 0) { lbs_logger_format (lbs_log, "bind: %s", strerror (errno)); close (sockfd); } else { - lbs_logger_string (lbs_log, "bind OK"); freeaddrinfo (result); - return sockfd; + if (try_bind) { + lbs_logger_string (lbs_log, "bind OK"); + return sockfd; + } else { + return 0; + } } } diff --git a/hw2/ump-gai.h b/hw2/ump-gai.h index 6d6ba25..104a981 100644 --- a/hw2/ump-gai.h +++ b/hw2/ump-gai.h @@ -10,6 +10,7 @@ #include <sys/socket.h> int ump_gai (LbsLogger* lbs_log, const char* host, const char* port, - const struct addrinfo* hints, int *error); + bool try_bind, struct sockaddr_storage* addr, socklen_t* addr_len, + int *error); #endif /* UMP_GAI_H */ diff --git a/hw2/ump-pkt.c b/hw2/ump-pkt.c index 9b652ba..babcf34 100644 --- a/hw2/ump-pkt.c +++ b/hw2/ump-pkt.c @@ -10,11 +10,11 @@ uint16_t ump_pkt_calc_checksum (UmpPkt* pkt, bool skip_checksum) { size_t pkt_len = ump_pkt_get_data_offset (pkt) + pkt->app_data_len; - uint8_t* pkt_data = UMP_COMMON_MOVE_POINTER (pkt, 0); + uint16_t* pkt_data = (uint16_t*)UMP_COMMON_MOVE_POINTER (pkt, 0); uint16_t checksum = 0; - for (int i = 0; i < pkt_len; i++) { - if ((i != 16 && i != 17) || !skip_checksum) { - uint32_t checksum_new = checksum + pkt_data[i]; + for (int i = 0; i < pkt_len / 2; i++) { + if ((i != 16 / 2) || !skip_checksum) { + uint16_t checksum_new = checksum + pkt_data[i]; if (checksum_new > checksum) { checksum = checksum_new; } else { @@ -26,29 +26,19 @@ uint16_t ump_pkt_calc_checksum (UmpPkt* pkt, bool skip_checksum) { } void ump_pkt_fill_checksum (UmpPkt* pkt) { - uint8_t checksum = ump_pkt_calc_checksum (pkt, true); + uint16_t checksum = ump_pkt_calc_checksum (pkt, true); ump_pkt_set_checksum (pkt, checksum); } bool ump_pkt_verify_checksum (UmpPkt* pkt) { - uint8_t checksum = ump_pkt_calc_checksum (pkt, false); - if (~checksum) { + uint16_t checksum = ump_pkt_calc_checksum (pkt, false); + if (checksum) { return false; } else { return true; } } -/* -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_ns, 12, 1); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_cwr, 13, 7); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_ece, 13, 6); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_urg, 13, 5); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_ack, 13, 4); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_psh, 13, 3); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_rst, 13, 2); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_syn, 13, 1); -UMP_COMMON_DEFINE_BOTH_FLAG (UmpPkt, ump_pkt, flag_fin, 13, 0);*/ char* ump_pkt_show_message (UmpPkt* pkt) { static char msg[6 * 9]; char* msgp = msg; diff --git a/hw2/ump-pkt.h b/hw2/ump-pkt.h index 678761c..7999391 100644 --- a/hw2/ump-pkt.h +++ b/hw2/ump-pkt.h @@ -52,7 +52,7 @@ UMP_COMMON_DEFINE_BOTH (UmpPkt, ump_pkt, window_size, 14, uint16_t); UMP_COMMON_DEFINE_BOTH (UmpPkt, ump_pkt, checksum, 16, uint16_t); UMP_COMMON_DEFINE_BOTH (UmpPkt, ump_pkt, urgent_ptr, 18, uint16_t); -static inline uint8_t* ump_pkt_get_app_data (UmpPkt* pkt) { +static inline void* ump_pkt_get_app_data (UmpPkt* pkt) { uint8_t off = ump_pkt_get_data_offset (pkt); return UMP_COMMON_MOVE_POINTER (pkt, off); } @@ -63,7 +63,7 @@ static inline size_t ump_pkt_get_app_data_max (UmpPkt* pkt) { return UMP_PKT_SIZE - ump_pkt_get_data_offset (pkt); } static inline void ump_pkt_set_app_data ( - UmpPkt* pkt, const uint8_t* data, size_t len) { + UmpPkt* pkt, const void* data, size_t len) { uint8_t* app_data = ump_pkt_get_app_data (pkt); memcpy (app_data, data, len); @@ -73,6 +73,11 @@ static inline void ump_pkt_set_app_data ( static inline void ump_pkt_init (UmpPkt* pkt) { memset (pkt, 0, sizeof (UmpPkt)); ump_pkt_set_data_offset (pkt, 20); + pkt->app_data_len = 0; +} + +static inline size_t ump_pkt_calc_size (UmpPkt* pkt) { + return pkt->app_data_len + ump_pkt_get_data_offset (pkt); } static inline bool ump_pkt_check_size (UmpPkt* pkt, size_t size) { diff --git a/hw2/ump-sched.c b/hw2/ump-sched.c new file mode 100644 index 0000000..b8e7132 --- /dev/null +++ b/hw2/ump-sched.c @@ -0,0 +1,286 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "ump-sched.h" +#include "ump-app.h" +#include "ump-gai.h" +#include "ump-pkt.h" +#include "l4logger.h" +#include "xwrap.h" + +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <unistd.h> + +UmpSched* ump_sched_new ( + LbsLogger* lbs_log, UmpSchedType type, char* agents[], size_t count) { + + if (type >= UMP_SCHED_TYPE_LAST || type < 0) { + return NULL; + } + + UmpSched* sched = xmalloc (sizeof (UmpSched) + sizeof (UmpSchedConn) * count); + sched->pkt_start = 0; + sched->pkt_end = 0; + sched->window_size = 1; + sched->threshold = 16; + sched->seq_start = rand (); + sched->seq_num = sched->seq_start; + sched->ack_num = sched->seq_num; + sched->conn_fd = -1; + sched->log = lbs_log; + sched->type = type; + sched->peer_set = false; + sched->conn_count = count; + + for (int i = 0; i < count; i++) { + int gai_error; + if (ump_gai (sched->log, agents[i * 2], agents[i * 2 + 1], + false, &(sched->conn[i].addr), &(sched->conn[i].addr_len), + &gai_error) < 0) { + + free (sched); + return NULL; + } + + sched->conn[i].score = 0; + sched->conn[i].sent = 0; + } + + return sched; +} + +void ump_sched_free (UmpSched* sched) { + if (sched->conn_fd >= 0) { + close (sched->conn_fd); + } + free (sched); +} + +static size_t init_packet (UmpPkt* pkt, + struct sockaddr* addr, void* data, size_t data_len) { + + UmpApp app_data_struct; + UmpApp* app_data = &app_data_struct; + + ump_pkt_init (pkt); + app_data->real_data_len = 0; + + if (addr->sa_family == AF_INET6) { + ump_app_set_is_ipv6 (app_data, true); + ump_app_set_dest_ip_addr (app_data, SOCKADDR_IN6 (addr)->sin6_addr.s6_addr); + ump_pkt_set_dest_port (pkt, SOCKADDR_IN6 (addr)->sin6_port); + } else { + ump_app_set_is_ipv6 (app_data, false); + ump_app_set_dest_ip_addr (app_data, &(SOCKADDR_IN (addr)->sin_addr.s_addr)); + ump_pkt_set_dest_port (pkt, SOCKADDR_IN (addr)->sin_port); + } + + size_t data_max = ump_app_get_real_data_max (app_data); + size_t set_size = data_len > data_max ? data_max : data_len; + if (data != NULL) { + ump_app_set_real_data (app_data, data, set_size); + } + ump_pkt_set_app_data (pkt, app_data, ump_app_calc_size (app_data)); + return data_len - set_size; +} + +static bool check_packet (UmpPkt* pkt, UmpSched* sched, size_t pkt_len) { + if (!ump_pkt_check_size (pkt, pkt_len)) { + lbs_logger_string (sched->log, "Bad header"); + return false; + } + size_t app_len = pkt_len - ump_pkt_get_data_offset (pkt); + pkt->app_data_len = app_len; + if (!ump_pkt_verify_checksum (pkt)) { + lbs_logger_string (sched->log, "Bad checksum"); + return false; + } + if (!ump_app_check_size (ump_pkt_get_app_data (pkt), app_len)) { + lbs_logger_string (sched->log, "Bad app_data"); + return false; + } + return true; +} + +static int send_packet (UmpPkt* pkt, UmpSched* sched) { + int selected = 0, net_score = INT_MIN; + for (int i = 0; i < sched->conn_count; i++) { + int net_score_this = sched->conn[i].score - sched->conn[i].sent; + if (net_score_this > net_score) { + net_score = net_score_this; + selected = i; + } + } + + if (sched->peer_set) { + sched->conn[selected].sent++; + sched->conn[selected].score++; + lbs_logger_format (sched->log, "send %s packet #%" PRIu32, + ump_pkt_show_message (pkt), ump_pkt_get_seq_num (pkt)); + if (sendto (sched->conn_fd, pkt, + ump_pkt_get_data_offset (pkt) + pkt->app_data_len, 0, + SOCKADDR (&(sched->conn[selected].addr)), + sched->conn[selected].addr_len) < 0) { + + lbs_logger_format (sched->log, "sendto: %s", strerror (errno)); + return -1; + } + return 0; + } else { + lbs_logger_string (sched->log, "no peer ... why?"); + return -1; + } +} + +int ump_sched_connect (UmpSched* sched, char* dest[2]) { + assert (sched->type == UMP_SCHED_TYPE_SENDER); + + int gai_error; + if (ump_gai (sched->log, dest[0], dest[1], false, + &(sched->peer), &(sched->peer_len), &gai_error) < 0) { + + return -1; + } + + sched->conn_fd = socket (sched->peer.ss_family, SOCK_DGRAM, 0); + if (sched->conn_fd < 0) { + lbs_logger_format (sched->log, "socket: %s", strerror (errno)); + return -1; + } + + sched->peer_set = true; + lbs_logger_string (sched->log, "socket OK"); + + UmpPkt pkt_struct; + UmpPkt *pkt = &pkt_struct; + + sched->seq_num++; + init_packet (pkt, SOCKADDR (&sched->peer), NULL, 0); + ump_pkt_set_flag_syn (pkt, true); + ump_pkt_set_seq_num (pkt, sched->seq_num); + ump_pkt_fill_checksum (pkt); + send_packet (pkt, sched); + + lbs_logger_string (sched->log, "Waiting for ACK ..."); + setitimer (ITIMER_REAL, &(struct itimerval) { + .it_interval = (struct timeval) { 0, 0 }, + .it_value = (struct timeval) { 1, 5 } + }, NULL); + + ssize_t pkt_len = recvfrom (sched->conn_fd, pkt, UMP_PKT_SIZE, 0, NULL, NULL); + if (pkt_len < 0) { + if (errno == EINTR) { + lbs_logger_string (sched->log, "Time out !!!"); + } + return -1; + } + + lbs_logger_format (sched->log, "receive %s packet #%" PRIu32, + ump_pkt_show_message (pkt), ump_pkt_get_seq_num (pkt)); + if (!check_packet (pkt, sched, pkt_len)) { + return -1; + } + if (!ump_pkt_get_flag_ack (pkt)) { + lbs_logger_string (sched->log, "No ACK. Why?"); + return -1; + } + if (ump_pkt_get_seq_num (pkt) != sched->seq_num) { + lbs_logger_string (sched->log, "Wrong ACK number"); + return -1; + } + sched->ack_num = sched->seq_num; + + return 0; +} + +int ump_sched_listen (UmpSched* sched, char* host[2]) { + assert (sched->type == UMP_SCHED_TYPE_RECEIVER); + + int gai_error; + int gai_fd = ump_gai (sched->log, host[0], host[1], true, + NULL, NULL, &gai_error); + + if (gai_fd < 0) { + return -1; + } + sched->conn_fd = gai_fd; + + return 0; +} + +int ump_sched_accept (UmpSched* sched) { + assert (sched->type == UMP_SCHED_TYPE_RECEIVER); + + UmpPkt pkt_struct; + UmpPkt* pkt = &pkt_struct; + struct sockaddr_storage agent_addr; + socklen_t agent_addr_len = sizeof (struct sockaddr_storage); + + ssize_t pkt_len = recvfrom (sched->conn_fd, pkt, UMP_PKT_SIZE, 0, + SOCKADDR (&agent_addr), &agent_addr_len); + if (pkt_len < 0) { + lbs_logger_format (sched->log, "recvfrom: %s", strerror (errno)); + return -1; + } + + lbs_logger_format (sched->log, "receive %s packet #%" PRIu32, + ump_pkt_show_message (pkt), ump_pkt_get_seq_num (pkt)); + if (!check_packet (pkt, sched, pkt_len)) { + return -1; + } + if (!ump_pkt_get_flag_syn (pkt)) { + lbs_logger_string (sched->log, "No SYN. Why?"); + return -1; + } + + UmpApp* app_data = ump_pkt_get_app_data (pkt); + uint32_t seq = ump_pkt_get_seq_num (pkt); + + ump_app_fill_sockaddr_with_src (app_data, pkt, + SOCKADDR (&sched->peer), &sched->peer_len); + sched->peer_set = true; + + init_packet (pkt, SOCKADDR (&sched->peer), NULL, 0); + ump_pkt_set_flag_ack (pkt, true); + ump_pkt_set_seq_num (pkt, seq); + ump_pkt_fill_checksum (pkt); + lbs_logger_format (sched->log, "send %s packet #%" PRIu32, + ump_pkt_show_message (pkt), ump_pkt_get_seq_num (pkt)); + sendto (sched->conn_fd, pkt, + ump_pkt_get_data_offset (pkt) + pkt->app_data_len, 0, + SOCKADDR (&agent_addr), agent_addr_len); + + return 0; +} + +ssize_t ump_sched_receive (UmpSched* sched, void* buf, size_t count) { + return 0; +} + +ssize_t ump_sched_send (UmpSched* sched, void* buf, size_t count) { + return 0; +} + +void ump_sched_shutdown (UmpSched* sched) { + assert (sched->type == UMP_SCHED_TYPE_SENDER); + + UmpPkt pkt_struct; + UmpPkt* pkt = &pkt_struct; + + sched->seq_num++; + init_packet (pkt, SOCKADDR (&sched->peer), NULL, 0); + ump_pkt_set_flag_fin (pkt, true); + ump_pkt_set_seq_num (pkt, sched->seq_num); + ump_pkt_fill_checksum (pkt); + send_packet (pkt, sched); + + sched->peer_set = false; +} diff --git a/hw2/ump-sched.h b/hw2/ump-sched.h new file mode 100644 index 0000000..b184fc2 --- /dev/null +++ b/hw2/ump-sched.h @@ -0,0 +1,61 @@ +#ifndef UMP_SCHED_H +#define UMP_SCHED_H + +/* Multipath schedular and high level functions */ + +#include "l4logger.h" +#include "ump-pkt.h" + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/socket.h> + +#define UMP_SCHED_PKT_COUNT 64 + +typedef struct UmpSchedConnStruct { + int score; + int sent; + struct sockaddr_storage addr; + socklen_t addr_len; +} UmpSchedConn; + +typedef enum UmpSchedTypeEnum { + UMP_SCHED_TYPE_SENDER, + UMP_SCHED_TYPE_RECEIVER, + UMP_SCHED_TYPE_LAST +} UmpSchedType; + +typedef struct UmpSchedStruct { + UmpPkt pkt[UMP_SCHED_PKT_COUNT]; + int pkt_map[UMP_SCHED_PKT_COUNT]; + size_t pkt_start; + size_t pkt_end; + size_t window_size; + size_t threshold; + uint32_t seq_start; + uint32_t seq_num; + uint32_t ack_num; + int conn_fd; + struct sockaddr_storage peer; + socklen_t peer_len; + bool peer_set; + LbsLogger* log; + UmpSchedType type; + size_t conn_count; + UmpSchedConn conn[]; +} UmpSched; + +UmpSched* ump_sched_new ( + LbsLogger* lbs_log, UmpSchedType type, char* agents[], size_t count); +void ump_sched_free (UmpSched* sched); + +int ump_sched_connect (UmpSched* sched, char* dest[2]); +int ump_sched_listen (UmpSched* sched, char* host[2]); +int ump_sched_accept (UmpSched* sched); +ssize_t ump_sched_receive(UmpSched* sched, void* buf, size_t count); +ssize_t ump_sched_send (UmpSched* sched, void* buf, size_t count); +void ump_sched_shutdown (UmpSched* sched); + +#endif /* UMP_SCHED_H */ |