summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-12-22 03:07:39 +0800
committerLAN-TW <lantw44@gmail.com>2013-12-22 03:07:39 +0800
commit0651f1f727b6f33e9b8655aaf90ed9250eea41ae (patch)
tree1ac24224302337978d422af9b7f6135313016fb5
parent3c7cd856722378cb0ed0cba0f4a33eaa05a8dc0d (diff)
downloadcn2013-0651f1f727b6f33e9b8655aaf90ed9250eea41ae.tar.gz
cn2013-0651f1f727b6f33e9b8655aaf90ed9250eea41ae.tar.zst
cn2013-0651f1f727b6f33e9b8655aaf90ed9250eea41ae.zip
HW2: 修正各種錯誤,並完成基本的連線操作
-rw-r--r--hw2/Makefile.am5
-rw-r--r--hw2/agent-main.c22
-rw-r--r--hw2/trans-loop.c86
-rw-r--r--hw2/trans-loop.h9
-rw-r--r--hw2/trans-main.c88
-rw-r--r--hw2/ump-app.c56
-rw-r--r--hw2/ump-app.h37
-rw-r--r--hw2/ump-common.h4
-rw-r--r--hw2/ump-gai.c52
-rw-r--r--hw2/ump-gai.h3
-rw-r--r--hw2/ump-pkt.c24
-rw-r--r--hw2/ump-pkt.h9
-rw-r--r--hw2/ump-sched.c286
-rw-r--r--hw2/ump-sched.h61
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 */