Apostolos Fanakis
5 years ago
14 changed files with 288 additions and 1861 deletions
@ -1,362 +0,0 @@ |
|||
#include <stdlib.h> |
|||
#include <stdint.h> |
|||
#include <stddef.h> |
|||
#include <assert.h> |
|||
#include <string.h> |
|||
|
|||
#include <stdio.h> |
|||
|
|||
#include "circ_buff.h" |
|||
|
|||
// Defines the circular buffer structure
|
|||
struct circ_buf_t { |
|||
char **buffer; |
|||
size_t head; |
|||
size_t tail; |
|||
size_t max; // of the buffer
|
|||
size_t el_size; |
|||
bool full; |
|||
}; |
|||
|
|||
// Private Functions
|
|||
|
|||
unit_static void advance_pointer(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
if(cbuf->full) { |
|||
cbuf->tail = (cbuf->tail + 1) % cbuf->max; |
|||
} |
|||
|
|||
cbuf->head = (cbuf->head + 1) % cbuf->max; |
|||
|
|||
// We mark full because we will advance tail on the next time around
|
|||
cbuf->full = (cbuf->head == cbuf->tail); |
|||
} |
|||
|
|||
unit_static void retreat_pointer(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
cbuf->full = false; |
|||
cbuf->tail = (cbuf->tail + 1) % cbuf->max; |
|||
} |
|||
|
|||
// APIs
|
|||
|
|||
cbuf_handle_t circ_buf_init(char **buffer, size_t size, size_t element_size) { |
|||
assert(buffer && size); |
|||
|
|||
cbuf_handle_t cbuf = malloc(sizeof(circ_buf_t)); |
|||
assert(cbuf); |
|||
|
|||
cbuf->buffer = buffer; |
|||
cbuf->max = size; |
|||
cbuf->el_size = element_size; |
|||
circ_buf_reset(cbuf); |
|||
|
|||
assert(circ_buf_empty(cbuf)); |
|||
|
|||
return cbuf; |
|||
} |
|||
|
|||
void circ_buf_free(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
free(cbuf); |
|||
} |
|||
|
|||
void circ_buf_reset(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
cbuf->head = 0; |
|||
cbuf->tail = 0; |
|||
cbuf->full = false; |
|||
} |
|||
|
|||
size_t circ_buf_size(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
size_t size = cbuf->max; |
|||
|
|||
if(!cbuf->full) { |
|||
if(cbuf->head >= cbuf->tail) { |
|||
size = (cbuf->head - cbuf->tail); |
|||
} |
|||
else { |
|||
size = (cbuf->max + cbuf->head - cbuf->tail); |
|||
} |
|||
} |
|||
|
|||
return size; |
|||
} |
|||
|
|||
size_t circ_buf_capacity(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
return cbuf->max; |
|||
} |
|||
|
|||
void circ_buf_put(cbuf_handle_t cbuf, const char *data) { |
|||
assert(cbuf && cbuf->buffer); |
|||
|
|||
strcpy(cbuf->buffer[cbuf->head], data); |
|||
|
|||
advance_pointer(cbuf); |
|||
} |
|||
|
|||
void circ_buf_mul_add(cbuf_handle_t cbuf, char **data, uint8_t size, |
|||
int (*compar)(const void *, const void *)) { |
|||
assert(cbuf && data && cbuf->buffer); |
|||
|
|||
qsort(data, size, sizeof(char*), compar); |
|||
|
|||
char *last_element = (char*) malloc(circ_buf_element_size(cbuf) * sizeof(char)); |
|||
for (uint8_t i = 0; i < size; ++i) { |
|||
circ_buf_read(cbuf, 0, last_element); |
|||
|
|||
if (compar(&data[i], &last_element) < 0) { |
|||
continue; |
|||
} |
|||
|
|||
circ_buf_put(cbuf, data[i]); |
|||
} |
|||
|
|||
free(last_element); |
|||
|
|||
int end_buffer_size = circ_buf_size(cbuf); |
|||
char **temp_array = (char **) malloc(end_buffer_size * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < end_buffer_size; ++buff_el) { |
|||
temp_array[buff_el] = (char *) malloc(circ_buf_element_size(cbuf) * sizeof(char)); |
|||
circ_buf_get(cbuf, temp_array[buff_el]); |
|||
} |
|||
|
|||
qsort(temp_array, end_buffer_size, sizeof(char*), compar); |
|||
|
|||
for (uint8_t i = 0; i < end_buffer_size; ++i) { |
|||
circ_buf_put(cbuf, temp_array[i]); |
|||
} |
|||
|
|||
for (uint8_t buff_el = 0; buff_el < end_buffer_size; ++buff_el) { |
|||
free(temp_array[buff_el]); |
|||
} |
|||
free(temp_array); |
|||
} |
|||
|
|||
int circ_buf_get(cbuf_handle_t cbuf, char *data) { |
|||
assert(cbuf && data && cbuf->buffer); |
|||
|
|||
int r = -1; |
|||
|
|||
if(!circ_buf_empty(cbuf)) { |
|||
strcpy(data, cbuf->buffer[cbuf->tail]); |
|||
retreat_pointer(cbuf); |
|||
|
|||
r = 0; |
|||
} |
|||
|
|||
return r; |
|||
} |
|||
|
|||
int circ_buf_read(cbuf_handle_t cbuf, size_t position, char *data) { |
|||
assert(cbuf && data && cbuf->buffer && (position < circ_buf_size(cbuf))); |
|||
|
|||
int r = -1; |
|||
|
|||
if(!circ_buf_empty(cbuf)) { |
|||
strcpy(data, cbuf->buffer[(cbuf->tail + position) % cbuf->max]); |
|||
|
|||
r = 0; |
|||
} |
|||
|
|||
return r; |
|||
} |
|||
|
|||
void diff_bufs(cbuf_handle_t cbuf1, cbuf_handle_t cbuf2, |
|||
char ***add1, char ***add2) { |
|||
assert(cbuf1 && cbuf2 && |
|||
(circ_buf_element_size(cbuf1) == circ_buf_element_size(cbuf2)) && |
|||
(circ_buf_capacity(cbuf1) == circ_buf_capacity(cbuf2))); |
|||
|
|||
// Initializes the diff arrays
|
|||
(*add1) = (char **) malloc(circ_buf_capacity(cbuf2) * sizeof(char *)); |
|||
(*add2) = (char **) malloc(circ_buf_capacity(cbuf1) * sizeof(char *)); |
|||
|
|||
char *curr_str1 = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); |
|||
char *curr_str2 = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); |
|||
/*uint8_t diff_array_index = 0;
|
|||
for (uint8_t i = 0; i < circ_buf_size(cbuf1); ++i) { |
|||
// Reads current element of cbuf1
|
|||
circ_buf_read(cbuf1, i, curr_str1); |
|||
bool element_exists = false; |
|||
|
|||
for (uint8_t j = 0; j < circ_buf_size(cbuf2); ++j) { |
|||
circ_buf_read(cbuf2, j, curr_str2); |
|||
// Checks against cbuf2 elements
|
|||
if (!strcmp(curr_str2, curr_str1)) { |
|||
element_exists = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!element_exists) { |
|||
(*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); |
|||
strcpy((*add2)[diff_array_index], curr_str1); |
|||
++diff_array_index; |
|||
} |
|||
} |
|||
|
|||
(*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); |
|||
strcpy((*add1)[diff_array_index], EOB); |
|||
|
|||
diff_array_index = 0; |
|||
for (uint8_t i = 0; i < circ_buf_size(cbuf2); ++i) { |
|||
// Reads current element of cbuf2
|
|||
circ_buf_read(cbuf2, i, curr_str2); |
|||
bool element_exists = false; |
|||
|
|||
for (uint8_t j = 0; j < circ_buf_size(cbuf1); ++j) { |
|||
circ_buf_read(cbuf1, j, curr_str1); |
|||
// Checks against cbuf1 elements
|
|||
if (!strcmp(curr_str1, curr_str2)) { |
|||
element_exists = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!element_exists) { |
|||
(*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); |
|||
strcpy((*add1)[diff_array_index], curr_str2); |
|||
++diff_array_index; |
|||
} |
|||
} |
|||
|
|||
(*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); |
|||
strcpy((*add2)[diff_array_index], EOB);*/ |
|||
|
|||
|
|||
|
|||
uint8_t cbuf1_idx = 0, cbuf2_idx = 0, add1_arr_idx = 0, add2_arr_idx = 0; |
|||
while ((cbuf1_idx < circ_buf_size(cbuf1)) && |
|||
(cbuf2_idx < circ_buf_size(cbuf2))) { |
|||
circ_buf_read(cbuf1, cbuf1_idx, curr_str1); |
|||
circ_buf_read(cbuf2, cbuf2_idx, curr_str2); |
|||
|
|||
int strcmp_res = strcmp(curr_str1, curr_str2); |
|||
if (!strcmp_res) { |
|||
++cbuf1_idx; |
|||
++cbuf2_idx; |
|||
} else { // TODO: change the inner comparisons (strtok etc)
|
|||
if (strcmp_res < 0) { |
|||
(*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); |
|||
strcpy((*add2)[add2_arr_idx], curr_str1); |
|||
++add2_arr_idx; |
|||
++cbuf1_idx; |
|||
} |
|||
else if (strcmp_res > 0) { |
|||
(*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); |
|||
strcpy((*add1)[add1_arr_idx], curr_str2); |
|||
++add1_arr_idx; |
|||
++cbuf2_idx; |
|||
} |
|||
} |
|||
} |
|||
|
|||
while (cbuf1_idx < circ_buf_size(cbuf1)) { |
|||
(*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); |
|||
circ_buf_read(cbuf1, cbuf1_idx, curr_str1); |
|||
strcpy((*add2)[add2_arr_idx], curr_str1); |
|||
++add2_arr_idx; |
|||
++cbuf1_idx; |
|||
} |
|||
|
|||
while (cbuf2_idx < circ_buf_size(cbuf2)) { |
|||
(*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); |
|||
circ_buf_read(cbuf2, cbuf2_idx, curr_str2); |
|||
strcpy((*add1)[add1_arr_idx], curr_str2); |
|||
++add1_arr_idx; |
|||
++cbuf2_idx; |
|||
} |
|||
|
|||
(*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); |
|||
strcpy((*add1)[add1_arr_idx], EOB); |
|||
|
|||
(*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); |
|||
strcpy((*add2)[add2_arr_idx], EOB); |
|||
|
|||
free(curr_str1); |
|||
free(curr_str2); |
|||
|
|||
/*uint8_t i = 0;
|
|||
printf("add1:\n"); |
|||
while (strcmp((*add1)[i], EOB)) { |
|||
printf("%s\n", (*add1)[i]); |
|||
++i; |
|||
} |
|||
|
|||
i = 0; |
|||
printf("add2:\n"); |
|||
while (strcmp((*add2)[i], EOB)) { |
|||
printf("%s\n", (*add2)[i]); |
|||
++i; |
|||
}*/ |
|||
} |
|||
|
|||
int circ_buf_serialize(cbuf_handle_t cbuf, char **serialized) { |
|||
char *temp = (char*) malloc(circ_buf_element_size(cbuf) * sizeof(char)); |
|||
const char separator[2] = "\r"; |
|||
uint8_t char_sum = circ_buf_size(cbuf) - 1; |
|||
uint8_t i; |
|||
|
|||
for (i = 0; i < circ_buf_size(cbuf); ++i) { |
|||
circ_buf_read(cbuf, i, temp); |
|||
char_sum += strlen(temp); |
|||
} |
|||
|
|||
(*serialized) = (char*) malloc((char_sum + 1) * sizeof(char)); |
|||
strcpy((*serialized), ""); |
|||
|
|||
for (i = 0; i < circ_buf_size(cbuf) - 1; ++i) { |
|||
circ_buf_read(cbuf, i, temp); |
|||
strcat((*serialized), temp); |
|||
strcat((*serialized), separator); |
|||
} |
|||
|
|||
circ_buf_read(cbuf, i, temp); |
|||
strcat((*serialized), temp); |
|||
|
|||
free(temp); |
|||
|
|||
return strlen((*serialized)); |
|||
} |
|||
|
|||
int circ_buf_deserialize(cbuf_handle_t cbuf, const char *serialized) { |
|||
char *str = calloc(strlen(serialized) + 1, sizeof(char)); |
|||
strcpy(str, serialized); |
|||
const char separator[2] = "\r"; |
|||
char *token; |
|||
|
|||
token = strtok(str, separator); |
|||
|
|||
while (token != NULL) { |
|||
circ_buf_put(cbuf, token); |
|||
token = strtok(NULL, separator); |
|||
} |
|||
|
|||
return circ_buf_size(cbuf); |
|||
} |
|||
|
|||
bool circ_buf_empty(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
return (!cbuf->full && (cbuf->head == cbuf->tail)); |
|||
} |
|||
|
|||
bool circ_buf_full(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
return cbuf->full; |
|||
} |
|||
|
|||
size_t circ_buf_element_size(cbuf_handle_t cbuf) { |
|||
assert(cbuf); |
|||
|
|||
return cbuf->el_size; |
|||
} |
@ -1,80 +0,0 @@ |
|||
/*
|
|||
* Implementation of a simple circular buffer data structure. |
|||
* Based on the example and guide found here: |
|||
* https://embeddedartistry.com/blog/2017/4/6/circular-buffers-in-cc
|
|||
*/ |
|||
#ifndef CIRC_BUFF_H_ |
|||
#define CIRC_BUFF_H_ |
|||
|
|||
#include <stdbool.h> |
|||
|
|||
#define EOB "-1" |
|||
|
|||
// Circular buffer structure
|
|||
typedef struct circ_buf_t circ_buf_t; |
|||
// and handle type
|
|||
typedef circ_buf_t *cbuf_handle_t; |
|||
|
|||
#ifdef TEST //This is a test build
|
|||
// Makes private functions reachable by the tester
|
|||
#define unit_static |
|||
unit_static void advance_pointer(cbuf_handle_t cbuf); |
|||
unit_static void retreat_pointer(cbuf_handle_t cbuf); |
|||
#else |
|||
#define unit_static static |
|||
#endif |
|||
|
|||
// Initializes a circular buffer structure and returns the circular buffer handle.
|
|||
// Pass in a storage buffer and size.
|
|||
cbuf_handle_t circ_buf_init(char **buffer, size_t size, size_t element_size); |
|||
|
|||
// Frees a circular buffer structure. Does not free data buffer!
|
|||
void circ_buf_free(cbuf_handle_t cbuf); |
|||
|
|||
// Resets the circular buffer to empty, head == tail. Data not cleared!
|
|||
void circ_buf_reset(cbuf_handle_t cbuf); |
|||
|
|||
// Adds data to the end of the buffer, even if the buffer is full. Old data is overwritten.
|
|||
void circ_buf_put(cbuf_handle_t cbuf, const char *data); |
|||
|
|||
// Adds multiple entries to the buffer, keeping the data in ascending order according to the
|
|||
// function compar provided in the parameters. If the buffer is full, smallest data are overwritten.
|
|||
// Doesn't check for duplicates!
|
|||
void circ_buf_mul_add(cbuf_handle_t cbuf, char **data, uint8_t size, |
|||
int (*compar)(const void *, const void *)); |
|||
|
|||
// Retrieves a value from the buffer.
|
|||
int circ_buf_get(cbuf_handle_t cbuf, char *data); |
|||
|
|||
// Reads a value from the buffer. Does NOT retrieve, size is not reduced!
|
|||
int circ_buf_read(cbuf_handle_t cbuf, size_t position, char *data); |
|||
|
|||
// Compares the buffers cbuf1 and cbuf2. Elements present on cbuf1 that do not
|
|||
// exist on cbuf2 are added to the array add2, elements present on cbuf2 that do
|
|||
// not exist on cbuf1 are added to the array add1.
|
|||
// Both buffers must be ordered on the same way!
|
|||
void diff_bufs(cbuf_handle_t cbuf1, cbuf_handle_t cbuf2, |
|||
char ***add1, char ***add2); |
|||
|
|||
// Serializes the whole buffer to a single string
|
|||
int circ_buf_serialize(cbuf_handle_t cbuf, char **serialized); |
|||
|
|||
// De-serializes a string to a buffer
|
|||
int circ_buf_deserialize(cbuf_handle_t cbuf, const char *serialized); |
|||
|
|||
// Checks if the buffer is empty.
|
|||
bool circ_buf_empty(cbuf_handle_t cbuf); |
|||
|
|||
// Checks if the buffer is full.
|
|||
bool circ_buf_full(cbuf_handle_t cbuf); |
|||
|
|||
// Returns the capacity of the buffer.
|
|||
size_t circ_buf_capacity(cbuf_handle_t cbuf); |
|||
|
|||
// Returns the number of elements stored in the buffer.
|
|||
size_t circ_buf_size(cbuf_handle_t cbuf); |
|||
|
|||
// Returns the size of each element.
|
|||
size_t circ_buf_element_size(cbuf_handle_t cbuf); |
|||
|
|||
#endif //CIRC_BUFF_H_
|
@ -1,353 +0,0 @@ |
|||
#include "helpers.h" |
|||
|
|||
/*
|
|||
* Function based on this example: |
|||
* http://man7.org/linux/man-pages/man3/getifaddrs.3.html#EXAMPLE
|
|||
*/ |
|||
int get_own_id(void) { |
|||
int id = -1; |
|||
struct ifaddrs *ifaddr, *ifa; |
|||
int family, s, n; |
|||
char host[NI_MAXHOST]; |
|||
|
|||
if (getifaddrs(&ifaddr) == -1) { |
|||
perror("Couldn't get network interfaces."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Walks through linked list, maintaining head pointer so we can free list later
|
|||
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { |
|||
if (ifa->ifa_addr == NULL) { |
|||
continue; |
|||
} |
|||
|
|||
family = ifa->ifa_addr->sa_family; |
|||
|
|||
// Gets the address of an AF_INET* interface address
|
|||
if (family == AF_INET || family == AF_INET6) { |
|||
s = getnameinfo(ifa->ifa_addr, |
|||
(family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), |
|||
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); |
|||
if (s != 0) { |
|||
printf("getnameinfo() failed: %s\n", gai_strerror(s)); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
id = extract_id_from_ip(host); |
|||
if (id < 0) { |
|||
continue; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
} |
|||
|
|||
freeifaddrs(ifaddr); |
|||
|
|||
return(id); |
|||
} |
|||
|
|||
int extract_id_from_ip(const char *ip) { |
|||
const char separator[2] = "."; |
|||
int id = 0; |
|||
char *rest, *token, *ip_cp; |
|||
|
|||
ip_cp = malloc(strlen(ip) * sizeof(char)); |
|||
strcpy(ip_cp, ip); |
|||
|
|||
rest = ip_cp; |
|||
token = strtok_r(rest, separator, &rest); |
|||
if (!token || atoi(token) != 10) { |
|||
return -1; |
|||
} |
|||
|
|||
token = strtok_r(rest, separator, &rest); |
|||
if (!token || atoi(token) != 0) { |
|||
return -1; |
|||
} |
|||
|
|||
token = strtok_r(rest, separator, &rest); |
|||
if (!token) { |
|||
return -1; |
|||
} |
|||
id = atoi(token) * 100; |
|||
|
|||
token = strtok_r(rest, separator, &rest); |
|||
if (!token) { |
|||
return -1; |
|||
} |
|||
id += atoi(token); |
|||
|
|||
return id; |
|||
} |
|||
|
|||
void set_timer_and_handler(void (*handler)(int), long int timer_interval) { |
|||
struct itimerval interval_timer; |
|||
struct sigaction signal_action; |
|||
|
|||
// Installs handler as the signal handler for SIGALRM
|
|||
memset(&signal_action, 0, sizeof(signal_action)); |
|||
signal_action.sa_handler = handler; |
|||
if (sigaction(SIGALRM, &signal_action, NULL)) { |
|||
perror("Couldn't install function handler for SIGALRM signals."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Sets an interval timer to deliver a SIGALRM signal every timer_interval seconds
|
|||
interval_timer.it_interval.tv_usec = 0; |
|||
interval_timer.it_interval.tv_sec = timer_interval; |
|||
interval_timer.it_value.tv_usec = 0; |
|||
interval_timer.it_value.tv_sec = timer_interval; |
|||
|
|||
if (setitimer(ITIMER_REAL, &interval_timer, NULL) == -1) { |
|||
perror("Couldn't set timer."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
void enable_echo_broadcast(void) { |
|||
if (system("echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts") < 0) { |
|||
perror("Couldn't allow echo broadcasts."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Function based on this snippet: |
|||
* https://codereview.stackexchange.com/a/58107
|
|||
*/ |
|||
void search_for_neighbors(node_handle_t **neighbors, uint16_t *num_neighbors, uint16_t port) { |
|||
// Broadcasts ping
|
|||
if (system("ping -b 10.255.255.255 -c 3 > /dev/null") < 0) { |
|||
perror("Couldn't broadcast echo."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Reads the ARP file checking for connected devices
|
|||
FILE *arpCache = fopen(ARP_CACHE, "r"); |
|||
if (!arpCache) { |
|||
perror("ARP Cache: Failed to open file \"" ARP_CACHE "\""); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Ignores the first line, which contains the header
|
|||
char header[ARP_BUFFER_LEN]; |
|||
if (!fgets(header, sizeof(header), arpCache)) { |
|||
perror("Couldn't read ARP file header."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Extracts IP addresses found in the file
|
|||
char ipAddr[ARP_BUFFER_LEN]; |
|||
char **neighbors_ips = (char **) malloc(sizeof(char *)); |
|||
if (!neighbors_ips) { |
|||
perror("Unable to allocate memory for neighbor IP."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
int count = 0; |
|||
while (1 == fscanf(arpCache, ARP_LINE_FORMAT, ipAddr)) { |
|||
++count; |
|||
if (count > 1) { |
|||
char **r_neighbors_ips = realloc(neighbors_ips, count * sizeof(char *)); |
|||
if (!r_neighbors_ips) { |
|||
free(r_neighbors_ips); |
|||
perror("Unable to reallocate memory for neighbor IP."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
neighbors_ips = r_neighbors_ips; |
|||
} |
|||
|
|||
neighbors_ips[count - 1] = (char *) malloc(ARP_BUFFER_LEN * sizeof(char)); |
|||
strcpy(neighbors_ips[count - 1], ipAddr); |
|||
} |
|||
|
|||
// Allocates memory for the new neighbors structs
|
|||
if (!(*num_neighbors)) { |
|||
// Neighbors array came empty
|
|||
(*neighbors) = (node_handle_t *) malloc(count * sizeof(node_handle_t)); |
|||
if (!neighbors_ips) { |
|||
perror("Unable to allocate memory for nodes."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
} else { |
|||
node_handle_t *r_neighbors = realloc((*neighbors), count * sizeof(node_handle_t)); |
|||
if (!r_neighbors) { |
|||
free(r_neighbors); |
|||
perror("Unable to reallocate memory for nodes."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
(*neighbors) = r_neighbors; |
|||
} |
|||
|
|||
// Adds new event timestamps to neighbors structs
|
|||
for (uint8_t i = 0; i < count; ++i) { |
|||
bool found_flag = false; |
|||
|
|||
for (uint8_t j = 0; j < (*num_neighbors); ++j) { |
|||
if (!strcmp(inet_ntoa(node_get_addr((*neighbors)[j]).sin_addr), |
|||
neighbors_ips[i])) { |
|||
bool node_alive = check_node_alive(neighbors_ips[i]); |
|||
node_add_timestamp((*neighbors)[i], time(NULL), node_alive); |
|||
|
|||
found_flag = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!found_flag) { |
|||
// New node found!
|
|||
printf("Adding %s\n", neighbors_ips[i]); |
|||
struct sockaddr_in peer_name; |
|||
init_sockaddr(&peer_name, neighbors_ips[i], port); |
|||
(*neighbors)[(*num_neighbors)++] = node_init(peer_name); |
|||
} |
|||
} |
|||
|
|||
if (!((*num_neighbors) == count)) { |
|||
(*num_neighbors) = count; |
|||
} |
|||
|
|||
fclose(arpCache); |
|||
} |
|||
|
|||
void create_message(node_handle_t *neighbors, char *new_message, int own_id, |
|||
uint8_t num_neighbors, uint16_t max_message_length) { |
|||
node_handle_t random_node = neighbors[rand() % (num_neighbors)]; |
|||
|
|||
int peer_id = extract_id_from_ip(inet_ntoa((node_get_addr(random_node)).sin_addr)); |
|||
if (peer_id < 0) { |
|||
perror("Couldn't extract own ID."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
snprintf(new_message, max_message_length, "%04d_%04d_%ld_%s", own_id, peer_id, time(NULL), |
|||
"It's amazing... It's fantastic!"); |
|||
} |
|||
|
|||
bool check_node_alive(const char *ipv4) { |
|||
char command[64]; |
|||
|
|||
snprintf(command, 64, "ping %s -c 1 -W 1 | grep \"1 received\" > /dev/null", ipv4); |
|||
|
|||
int call_res = system(command); |
|||
if (call_res < 0) { |
|||
perror("Couldn't ping node."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
return call_res == 0; |
|||
} |
|||
|
|||
/*
|
|||
* Function based on this example: |
|||
* https://www.gnu.org/software/libc/manual/html_node/Inet-Example.html#Inet-Example
|
|||
*/ |
|||
int create_socket_and_listen(uint16_t port, uint8_t backlog_size) { |
|||
int in_sock; |
|||
struct sockaddr_in own_name; |
|||
|
|||
// Creates the socket
|
|||
in_sock = socket(PF_INET, SOCK_STREAM, 0); |
|||
if (in_sock < 0) { |
|||
perror("Couldn't create the socket."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Gives the socket a name
|
|||
own_name.sin_family = AF_INET; |
|||
own_name.sin_port = htons(port); |
|||
own_name.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
// Binds own address structure to socket
|
|||
if (bind(in_sock, (struct sockaddr *) &own_name, sizeof(own_name)) < 0) { |
|||
perror("Couldn't bind the address structure to the socket."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
if (listen(in_sock, backlog_size) < 0) { |
|||
perror("Couldn't listen for connections on the socket."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
return in_sock; |
|||
} |
|||
|
|||
void send_message(struct sockaddr_in peer_name, const char *message) { |
|||
int out_sock; |
|||
|
|||
// Creates the socket
|
|||
out_sock = socket(PF_INET, SOCK_STREAM, 0); |
|||
if (out_sock < 0) { |
|||
perror("Couldn't create the socket."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Connects to the peer
|
|||
if (connect(out_sock, (struct sockaddr *) &peer_name, sizeof(peer_name))) { |
|||
printf("Couldn't connect to the peer.\n"); |
|||
} else { |
|||
// Sends data to the peer
|
|||
write_to_peer(out_sock, message); |
|||
} |
|||
|
|||
close(out_sock); |
|||
} |
|||
|
|||
void accept_connection(int sock, struct sockaddr_in *peer_name, fd_set *active_fd_set) { |
|||
size_t peer_name_size = sizeof((*peer_name)); |
|||
int comm_socket = accept(sock, (struct sockaddr *) peer_name, &peer_name_size); |
|||
if (comm_socket < 0) { |
|||
perror("Couldn't accept the connection."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
fprintf(stderr, "Connected to host %s, port %hd.\n", |
|||
inet_ntoa((*peer_name).sin_addr), ntohs((*peer_name).sin_port)); |
|||
FD_SET(comm_socket, active_fd_set); |
|||
} |
|||
|
|||
void write_to_peer(int file_desc, const char *message) { |
|||
int num_bytes = write(file_desc, message, strlen(message) + 1); |
|||
if (num_bytes < 0) { |
|||
perror("Couldn't write to peer."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
int read_from_peer(int file_des, uint16_t max_line) { |
|||
char buffer[max_line]; |
|||
int num_bytes; |
|||
|
|||
num_bytes = read(file_des, buffer, sizeof(buffer)); |
|||
if (num_bytes < 0) { |
|||
perror("Couldn't read from peer."); |
|||
exit(EXIT_FAILURE); |
|||
} else if (num_bytes == 0) |
|||
// End-of-file
|
|||
return -1; |
|||
else { |
|||
fprintf(stderr, "Got message: `%s'\n", buffer); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Function based on this example: |
|||
* https://www.gnu.org/software/libc/manual/html_node/Inet-Example.html#Inet-Example
|
|||
*/ |
|||
void init_sockaddr(struct sockaddr_in *peer_name, const char *ipv4, uint16_t port) { |
|||
struct hostent *hostinfo; |
|||
|
|||
peer_name->sin_family = AF_INET; |
|||
peer_name->sin_port = htons(port); |
|||
hostinfo = gethostbyname(ipv4); |
|||
if (hostinfo == NULL) { |
|||
fprintf(stderr, "Unknown host %s.\n", ipv4); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
peer_name->sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; |
|||
} |
@ -1,65 +0,0 @@ |
|||
#ifndef HELPERS_H_ |
|||
#define HELPERS_H_ |
|||
|
|||
#define _GNU_SOURCE |
|||
|
|||
#include <stdio.h> |
|||
#include <errno.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <netdb.h> |
|||
#include <arpa/inet.h> |
|||
#include <sys/select.h> |
|||
#include <ifaddrs.h> |
|||
#include <linux/if_link.h> |
|||
#include <sys/time.h> |
|||
#include <signal.h> |
|||
#include <string.h> |
|||
#include <sys/wait.h> |
|||
|
|||
#include "node.h" |
|||
|
|||
// Macros to turn a numeric macro into a string literal
|
|||
#define xstr(s) str(s) |
|||
#define str(s) #s |
|||
|
|||
// Neighbor discovery related definitions
|
|||
#define ARP_CACHE "/proc/net/arp" |
|||
#define ARP_STRING_LEN 1023 |
|||
#define ARP_BUFFER_LEN (ARP_STRING_LEN + 1) |
|||
#define PING_BUFFER_LEN 1024 |
|||
|
|||
// Format for fscanf() to read the 1st field of ARP
|
|||
#define ARP_LINE_FORMAT "%" xstr(ARP_STRING_LEN) "s %*s %*s %*s %*s %*s" |
|||
|
|||
int get_own_id(void); |
|||
|
|||
int extract_id_from_ip(const char *ip); |
|||
|
|||
void set_timer_and_handler(void (*handler)(int), long int timer_interval); |
|||
|
|||
void enable_echo_broadcast(void); |
|||
|
|||
void search_for_neighbors(node_handle_t **neighbors, uint16_t *num_neighbors, uint16_t port); |
|||
|
|||
void create_message(node_handle_t *neighbors, char *new_message, int own_id, |
|||
uint8_t num_neighbors, uint16_t max_message_length); |
|||
|
|||
bool check_node_alive(const char *ipv4); |
|||
|
|||
int create_socket_and_listen(uint16_t port, uint8_t backlog_size); |
|||
|
|||
void send_message(struct sockaddr_in peer_name, const char *message); |
|||
|
|||
void accept_connection(int sock, struct sockaddr_in *client_name, fd_set *active_fd_set); |
|||
|
|||
void write_to_peer(int filedes, const char *message); |
|||
|
|||
int read_from_peer(int file_des, uint16_t max_line); |
|||
|
|||
void init_sockaddr(struct sockaddr_in *name, const char *hostname, uint16_t port); |
|||
|
|||
#endif //HELPERS_H_
|
@ -0,0 +1,132 @@ |
|||
#include <stdlib.h> |
|||
#include <assert.h> |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
#include "message.h" |
|||
|
|||
/* Private functions */ |
|||
|
|||
// Defines the node structure
|
|||
struct message_t { |
|||
char *message; |
|||
uint16_t received_from, *sent_to; |
|||
observer_func *observers; |
|||
int message_length, num_sent_to, num_observers; |
|||
}; |
|||
|
|||
unit_static void message_state_changed(message_handle_t message_handle) { |
|||
assert(message_handle); |
|||
|
|||
for (uint16_t i = 0; i < message_handle->num_observers; ++i) { |
|||
(message_handle->observers[i])(); |
|||
} |
|||
} |
|||
|
|||
/* API */ |
|||
|
|||
message_handle_t message_init(const char *message, int message_length, uint16_t received_from) { |
|||
//assert(addr);
|
|||
assert(message_length <= MAX_MESSAGE_LENGTH); |
|||
|
|||
message_handle_t message_handle = malloc(sizeof(message_t)); |
|||
assert(message_handle); |
|||
|
|||
message_handle->message = malloc((message_length + 1) * sizeof(char)); |
|||
strcpy(message_handle->message, message); |
|||
message_handle->message_length = message_length; |
|||
|
|||
message_handle->received_from = received_from; |
|||
|
|||
message_handle->sent_to = NULL; |
|||
message_handle->num_sent_to = 0; |
|||
|
|||
message_handle->observers = NULL; |
|||
message_handle->num_observers = 0; |
|||
|
|||
return message_handle; |
|||
} |
|||
|
|||
void message_free(message_handle_t message_handle) { |
|||
assert(message_handle); |
|||
|
|||
free(message_handle->sent_to); |
|||
free(message_handle->observers); |
|||
free(message_handle->message); |
|||
free(message_handle); |
|||
} |
|||
|
|||
void message_add_sent_to(message_handle_t message_handle, uint16_t sent_to) { |
|||
assert(message_handle); |
|||
|
|||
if (message_handle->sent_to == NULL) { |
|||
message_handle->sent_to = (uint16_t *) malloc(sizeof(uint16_t)); |
|||
if (!message_handle->sent_to) { |
|||
perror("Unable to allocate memory for message receivers."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
++(message_handle->num_sent_to); |
|||
} else { |
|||
uint16_t *r_sent_to = realloc(message_handle->sent_to, ++(message_handle->num_sent_to) * sizeof(uint16_t)); |
|||
if (!r_sent_to) { |
|||
free(r_sent_to); |
|||
perror("Unable to reallocate memory for message receivers."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
message_handle->sent_to = r_sent_to; |
|||
} |
|||
|
|||
message_handle->sent_to[message_handle->num_sent_to - 1] = sent_to; |
|||
message_state_changed(message_handle); |
|||
} |
|||
|
|||
char *message_get(message_handle_t message_handle, int *message_length) { |
|||
assert(message_handle); |
|||
|
|||
char *message = (char *) malloc((message_handle->message_length + 1) * sizeof(char)); |
|||
if (!message) { |
|||
perror("Unable to allocate memory for message return."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
strcpy(message, message_handle->message); |
|||
(*message_length) = message_handle->message_length; |
|||
|
|||
return message; |
|||
} |
|||
|
|||
bool message_sent_to(message_handle_t message_handle, uint16_t node) { |
|||
assert(message_handle); |
|||
|
|||
for (uint16_t i = 0; i < message_handle->num_sent_to; ++i) { |
|||
if (message_handle->sent_to[i] == node) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void message_attach_observer(message_handle_t message_handle, observer_func observer) { |
|||
assert(message_handle); |
|||
|
|||
if (message_handle->observers == NULL) { |
|||
message_handle->observers = (observer_func *) malloc(sizeof(observer_func)); |
|||
if (!message_handle->observers) { |
|||
perror("Unable to allocate memory for message observers."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
++(message_handle->num_observers); |
|||
} else { |
|||
uint16_t *r_observers = realloc(message_handle->observers, |
|||
++(message_handle->num_observers) * sizeof(observer_func)); |
|||
if (!r_observers) { |
|||
free(r_observers); |
|||
perror("Unable to reallocate memory for message observers."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
message_handle->observers[message_handle->num_observers - 1] = observer; |
|||
} |
@ -0,0 +1,44 @@ |
|||
#ifndef MESSAGE_H_ |
|||
#define MESSAGE_H_ |
|||
|
|||
#include <stdbool.h> |
|||
#include <stdint.h> |
|||
|
|||
#define MAX_MESSAGE_LENGTH 277 |
|||
|
|||
// Message structure
|
|||
typedef struct message_t message_t; |
|||
// and handle type
|
|||
typedef message_t *message_handle_t; |
|||
|
|||
typedef void (*observer_func)(void); |
|||
|
|||
#ifdef TEST //This is a test build
|
|||
// Makes private functions reachable by the tester
|
|||
#define unit_static |
|||
// Calls all observer functions attached to this message.
|
|||
unit_static void message_state_changed(message_handle_t message_handle); |
|||
#else |
|||
#define unit_static static |
|||
#endif |
|||
|
|||
// Initializes a message structure and returns the message handle. User must provide the length of
|
|||
// the message without the null termination character (strlen);
|
|||
message_handle_t message_init(const char *message, int message_length, uint16_t received_from); |
|||
|
|||
// Frees a message structure.
|
|||
void message_free(message_handle_t message_handle); |
|||
|
|||
// Adds an new receiver to the message.
|
|||
void message_add_sent_to(message_handle_t message_handle, uint16_t sent_to); |
|||
|
|||
// Returns the message.
|
|||
char *message_get(message_handle_t message_handle, int *message_length); |
|||
|
|||
// Returns true if the message has been previously sent to this node, false otherwise.
|
|||
bool message_sent_to(message_handle_t message_handle, uint16_t node); |
|||
|
|||
// Attaches an observer function to the message.
|
|||
void message_attach_observer(message_handle_t message_handle, observer_func observer); |
|||
|
|||
#endif //MESSAGE_H_
|
@ -1,124 +0,0 @@ |
|||
#include <stdlib.h> |
|||
#include <assert.h> |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
#include "node.h" |
|||
|
|||
// Defines the node structure
|
|||
struct node_t { |
|||
struct sockaddr_in addr; |
|||
uint64_t **events; |
|||
uint64_t appearance_duration; |
|||
uint8_t events_size; |
|||
node_status _node_status; |
|||
}; |
|||
|
|||
node_handle_t node_init(struct sockaddr_in addr) { |
|||
//assert(addr);
|
|||
|
|||
node_handle_t node = malloc(sizeof(node_t)); |
|||
assert(node); |
|||
|
|||
node->addr = addr; |
|||
node->events_size = 0; |
|||
node->events = (uint64_t **) malloc(2 * sizeof(uint64_t)); |
|||
node->events[0] = (uint64_t *) malloc(sizeof(uint64_t)); |
|||
node->events[1] = (uint64_t *) malloc(sizeof(uint64_t)); |
|||
node->events[0][0] = 0; |
|||
node->events[1][0] = 0; |
|||
node->appearance_duration = 0; |
|||
node->_node_status = NODE_INITIALIAZED; |
|||
|
|||
return node; |
|||
} |
|||
|
|||
void node_free(node_handle_t node) { |
|||
assert(node); |
|||
|
|||
free(node->events[0]); |
|||
free(node->events[1]); |
|||
free(node->events); |
|||
free(node); |
|||
} |
|||
|
|||
void node_add_timestamp(node_handle_t node, time_t timestamp, bool visible) { |
|||
assert(node && timestamp); |
|||
|
|||
if ((visible && !node->events[1][node->events_size - 1]) || |
|||
(!visible && node->events[1][node->events_size - 1])) { |
|||
return; |
|||
} |
|||
|
|||
if (visible) { |
|||
int *realloc_r = realloc(node->events[0], node->events_size + 1); |
|||
if (!realloc_r) { |
|||
node_free(node); |
|||
perror("Error trying to reallocate memory for event timestamps!"); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
realloc_r = realloc(node->events[1], node->events_size + 1); |
|||
if (!realloc_r) { |
|||
node_free(node); |
|||
perror("Error trying to reallocate memory for event timestamps!"); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
node->events[0][node->events_size] = timestamp; |
|||
node->events[1][node->events_size] = 0; |
|||
node->_node_status = NODE_PRESENT; |
|||
++node->events_size; |
|||
} else { |
|||
node->events[1][node->events_size - 1] = timestamp; |
|||
node->_node_status = NODE_GONE; |
|||
node->appearance_duration += node->events[1][node->events_size - 1] - |
|||
node->events[0][node->events_size - 1]; |
|||
} |
|||
} |
|||
|
|||
struct sockaddr_in node_get_addr(node_handle_t node) { |
|||
assert(node); |
|||
|
|||
return node->addr; |
|||
} |
|||
|
|||
enum node_status node_get_status(node_handle_t node) { |
|||
assert(node); |
|||
|
|||
return node->_node_status; |
|||
} |
|||
|
|||
uint8_t node_get_latest_appearance_duration(node_handle_t node) { |
|||
assert(node); |
|||
|
|||
if (node->_node_status == NODE_INITIALIAZED) { |
|||
return 0; |
|||
} else if (node->events[1][node->events_size - 1] == 0) { |
|||
return (uint64_t)time(NULL) - node->events[0][node->events_size - 1]; |
|||
} else { |
|||
return node->events[1][node->events_size - 1] - node->events[0][node->events_size - 1]; |
|||
} |
|||
} |
|||
|
|||
uint8_t node_get_total_appearance_duration(node_handle_t node) { |
|||
assert(node); |
|||
|
|||
return node->appearance_duration; |
|||
} |
|||
|
|||
uint8_t node_get_event_table(node_handle_t node, time_t ***event_table) { |
|||
assert(node && event_table); |
|||
|
|||
if (node->events_size < 1) { |
|||
return 0; |
|||
} |
|||
|
|||
(*event_table) = (time_t **) malloc(2 * sizeof(time_t *)); |
|||
(*event_table)[0] = (time_t *) malloc(node->events_size * sizeof(time_t)); |
|||
(*event_table)[1] = (time_t *) malloc(node->events_size * sizeof(time_t)); |
|||
|
|||
memcpy((*event_table)[0], node->events[0], node->events_size * sizeof(time_t)); |
|||
memcpy((*event_table)[1], node->events[1], node->events_size * sizeof(time_t)); |
|||
|
|||
return node->events_size; |
|||
} |
@ -1,59 +0,0 @@ |
|||
#ifndef NODE_H_ |
|||
#define NODE_H_ |
|||
|
|||
#include <stdbool.h> |
|||
#include <time.h> |
|||
#include <arpa/inet.h> |
|||
|
|||
// Node structure
|
|||
typedef struct node_t node_t; |
|||
// and handle type
|
|||
typedef node_t *node_handle_t; |
|||
|
|||
typedef enum node_status { NODE_INITIALIAZED, NODE_PRESENT, NODE_GONE } node_status; |
|||
|
|||
#ifdef TEST //This is a test build
|
|||
// Makes private functions reachable by the tester
|
|||
#define unit_static |
|||
#else |
|||
#define unit_static static |
|||
#endif |
|||
|
|||
// Initializes a node structure and returns the node handle.
|
|||
node_handle_t node_init(struct sockaddr_in addr); |
|||
|
|||
// Frees a node structure.
|
|||
void node_free(node_handle_t node); |
|||
|
|||
// Adds an event timestamp to the node. Either the (re)appearance or the disappearance of the node.
|
|||
void node_add_timestamp(node_handle_t node, time_t timestamp, bool visible); |
|||
|
|||
// Returns the address of the node
|
|||
struct sockaddr_in node_get_addr(node_handle_t node); |
|||
|
|||
node_status node_get_status(node_handle_t node); |
|||
|
|||
//uint8_t node_get_appear_count(node_handle_t node);
|
|||
|
|||
//uint8_t node_get_disappear_count(node_handle_t node);
|
|||
|
|||
//void node_get_latest_appear(node_handle_t node, );
|
|||
|
|||
//void node_get_latest_disappear(node_handle_t node, );
|
|||
|
|||
// Returns the duration (in seconds) of the latest stretch of time that this node has been visible.
|
|||
uint8_t node_get_latest_appearance_duration(node_handle_t node); |
|||
|
|||
// Returns the total duration (in seconds) of time that this node was visible.
|
|||
uint8_t node_get_total_appearance_duration(node_handle_t node); |
|||
|
|||
// Returns the event timestamps table for this node.
|
|||
uint8_t node_get_event_table(node_handle_t node, time_t ***event_table); |
|||
|
|||
// Serializes the whole node to a single string
|
|||
//int circ_buf_serialize(node_handle_t node, char **serialized);
|
|||
|
|||
// De-serializes a string to a node
|
|||
//int circ_buf_deserialize(node_handle_t node, const char *serialized);
|
|||
|
|||
#endif //NODE_H_
|
@ -1,95 +0,0 @@ |
|||
#include "zaqar.h" |
|||
|
|||
#define MESSAGE "You got mail!!! xo xo xo" |
|||
|
|||
volatile sig_atomic_t sigalrm_flag = false; |
|||
|
|||
int main(void) { |
|||
int in_sock, own_id; |
|||
fd_set active_fd_set, read_fd_set; |
|||
struct sockaddr_in peer_name; |
|||
node_handle_t *neighbors; |
|||
uint16_t num_neighbors = 0; |
|||
|
|||
own_id = get_own_id(); |
|||
if (own_id < 0) { |
|||
perror("Couldn't extract own ID."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Enables echo broadcast pings
|
|||
enable_echo_broadcast(); |
|||
|
|||
// Searches network for neighbors
|
|||
search_for_neighbors(&neighbors, &num_neighbors, PORT); |
|||
|
|||
// Sets a timer and handler to produce interrupts for sending messages
|
|||
set_timer_and_handler(handle_alarm, TIMER_INTERVAL); |
|||
|
|||
// Creates a socket and sets it up to accept connections
|
|||
in_sock = create_socket_and_listen(PORT, BACKLOG_SIZE); |
|||
|
|||
// Initializes the set of active sockets
|
|||
// Clears the descriptor set
|
|||
FD_ZERO(&active_fd_set); |
|||
// Sets socket in active readset
|
|||
FD_SET(in_sock, &active_fd_set); |
|||
|
|||
while (1) { |
|||
if (sigalrm_flag) { |
|||
// It's time to send a message!
|
|||
char new_message[MAX_MESSAGE_LENGTH]; |
|||
|
|||
search_for_neighbors(&neighbors, &num_neighbors, PORT); |
|||
create_message(neighbors, new_message, own_id, num_neighbors, MAX_MESSAGE_LENGTH); |
|||
|
|||
for (uint8_t i = 0; i < num_neighbors; ++i) { |
|||
if (node_get_status(neighbors[i]) == NODE_PRESENT) { |
|||
send_message(node_get_addr(neighbors[i]), new_message); |
|||
} |
|||
} |
|||
|
|||
sigalrm_flag = false; |
|||
} |
|||
|
|||
// Shallow copies the readset
|
|||
read_fd_set = active_fd_set; |
|||
|
|||
// Blocks until input arrives on one or more active sockets
|
|||
if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) { |
|||
// Handles the wake-up from alarm signal interrupts
|
|||
if (sigalrm_flag) { |
|||
continue; |
|||
} |
|||
|
|||
perror("Couldn't initiate synchronous I/O multiplexing."); |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
// Services all the sockets with input pending
|
|||
for (int i = 0; i < FD_SETSIZE; ++i) { |
|||
if (FD_ISSET(i, &read_fd_set)) { |
|||
if (i == in_sock) { |
|||
// Connection request on original socket
|
|||
accept_connection(in_sock, &peer_name, &active_fd_set); |
|||
} else { |
|||
// Data arriving on an already-connected socket
|
|||
if (read_from_peer(i, MAX_MESSAGE_LENGTH) < 0) { |
|||
close(i); |
|||
FD_CLR(i, &active_fd_set); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void handle_alarm(int sig) { |
|||
if (sig != SIGALRM) { |
|||
return; |
|||
} else { |
|||
sigalrm_flag = true; |
|||
} |
|||
} |
@ -1,28 +0,0 @@ |
|||
#ifndef ZAQAR_H_ |
|||
#define ZAQAR_H_ |
|||
|
|||
#include <stdbool.h> |
|||
#include <stdio.h> |
|||
#include <errno.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <netdb.h> |
|||
#include <arpa/inet.h> |
|||
#include <sys/select.h> |
|||
|
|||
#include <sys/signalfd.h> |
|||
|
|||
#include "helpers.h" |
|||
#include "node.h" |
|||
|
|||
#define TIMER_INTERVAL 10 |
|||
#define PORT 5000 |
|||
#define MAX_MESSAGE_LENGTH 277 |
|||
#define BACKLOG_SIZE 2 |
|||
|
|||
void handle_alarm(int sig); |
|||
|
|||
#endif //ZAQAR_H_
|
@ -1,517 +0,0 @@ |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
#include "unity.h" |
|||
#include "circ_buff.h" |
|||
|
|||
#define BUFFER_SIZE 8 |
|||
#define BUFFER_ELEMENT_SIZE 278 |
|||
|
|||
int compar(const void* entry1, const void* entry2) { |
|||
char **pstr1 = (char**)entry1, **pstr2 = (char**)entry2; |
|||
char *str1 = calloc(strlen(*pstr1) + 1, sizeof(char)), |
|||
*str2 = calloc(strlen(*pstr2) + 1, sizeof(char)); |
|||
strcpy(str1, *pstr1); |
|||
strcpy(str2, *pstr2); |
|||
|
|||
const char s[2] = "_"; |
|||
strtok(str1, s); |
|||
char* rest = strtok(NULL, ""); |
|||
int num1 = atoi(rest); |
|||
|
|||
strtok(str2, s); |
|||
rest = strtok(NULL, ""); |
|||
int num2 = atoi(rest); |
|||
|
|||
free(str1); |
|||
free(str2); |
|||
|
|||
return num1 - num2; |
|||
} |
|||
|
|||
void free_buffer(char** buffer) { |
|||
for(uint8_t i = 0; i < BUFFER_SIZE; ++i) { |
|||
free(buffer[i]); |
|||
} |
|||
} |
|||
|
|||
void test_circ_buf_init(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
TEST_ASSERT_NOT_NULL(circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE)); |
|||
|
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_put(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
circ_buf_put(circ_buf, temp); |
|||
} |
|||
|
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_0", buffer[0], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_1", buffer[1], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_2", buffer[2], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_3", buffer[3], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_4", buffer[4], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_5", buffer[5], BUFFER_ELEMENT_SIZE); |
|||
|
|||
for(uint8_t i = 0; i < BUFFER_SIZE; ++i) { |
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
circ_buf_put(circ_buf, temp); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_2", buffer[0], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_3", buffer[1], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_4", buffer[2], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_5", buffer[3], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_6", buffer[4], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_7", buffer[5], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_0", buffer[6], BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_1", buffer[7], BUFFER_ELEMENT_SIZE); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_mul_add(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
char** to_add = (char **) malloc(5 * sizeof(char*)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
to_add[i] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
if (i < 5) { |
|||
snprintf(to_add[i], BUFFER_ELEMENT_SIZE, "string_%d", i + 10); |
|||
} |
|||
|
|||
circ_buf_put(circ_buf, temp); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
circ_buf_mul_add(circ_buf, to_add, 5, compar); |
|||
|
|||
char* actual = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_3", actual, BUFFER_ELEMENT_SIZE); |
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_4", actual, BUFFER_ELEMENT_SIZE); |
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_5", actual, BUFFER_ELEMENT_SIZE); |
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_10", actual, BUFFER_ELEMENT_SIZE); |
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_11", actual, BUFFER_ELEMENT_SIZE); |
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_12", actual, BUFFER_ELEMENT_SIZE); |
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_13", actual, BUFFER_ELEMENT_SIZE); |
|||
circ_buf_get(circ_buf, actual); |
|||
TEST_ASSERT_EQUAL_STRING_LEN("string_14", actual, BUFFER_ELEMENT_SIZE); |
|||
|
|||
free(actual); |
|||
circ_buf_free(circ_buf); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_get(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
circ_buf_put(circ_buf, temp); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
char* actual = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
char* expected = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
circ_buf_get(circ_buf, actual); |
|||
snprintf(expected, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, BUFFER_ELEMENT_SIZE); |
|||
} |
|||
|
|||
free(actual); |
|||
free(expected); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_read(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
circ_buf_put(circ_buf, temp); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
char* actual = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
char* expected = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
circ_buf_read(circ_buf, i, actual); |
|||
snprintf(expected, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, BUFFER_ELEMENT_SIZE); |
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE - 2, circ_buf_size(circ_buf)); |
|||
} |
|||
|
|||
free(actual); |
|||
free(expected); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_serialize(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
circ_buf_put(circ_buf, temp); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
char* serialized; |
|||
uint8_t serialized_length = circ_buf_serialize(circ_buf, &serialized); |
|||
TEST_ASSERT_EQUAL_UINT8(53, serialized_length); |
|||
|
|||
char* expected = "string_0\rstring_1\rstring_2\rstring_3\rstring_4\rstring_5"; |
|||
TEST_ASSERT_EQUAL_STRING_LEN(expected, serialized, 53); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_deserialize(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
char* serialized = "string_0\rstring_1\rstring_2\rstring_3\rstring_4\rstring_5"; |
|||
uint8_t deserialized_size = circ_buf_deserialize(circ_buf, serialized); |
|||
TEST_ASSERT_EQUAL_UINT8(6, deserialized_size); |
|||
|
|||
char* actual = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
char* expected = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
circ_buf_get(circ_buf, actual); |
|||
snprintf(expected, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, BUFFER_ELEMENT_SIZE); |
|||
} |
|||
|
|||
free(actual); |
|||
free(expected); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_empty(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
TEST_ASSERT_TRUE(circ_buf_empty(circ_buf)); |
|||
|
|||
for(uint8_t i = 0; i < BUFFER_SIZE; ++i) { |
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
} |
|||
|
|||
TEST_ASSERT_FALSE(circ_buf_empty(circ_buf)); |
|||
|
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < BUFFER_SIZE; ++i) { |
|||
circ_buf_get(circ_buf, temp); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
TEST_ASSERT_TRUE(circ_buf_empty(circ_buf)); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
|
|||
void test_circ_buf_full(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 1); ++i) { |
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
TEST_ASSERT_FALSE(circ_buf_full(circ_buf)); |
|||
} |
|||
|
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
TEST_ASSERT_TRUE(circ_buf_full(circ_buf)); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
|
|||
void test_circ_buf_capacity(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE, circ_buf_capacity(circ_buf)); |
|||
|
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE, circ_buf_capacity(circ_buf)); |
|||
|
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
circ_buf_get(circ_buf, temp); |
|||
free(temp); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE, circ_buf_capacity(circ_buf)); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_size(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(0, circ_buf_size(circ_buf)); |
|||
|
|||
for(uint8_t i = 0; i < BUFFER_SIZE; ++i) { |
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
TEST_ASSERT_EQUAL_INT8(i + 1, circ_buf_size(circ_buf)); |
|||
} |
|||
|
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
|
|||
for(uint8_t i = 0; i < BUFFER_SIZE; ++i) { |
|||
circ_buf_get(circ_buf, temp); |
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE - i - 1, circ_buf_size(circ_buf)); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_reset(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
for(uint8_t i = 0; i < BUFFER_SIZE - 3; ++i) { |
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
} |
|||
|
|||
circ_buf_reset(circ_buf); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(0, circ_buf_size(circ_buf)); |
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE, circ_buf_capacity(circ_buf)); |
|||
TEST_ASSERT_TRUE(circ_buf_empty(circ_buf)); |
|||
TEST_ASSERT_FALSE(circ_buf_full(circ_buf)); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_circ_buf_element_size(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_ELEMENT_SIZE, circ_buf_element_size(circ_buf)); |
|||
|
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_ELEMENT_SIZE, circ_buf_element_size(circ_buf)); |
|||
|
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
circ_buf_get(circ_buf, temp); |
|||
free(temp); |
|||
|
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_ELEMENT_SIZE, circ_buf_element_size(circ_buf)); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_advance_pointer(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
advance_pointer(circ_buf); |
|||
TEST_ASSERT_EQUAL_INT8(1, circ_buf_size(circ_buf)); |
|||
advance_pointer(circ_buf); |
|||
TEST_ASSERT_EQUAL_INT8(2, circ_buf_size(circ_buf)); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_retreat_pointer(void) { |
|||
char** buffer = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf = circ_buf_init(buffer, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
for(uint8_t i = 0; i < BUFFER_SIZE - 3; ++i) { |
|||
circ_buf_put(circ_buf, "Lorem ipsum"); |
|||
} |
|||
|
|||
retreat_pointer(circ_buf); |
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE - 4, circ_buf_size(circ_buf)); |
|||
retreat_pointer(circ_buf); |
|||
TEST_ASSERT_EQUAL_INT8(BUFFER_SIZE - 5, circ_buf_size(circ_buf)); |
|||
|
|||
circ_buf_free(circ_buf); |
|||
free_buffer(buffer); |
|||
free(buffer); |
|||
} |
|||
|
|||
void test_diff_bufs(void) { |
|||
char** buffer1 = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
char** buffer2 = (char **) malloc(BUFFER_SIZE * sizeof(char *)); |
|||
for (uint8_t buff_el = 0; buff_el < BUFFER_SIZE; ++buff_el) { |
|||
buffer1[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
buffer2[buff_el] = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
} |
|||
|
|||
cbuf_handle_t circ_buf1 = circ_buf_init(buffer1, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
cbuf_handle_t circ_buf2 = circ_buf_init(buffer2, BUFFER_SIZE, BUFFER_ELEMENT_SIZE); |
|||
|
|||
char* temp = (char *) malloc(BUFFER_ELEMENT_SIZE * sizeof(char)); |
|||
for(uint8_t i = 0; i < (BUFFER_SIZE - 2); ++i) { |
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i); |
|||
circ_buf_put(circ_buf1, temp); |
|||
|
|||
snprintf(temp, BUFFER_ELEMENT_SIZE, "string_%d", i + 2); |
|||
circ_buf_put(circ_buf2, temp); |
|||
} |
|||
|
|||
free(temp); |
|||
|
|||
char** add1 = NULL; |
|||
char** add2 = NULL; |
|||
diff_bufs(circ_buf1, circ_buf2, &add1, &add2); |
|||
|
|||
TEST_ASSERT_NOT_NULL(add1[0]); |
|||
TEST_ASSERT_NOT_NULL(add2[0]); |
|||
|
|||
TEST_ASSERT_EQUAL_STRING("string_6", add1[0]); |
|||
TEST_ASSERT_EQUAL_STRING("string_7", add1[1]); |
|||
TEST_ASSERT_EQUAL_STRING(EOB, add1[2]); |
|||
TEST_ASSERT_EQUAL_STRING("string_0", add2[0]); |
|||
TEST_ASSERT_EQUAL_STRING("string_1", add2[1]); |
|||
TEST_ASSERT_EQUAL_STRING(EOB, add2[2]); |
|||
|
|||
circ_buf_free(circ_buf1); |
|||
free_buffer(buffer1); |
|||
free(buffer1); |
|||
circ_buf_free(circ_buf2); |
|||
free_buffer(buffer2); |
|||
free(buffer2); |
|||
} |
@ -0,0 +1,107 @@ |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
#include "unity.h" |
|||
#include "message.h" |
|||
|
|||
struct message_t { |
|||
char *message; |
|||
uint16_t received_from, *sent_to; |
|||
observer_func *observers; |
|||
int message_length, num_sent_to, num_observers; |
|||
}; |
|||
|
|||
void test_message_init(void) { |
|||
const char message[] = "testing"; |
|||
|
|||
message_handle_t message_handle = message_init(message, strlen(message), 0); |
|||
|
|||
TEST_ASSERT_NOT_NULL(message_handle); |
|||
TEST_ASSERT_EQUAL_INT(strlen(message), message_handle->message_length); |
|||
TEST_ASSERT_EQUAL_INT(0, message_handle->num_sent_to); |
|||
TEST_ASSERT_EQUAL_INT(0, message_handle->num_observers); |
|||
|
|||
message_free(message_handle); |
|||
} |
|||
|
|||
void test_message_add_sent_to(void) { |
|||
const char message[] = "testing"; |
|||
message_handle_t message_handle = message_init(message, strlen(message), 0); |
|||
|
|||
const uint16_t expected[] = {4, 345, 26463, 35, 43663, 347, 3262}; |
|||
for (int i = 0; i < 7; ++i) { |
|||
message_add_sent_to(message_handle, expected[i]); |
|||
} |
|||
|
|||
TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, message_handle->sent_to, 7); |
|||
|
|||
message_free(message_handle); |
|||
} |
|||
|
|||
void test_message_get(void) { |
|||
const char expected[] = "testing"; |
|||
message_handle_t message_handle = message_init(expected, strlen(expected), 0); |
|||
|
|||
int message_length = -1; |
|||
char *actual = message_get(message_handle, &message_length); |
|||
|
|||
TEST_ASSERT_EQUAL_UINT16(strlen(expected), message_length); |
|||
TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, message_length); |
|||
|
|||
free(actual); |
|||
message_free(message_handle); |
|||
} |
|||
|
|||
void test_message_sent_to(void) { |
|||
const char message[] = "testing"; |
|||
message_handle_t message_handle = message_init(message, strlen(message), 0); |
|||
|
|||
const uint16_t expected[] = {4, 345, 26463, 35, 43663, 347, 3262}; |
|||
for (int i = 0; i < 7; ++i) { |
|||
message_add_sent_to(message_handle, expected[i]); |
|||
} |
|||
|
|||
TEST_ASSERT_EQUAL_INT(7, message_handle->num_sent_to); |
|||
|
|||
TEST_ASSERT_TRUE(message_sent_to(message_handle, 345)); |
|||
TEST_ASSERT_TRUE(message_sent_to(message_handle, 43663)); |
|||
TEST_ASSERT_TRUE(message_sent_to(message_handle, 347)); |
|||
TEST_ASSERT_FALSE(message_sent_to(message_handle, 0)); |
|||
TEST_ASSERT_FALSE(message_sent_to(message_handle, -1)); |
|||
TEST_ASSERT_FALSE(message_sent_to(message_handle, 348)); |
|||
|
|||
message_free(message_handle); |
|||
} |
|||
|
|||
bool globalTestVariable = false; |
|||
void test_observer(void) { |
|||
globalTestVariable = true; |
|||
} |
|||
|
|||
void test_message_attach_observer(void) { |
|||
const char message[] = "testing"; |
|||
message_handle_t message_handle = message_init(message, strlen(message), 0); |
|||
|
|||
message_attach_observer(message_handle, test_observer); |
|||
|
|||
TEST_ASSERT_EQUAL_INT(1, message_handle->num_observers); |
|||
TEST_ASSERT_NOT_NULL(message_handle->observers); |
|||
TEST_ASSERT_EQUAL_PTR(test_observer, message_handle->observers[0]); |
|||
|
|||
message_free(message_handle); |
|||
} |
|||
|
|||
void test_message_state_changed(void) { |
|||
const char message[] = "testing"; |
|||
message_handle_t message_handle = message_init(message, strlen(message), 0); |
|||
|
|||
message_attach_observer(message_handle, &test_observer); |
|||
globalTestVariable = false; |
|||
message_state_changed(message_handle); |
|||
|
|||
TEST_ASSERT_TRUE(globalTestVariable); |
|||
|
|||
message_free(message_handle); |
|||
} |
@ -1,176 +0,0 @@ |
|||
#include <stdlib.h> |
|||
#include "unity.h" |
|||
|
|||
#include "node.h" |
|||
|
|||
struct node_t { |
|||
struct sockaddr_in addr; |
|||
uint64_t** events; |
|||
uint64_t appearance_duration; |
|||
uint8_t events_size; |
|||
node_status _node_status; |
|||
}; |
|||
|
|||
void test_node_init(void) { |
|||
struct sockaddr_in myaddr; |
|||
|
|||
myaddr.sin_family = AF_INET; |
|||
myaddr.sin_port = htons(2288); |
|||
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
node_handle_t node = node_init(myaddr); |
|||
TEST_ASSERT_NOT_NULL(node); |
|||
|
|||
node_free(node); |
|||
} |
|||
|
|||
void test_node_add_timestamp(void) { |
|||
struct sockaddr_in myaddr; |
|||
|
|||
myaddr.sin_family = AF_INET; |
|||
myaddr.sin_port = htons(2288); |
|||
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
node_handle_t node = node_init(myaddr); |
|||
|
|||
time_t base_time = time(NULL); |
|||
|
|||
node_add_timestamp(node, base_time - 15, true); |
|||
TEST_ASSERT_EQUAL_MEMORY(base_time - 15, node->events[0][0], sizeof(time_t)); |
|||
TEST_ASSERT_EQUAL_MEMORY(0, node->events[1][0], sizeof(time_t)); |
|||
|
|||
node_add_timestamp(node, base_time - 10, false); |
|||
TEST_ASSERT_EQUAL_MEMORY(base_time - 10, node->events[1][0], sizeof(time_t)); |
|||
|
|||
node_add_timestamp(node, base_time - 5, true); |
|||
TEST_ASSERT_EQUAL_MEMORY(base_time - 5, node->events[0][1], sizeof(time_t)); |
|||
TEST_ASSERT_EQUAL_MEMORY(0, node->events[1][1], sizeof(time_t)); |
|||
|
|||
node_add_timestamp(node, base_time, false); |
|||
TEST_ASSERT_EQUAL_MEMORY(base_time, node->events[1][1], sizeof(time_t)); |
|||
|
|||
node_add_timestamp(node, base_time + 5, false); |
|||
TEST_ASSERT_EQUAL_MEMORY(base_time, node->events[1][1], sizeof(time_t)); |
|||
|
|||
node_add_timestamp(node, base_time + 10, true); |
|||
TEST_ASSERT_EQUAL_MEMORY(base_time + 10, node->events[0][2], sizeof(time_t)); |
|||
TEST_ASSERT_EQUAL_MEMORY(0, node->events[1][2], sizeof(time_t)); |
|||
|
|||
node_free(node); |
|||
} |
|||
|
|||
void test_node_get_addr(void){ |
|||
struct sockaddr_in myaddr; |
|||
|
|||
myaddr.sin_family = AF_INET; |
|||
myaddr.sin_port = htons(2288); |
|||
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
node_handle_t node = node_init(myaddr); |
|||
|
|||
struct sockaddr_in actual = node_get_addr(node); |
|||
TEST_ASSERT_EQUAL_MEMORY(&myaddr, &actual, sizeof(myaddr)); |
|||
|
|||
node_free(node); |
|||
} |
|||
|
|||
void test_node_get_status(void){ |
|||
struct sockaddr_in myaddr; |
|||
|
|||
myaddr.sin_family = AF_INET; |
|||
myaddr.sin_port = htons(2288); |
|||
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
node_handle_t node = node_init(myaddr); |
|||
|
|||
TEST_ASSERT_EQUAL_INT(NODE_INITIALIAZED, node_get_status(node)); |
|||
|
|||
node_add_timestamp(node, time(NULL), true); |
|||
TEST_ASSERT_EQUAL_INT(NODE_PRESENT, node_get_status(node)); |
|||
|
|||
node_add_timestamp(node, time(NULL), false); |
|||
TEST_ASSERT_EQUAL_INT(NODE_GONE, node_get_status(node)); |
|||
|
|||
node_free(node); |
|||
} |
|||
|
|||
void test_node_get_latest_appearance_duration(void){ |
|||
struct sockaddr_in myaddr; |
|||
|
|||
myaddr.sin_family = AF_INET; |
|||
myaddr.sin_port = htons(2288); |
|||
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
node_handle_t node = node_init(myaddr); |
|||
|
|||
time_t base_time = time(NULL); |
|||
node_add_timestamp(node, base_time - 10, true); |
|||
TEST_ASSERT_UINT8_WITHIN(1, 10, node_get_latest_appearance_duration(node)); |
|||
|
|||
node_add_timestamp(node, base_time + 10, false); |
|||
TEST_ASSERT_EQUAL_UINT8(20, node_get_latest_appearance_duration(node)); |
|||
|
|||
node_free(node); |
|||
} |
|||
|
|||
void test_node_get_total_appearance_duration(void){ |
|||
struct sockaddr_in myaddr; |
|||
|
|||
myaddr.sin_family = AF_INET; |
|||
myaddr.sin_port = htons(2288); |
|||
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
node_handle_t node = node_init(myaddr); |
|||
|
|||
time_t base_time = time(NULL); |
|||
|
|||
node_add_timestamp(node, base_time - 30, true); |
|||
node_add_timestamp(node, base_time - 25, false); |
|||
TEST_ASSERT_EQUAL_UINT8(5, node_get_total_appearance_duration(node)); |
|||
|
|||
node_add_timestamp(node, base_time - 12, true); |
|||
node_add_timestamp(node, base_time - 5, false); |
|||
TEST_ASSERT_EQUAL_UINT8(12, node_get_total_appearance_duration(node)); |
|||
|
|||
node_free(node); |
|||
} |
|||
|
|||
void test_node_get_event_table(void){ |
|||
struct sockaddr_in myaddr; |
|||
|
|||
myaddr.sin_family = AF_INET; |
|||
myaddr.sin_port = htons(2288); |
|||
myaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|||
|
|||
node_handle_t node = node_init(myaddr); |
|||
|
|||
time_t base_time = time(NULL); |
|||
|
|||
node_add_timestamp(node, base_time - 15, true); |
|||
node_add_timestamp(node, base_time - 10, false); |
|||
node_add_timestamp(node, base_time - 5, true); |
|||
node_add_timestamp(node, base_time, false); |
|||
node_add_timestamp(node, base_time + 5, false); |
|||
node_add_timestamp(node, base_time + 10, true); |
|||
|
|||
time_t** event_table; |
|||
uint8_t num_entries = node_get_event_table(node, &event_table); |
|||
TEST_ASSERT_EQUAL_UINT8(3, num_entries); |
|||
TEST_ASSERT_NOT_NULL(event_table); |
|||
|
|||
time_t** expected_table = (time_t**) malloc(2 * sizeof(time_t *)); |
|||
expected_table[0] = (time_t*) malloc(3 * sizeof(time_t)); |
|||
expected_table[1] = (time_t*) malloc(3 * sizeof(time_t)); |
|||
|
|||
expected_table[0][0] = base_time - 15; |
|||
expected_table[1][0] = base_time - 10; |
|||
expected_table[0][1] = base_time - 5; |
|||
expected_table[1][1] = base_time; |
|||
expected_table[0][2] = base_time + 10; |
|||
expected_table[1][2] = 0; |
|||
|
|||
TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected_table[0], event_table[0], sizeof(time_t), 3); |
|||
TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected_table[1], event_table[1], sizeof(time_t), 3); |
|||
|
|||
node_free(node); |
|||
} |
Loading…
Reference in new issue