aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranciszek Malinka <franciszek.malinka@gmail.com>2021-04-19 08:41:26 +0200
committerFranciszek Malinka <franciszek.malinka@gmail.com>2021-04-19 08:41:26 +0200
commit1078d2387db43d0c7e982d1ba3340dc67fe0fed9 (patch)
treeebb144225320e2559b29cc49efb6b5eea03183c5
parent4167f191cec04314082896ca4618663e97b4f4f1 (diff)
Router update
-rw-r--r--Semestr 4/sieci/pracownia2/router/config.h9
-rw-r--r--Semestr 4/sieci/pracownia2/router/dist_vector.c8
-rw-r--r--Semestr 4/sieci/pracownia2/router/dist_vector.h24
-rw-r--r--Semestr 4/sieci/pracownia2/router/linked_list.c58
-rw-r--r--Semestr 4/sieci/pracownia2/router/linked_list.h38
-rw-r--r--Semestr 4/sieci/pracownia2/router/network_addr.c50
-rw-r--r--Semestr 4/sieci/pracownia2/router/network_addr.h43
-rw-r--r--Semestr 4/sieci/pracownia2/router/router.c27
-rw-r--r--Semestr 4/sieci/pracownia2/router/router_addr.c32
-rw-r--r--Semestr 4/sieci/pracownia2/router/router_addr.h19
-rw-r--r--Semestr 4/sieci/pracownia2/router/test.c40
-rw-r--r--Semestr 4/sieci/pracownia2/router/utils.c28
-rw-r--r--Semestr 4/sieci/pracownia2/router/utils.h17
-rw-r--r--Semestr 4/sieci/pracownia2/router/vector.h1
14 files changed, 314 insertions, 80 deletions
diff --git a/Semestr 4/sieci/pracownia2/router/config.h b/Semestr 4/sieci/pracownia2/router/config.h
new file mode 100644
index 0000000..3537c03
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/config.h
@@ -0,0 +1,9 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define SERVER_PORT 54321
+#define TURN_LEN_S 5
+#define TURN_LEN_MS (1000 * TURN_LEN_S)
+#define TURN_LEN_US (1000000 * TURN_LEN_S)
+
+#endif \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/dist_vector.c b/Semestr 4/sieci/pracownia2/router/dist_vector.c
new file mode 100644
index 0000000..1e09bff
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/dist_vector.c
@@ -0,0 +1,8 @@
+#include "dist_vector.h"
+
+bool is_connected_directly(struct vector_item item) {
+ return (get_network_address(item.network).s_addr ==
+ get_network_address(item.via_ip).s_addr);
+}
+
+void update_distance_vector(list_t *distance_vector, struct vector_item new_item) {} \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/dist_vector.h b/Semestr 4/sieci/pracownia2/router/dist_vector.h
new file mode 100644
index 0000000..cd1a995
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/dist_vector.h
@@ -0,0 +1,24 @@
+#ifndef DIST_VECTOR_H
+#define DIST_VECTOR_H
+
+#include "linked_list.h"
+#include "network_addr.h"
+
+/* Item of the distance vector.
+ * If <<reachable>> is set to 0, then it means that the network is reachable.
+ * If <<reachable>> has positive value, then it indicates that the network was
+ * unreachable for <<reachable>> turns.
+ */
+struct vector_item {
+ struct network_addr network;
+ router_addr via_ip;
+ uint8_t reachable;
+};
+
+/* Returns true if given distance vector item is connected directly, false otherwise */
+bool is_connected_directly(struct vector_item item);
+
+/* Updates the distance vector. */
+void update_distance_vector(list_t *distance_vector, struct vector_item new_item);
+
+#endif \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/linked_list.c b/Semestr 4/sieci/pracownia2/router/linked_list.c
new file mode 100644
index 0000000..b6b5225
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/linked_list.c
@@ -0,0 +1,58 @@
+#include "linked_list.h"
+#include <stdlib.h>
+#include <stdint.h>
+
+node_t *_next(node_t *node) {
+ return (node == NULL) ? NULL : node->next;
+}
+
+void _insert(node_t **head, void *data, size_t data_size) {
+ node_t *new_node = (node_t *)malloc(sizeof(node_t));
+ new_node->data = malloc(data_size);
+ for (int i = 0; i < data_size; i++)
+ *(uint8_t *)(new_node->data + i) = *(uint8_t *)(data + i);
+
+ new_node->next = *head;
+ *head = new_node;
+}
+
+void _erase(node_t **head) {
+ node_t *next_node = _next(*head);
+ free((*head)->data);
+ free(*head);
+ *head = next_node;
+}
+
+void _free_list(node_t *head) {
+ if (head == NULL) return;
+ _free_list(head->next);
+ free(head->data);
+ free(head);
+}
+
+list_t create_list() {
+ list_t ret;
+ ret.head = NULL;
+ ret.it = NULL;
+ return ret;
+}
+
+void insert(list_t *list, void *data, size_t data_size) {
+ _insert(&list->head, data, data_size);
+}
+
+void erase(list_t *list) {
+ _erase(&list->head);
+}
+
+void iterate(list_t *list) {
+ list->it = _next(list->it);
+}
+
+void reset(list_t *list) {
+ list->it = list->head;
+}
+
+void free_list(list_t *list) {
+ _free_list(list->head);
+} \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/linked_list.h b/Semestr 4/sieci/pracownia2/router/linked_list.h
new file mode 100644
index 0000000..f662dbe
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/linked_list.h
@@ -0,0 +1,38 @@
+#ifndef LINKED_LIST_H
+#define LINKED_LIST_H
+
+#include <stddef.h>
+
+typedef struct node {
+ void *data;
+ struct node *next;
+} node_t;
+
+
+typedef struct list_t {
+ node_t *head;
+ node_t *it;
+} list_t;
+
+/* Creates an empty list */
+list_t create_list();
+
+/* Insert a new node in the begining of a list. */
+void insert(list_t *list, void *data, size_t data_size);
+
+/* Erases first node from the list. */
+void erase(list_t *list);
+
+/* Moves iterator one step. */
+void iterate(list_t *list);
+
+/* Resets the iterator.
+ * Should execute the function after if you want to itarate unless you didnt insert or erase anything from the list.
+ */
+void reset(list_t *list);
+
+/* Deletes the whole list. */
+void free_list(list_t *list);
+
+
+#endif \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/network_addr.c b/Semestr 4/sieci/pracownia2/router/network_addr.c
new file mode 100644
index 0000000..a65f48c
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/network_addr.c
@@ -0,0 +1,50 @@
+#include "network_addr.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+struct in_addr _get_broadcast_address(struct in_addr addr, uint16_t netmask) {
+ struct in_addr result = addr;
+ /* bitshift by more than 31 is UB */
+ if (netmask < 32) {
+ result.s_addr |= ~((1<<netmask) - 1);
+ }
+ return result;
+}
+
+struct in_addr _get_network_address(struct in_addr addr, uint16_t netmask) {
+ struct in_addr result = addr;
+ if (netmask == 0) {
+ addr.s_addr = 0;
+ }
+ else {
+ result.s_addr &= ~((1 << (32 - netmask)) - 1);
+ }
+ return result;
+}
+
+struct in_addr get_broadcast_address(struct network_addr na) {
+ return _get_broadcast_address(na.addr, na.netmask);
+}
+
+struct in_addr get_network_address(struct network_addr na) {
+ return _get_network_address(na.addr, na.netmask);
+}
+
+void pretty_print(struct network_addr na) {
+ char ip_addr[20];
+ inet_ntop(AF_INET, &na.addr, ip_addr, sizeof(ip_addr));
+ printf("%s/%d distance %d\n", ip_addr, na.netmask, na.distance);
+}
+
+struct network_addr stora(char *str) {
+ struct network_addr result;
+ char addr[20];
+ size_t ip_preffix = strcspn(str, "/");
+
+ strncpy(addr, str, strlen(str));
+ addr[ip_preffix] = 0;
+ inet_pton(AF_INET, addr, &(result.addr));
+ result.netmask = atoi(str + ip_preffix + 1);
+ return result;
+}
diff --git a/Semestr 4/sieci/pracownia2/router/network_addr.h b/Semestr 4/sieci/pracownia2/router/network_addr.h
new file mode 100644
index 0000000..777406a
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/network_addr.h
@@ -0,0 +1,43 @@
+#ifndef ROUTER_ADDR_H
+#define ROUTER_ADDR_H
+
+#include <arpa/inet.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define INFINITY_DIST 128
+
+/* Network address and sitance */
+struct network_addr {
+ struct in_addr addr;
+ uint16_t distance;
+ uint8_t netmask;
+};
+
+typedef struct network_addr router_addr;
+
+/* Item of the distance vector.
+ * If <<reachable>> is set to 0, then it means that the network is reachable.
+ * If <<reachable>> has positive value, then it indicates that the network was
+ * unreachable for <<reachable>> turns.
+ */
+struct vector_item {
+ struct network_addr network;
+ struct in_addr via_ip;
+ uint8_t reachable;
+};
+
+/* Returns broadcast address of a given network. */
+struct in_addr get_broadcast_address(struct network_addr na);
+
+/* Returns network address of a given network */
+struct in_addr get_network_address(struct network_addr na);
+
+/* Prints network_addr via stdio. */
+void pretty_print(struct network_addr na);
+
+/* Converts string of ip in CIDR notation with a netmask to network_addr. */
+struct network_addr stora(char *str);
+
+
+#endif \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/router.c b/Semestr 4/sieci/pracownia2/router/router.c
index f68a6a3..031ead8 100644
--- a/Semestr 4/sieci/pracownia2/router/router.c
+++ b/Semestr 4/sieci/pracownia2/router/router.c
@@ -7,18 +7,13 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
-#include "router_addr.h"
+#include "network_addr.h"
#include "utils.h"
-#define SERVER_PORT 54321
-#define TURN_LEN_S 5
-#define TURN_LEN_MS (1000 * TURN_LEN_S)
-#define TURN_LEN_US (1000000 * TURN_LEN_S)
-
-uint16_t read_configuration(struct router_addr** networks) {
+uint16_t read_configuration(struct network_addr** networks) {
uint16_t n;
scanf("%hd", &n);
- *networks = malloc(n * sizeof(struct router_addr));
+ *networks = malloc(n * sizeof(struct network_addr));
for (int i = 0; i < n; i++) {
char addr[20];
char _dist[10];
@@ -30,7 +25,7 @@ uint16_t read_configuration(struct router_addr** networks) {
return n;
}
-void listen_for_routers(int sockfd, int timeout, int networks_number, struct router_addr *netowrks) {
+void listen_for_routers(int sockfd, int timeout, int networks_number, struct network_addr *netowrks) {
printf("Listening for %dms.\n", timeout);
while (poll_socket_modify_timeout(sockfd, &timeout)) {
printf("Poll returned, remaining timeout: %dms.\n", timeout);
@@ -40,12 +35,6 @@ void listen_for_routers(int sockfd, int timeout, int networks_number, struct rou
}
int send_distance_vector(int sockfd, struct in_addr network) {
- struct sockaddr_in network_address;
- bzero (&network_address, sizeof(network_address));
- network_address.sin_family = AF_INET;
- network_address.sin_port = htons(SERVER_PORT);
- network_address.sin_addr = network;
-
char* message = "Hello server! My name is S1\n";
ssize_t message_len = strlen(message);
int result;
@@ -53,12 +42,12 @@ int send_distance_vector(int sockfd, struct in_addr network) {
char addr[20];
inet_ntop(AF_INET, &network, addr, sizeof(addr));
printf("Sending datagram to %s\n", addr);
- if ((result = sendto(sockfd, message, message_len, 0, (struct sockaddr*) &network_address, sizeof(network_address))) != message_len) {
+ if ((result = send_message(sockfd, message, message_len, network)) != message_len) {
fprintf(stderr, "sendto error: %s\n", strerror(errno));
}
}
-void propagate_distance_vector(int sockfd, int networks_number, struct router_addr *networks) {
+void propagate_distance_vector(int sockfd, int networks_number, struct network_addr *networks) {
printf("Propagating distance vector\n");
for (int i = 0; i < networks_number; i++) {
struct in_addr broadcast_address = get_broadcast_address(networks[i]);
@@ -67,7 +56,7 @@ void propagate_distance_vector(int sockfd, int networks_number, struct router_ad
printf("Distance vector propagated.\n\n");
}
-void router_loop(int sockfd, int networks_number, struct router_addr *networks) {
+void router_loop(int sockfd, int networks_number, struct network_addr *networks) {
printf("Starting the router loop...\n");
for (;;) {
listen_for_routers(sockfd, TURN_LEN_MS, networks_number, networks);
@@ -76,7 +65,7 @@ void router_loop(int sockfd, int networks_number, struct router_addr *networks)
}
int main() {
- struct router_addr* networks;
+ struct network_addr* networks;
int n = read_configuration(&networks);
for (int i = 0; i < n; i++) {
pretty_print(networks[i]);
diff --git a/Semestr 4/sieci/pracownia2/router/router_addr.c b/Semestr 4/sieci/pracownia2/router/router_addr.c
deleted file mode 100644
index 1e4c086..0000000
--- a/Semestr 4/sieci/pracownia2/router/router_addr.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "router_addr.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-struct in_addr get_broadcast_address(struct router_addr ra) {
- struct in_addr result = ra.addr;
- /* bitshift by more than 31 is UB */
- if (ra.netmask < 32) {
- result.s_addr |= ~((1<<ra.netmask) - 1);
- }
- return result;
-}
-
-void pretty_print(struct router_addr ra) {
- char ip_addr[20];
- inet_ntop(AF_INET, &ra.addr, ip_addr, sizeof(ip_addr));
- printf("%s/%d distance %d\n", ip_addr, ra.netmask, ra.distance);
-}
-
-/* converts string of IP with netmask in CIDR notation to router_addr */
-struct router_addr stora(char *str) {
- struct router_addr result;
- char addr[20];
- size_t ip_preffix = strcspn(str, "/");
-
- strncpy(addr, str, strlen(str));
- addr[ip_preffix] = 0;
- inet_pton(AF_INET, addr, &(result.addr));
- result.netmask = atoi(str + ip_preffix + 1);
- return result;
-} \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/router_addr.h b/Semestr 4/sieci/pracownia2/router/router_addr.h
deleted file mode 100644
index bebb0f5..0000000
--- a/Semestr 4/sieci/pracownia2/router/router_addr.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef ROUTER_ADDR_H
-#define ROUTER_ADDR_H
-
-#include <arpa/inet.h>
-#include <stdint.h>
-
-struct router_addr {
- struct in_addr addr;
- uint16_t distance;
- uint8_t netmask;
-};
-
-struct in_addr get_broadcast_address(struct router_addr ra);
-
-void pretty_print(struct router_addr ra);
-
-struct router_addr stora(char *str);
-
-#endif \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/test.c b/Semestr 4/sieci/pracownia2/router/test.c
new file mode 100644
index 0000000..ebc6df1
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/test.c
@@ -0,0 +1,40 @@
+#include "linked_list.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Prints the list of ints to stdio */
+void print_list(list_t list) {
+ printf("List: ");
+ reset(&list);
+ while (list.it != NULL) {
+ printf("%d, ", *(int *)(list.it->data));
+ iterate(&list);
+ }
+ printf("\n");
+ reset(&list);
+}
+
+int main() {
+ int n;
+ scanf("%d", &n);
+ list_t list = create_list();
+
+ for (int i = 0; i < n; i++) {
+ int t;
+ scanf("%d", &t);
+ // insert
+ if (t == 0) {
+ int val = 0;
+ scanf("%d", &val);
+ insert(&list, &val, sizeof(int));
+ }
+ if (t == 1) {
+ erase(&list);
+ }
+ if (t == 2) {
+ print_list(list);
+ }
+ }
+
+ free_list(&list);
+} \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/utils.c b/Semestr 4/sieci/pracownia2/router/utils.c
index 9f008eb..2872a35 100644
--- a/Semestr 4/sieci/pracownia2/router/utils.c
+++ b/Semestr 4/sieci/pracownia2/router/utils.c
@@ -21,10 +21,12 @@ void bind_to_port(int sockfd, uint16_t port) {
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
+
if (bind(sockfd, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {
fprintf(stderr, "Bind error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
+
int broadcastPermission = 1;
setsockopt (sockfd, SOL_SOCKET, SO_BROADCAST, (void *)&broadcastPermission, sizeof(broadcastPermission));
}
@@ -38,16 +40,17 @@ int poll_socket_modify_timeout(int sockfd, int *timeout) {
fprintf(stderr, "poll_modify_timeout: timeout is negative.\n");
exit(EXIT_FAILURE);
}
-
+
struct pollfd fds;
+ struct timespec start;
+ struct timespec finish;
+
fds.fd = sockfd;
fds.events = POLLIN;
fds.revents = 0;
-
- struct timespec start;
clock_gettime(CLOCK_REALTIME, &start);
- int result = poll(&fds, 1, *timeout);
+ int result = poll(&fds, 1, *timeout);
if (result == -1) {
fprintf(stderr, "poll error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
@@ -56,15 +59,14 @@ int poll_socket_modify_timeout(int sockfd, int *timeout) {
*timeout = 0;
return 0;
}
- struct timespec finish;
+
clock_gettime(CLOCK_REALTIME, &finish);
*timeout -= get_time_interval(start, finish);
printf("Timeout: %dms, time waiting: %ldms.\n", *timeout, get_time_interval(start, finish));
return result;
}
-/* For debug purposes only */
-void recv_and_print(int sockfd, int networks_number, struct router_addr *networks) {
+void recv_and_print(int sockfd, int networks_number, struct network_addr *networks) {
struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
uint8_t buffer[IP_MAXPACKET + 1];
@@ -87,4 +89,14 @@ void recv_and_print(int sockfd, int networks_number, struct router_addr *network
buffer[datagram_len] = 0;
printf("%ld-byte message: +%s+\n", datagram_len, buffer);
-} \ No newline at end of file
+}
+
+size_t send_message(int sockfd, char *buffer, int buffer_len, struct in_addr network) {
+ struct sockaddr_in network_address;
+ bzero (&network_address, sizeof(network_address));
+ network_address.sin_family = AF_INET;
+ network_address.sin_port = htons(SERVER_PORT);
+ network_address.sin_addr = network;
+
+ return sendto(sockfd, buffer, buffer_len, 0, (struct sockaddr*) &network_address, sizeof(network_address));
+}
diff --git a/Semestr 4/sieci/pracownia2/router/utils.h b/Semestr 4/sieci/pracownia2/router/utils.h
index 3d36aed..63ad6fb 100644
--- a/Semestr 4/sieci/pracownia2/router/utils.h
+++ b/Semestr 4/sieci/pracownia2/router/utils.h
@@ -2,22 +2,35 @@
#define UTILS_H
#define UTILS_H
+#include "config.h"
#include <stdint.h>
#include <time.h>
#include <poll.h>
-#include "router_addr.h"
+#include "network_addr.h"
#define NS_TO_MS(X) ((long)(X) / (long)1000000)
#define S_TO_MS(X) ((long)(X) * (long)1000)
+/* Returns a UDP socket. */
int get_socket();
+/* Binds socket to given port and set the broadcast permission. */
void bind_to_port(int sockfd, uint16_t port);
+/* Computes the time elapsed between start and finish in miliseconds. */
long get_time_interval(struct timespec start, struct timespec finish);
+/* Polls given socket with given timeout and changes the timeout accordingly. */
int poll_socket_modify_timeout(int sockfd, int *timeout);
-void recv_and_print(int sockfd, int networks_number, struct router_addr *networks);
+/* For debug purposes only. Recieves and prints UDP message. */
+void recv_and_print(int sockfd, int networks_number, struct network_addr *networks);
+
+/* Sends message in buffer of length buffer_len to addr through given socket.
+ * IT DOES NOT TERMINATE THE PROGRAM IF SENDTO RETURNS ANY ERRORS!
+ * One must handle the errors on their own.
+ */
+size_t send_message(int sockfd, char *buffer, int buffer_len, struct in_addr addr);
+
#endif \ No newline at end of file
diff --git a/Semestr 4/sieci/pracownia2/router/vector.h b/Semestr 4/sieci/pracownia2/router/vector.h
new file mode 100644
index 0000000..4cd0039
--- /dev/null
+++ b/Semestr 4/sieci/pracownia2/router/vector.h
@@ -0,0 +1 @@
+#ifndef \ No newline at end of file