diff --git a/lib/circ_buff.c b/lib/circ_buff.c index 2c76f97..2c9ec57 100644 --- a/lib/circ_buff.c +++ b/lib/circ_buff.c @@ -93,7 +93,9 @@ size_t circ_buf_capacity(cbuf_handle_t cbuf) { void circ_buf_put(cbuf_handle_t cbuf, const message_handle_t *data) { assert(cbuf && cbuf->buffer); - message_free(cbuf->buffer[cbuf->head]); + if (cbuf->buffer[cbuf->head]) { + message_free(cbuf->buffer[cbuf->head]); + } cbuf->buffer[cbuf->head] = *data; advance_pointer(cbuf); diff --git a/lib/helpers.c b/lib/helpers.c index 177079e..f46e59e 100644 --- a/lib/helpers.c +++ b/lib/helpers.c @@ -68,6 +68,8 @@ node_id_t extract_id_from_ip(const ipv4_t ip) { void set_timer_and_handler(void (*handler)(int), long int wakeup_time) { assert(handler); + logI("Setting up new wakeup timer."); + struct itimerval timer; struct sigaction signal_action; @@ -76,7 +78,8 @@ void set_timer_and_handler(void (*handler)(int), long int wakeup_time) { 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."); + logE("Couldn't install function handler for SIGALRM signals."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -87,7 +90,8 @@ void set_timer_and_handler(void (*handler)(int), long int wakeup_time) { timer.it_value.tv_sec = wakeup_time; if (setitimer(ITIMER_REAL, &timer, NULL) == -1) { - perror("Couldn't set timer."); + logE("Couldn't set timer."); + logI("Exiting..."); exit(EXIT_FAILURE); } } @@ -95,11 +99,15 @@ void set_timer_and_handler(void (*handler)(int), long int wakeup_time) { uint16_t create_message(char *new_message, uint16_t max_message_length, node_handle_t *neighbors, uint8_t num_neighbors, node_id_t own_id) { assert(new_message && neighbors); + + logI("Creating new message."); + node_handle_t random_node = neighbors[rand() % (num_neighbors)]; node_id_t peer_id = node_get_id(random_node); if (!peer_id) { - perror("Couldn't extract peer's ID."); + logE("Couldn't extract peer's ID."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -114,13 +122,16 @@ uint16_t create_message(char *new_message, uint16_t max_message_length, node_han * https://www.gnu.org/software/libc/manual/html_node/Inet-Example.html#Inet-Example */ int create_socket_and_listen(port_t port, uint8_t backlog_size) { + logI("Creating the socket for input connections."); + int in_sock; address_t own_name; // Creates the socket in_sock = socket(PF_INET, SOCK_STREAM, 0); if (in_sock < 0) { - perror("Couldn't create the socket."); + logE("Couldn't create the socket."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -131,12 +142,14 @@ int create_socket_and_listen(port_t port, uint8_t backlog_size) { // 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."); + logE("Couldn't bind the address structure to the socket."); + logI("Exiting..."); exit(EXIT_FAILURE); } if (listen(in_sock, backlog_size) < 0) { - perror("Couldn't listen for connections on the socket."); + logE("Couldn't listen for connections on the socket."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -146,13 +159,16 @@ int create_socket_and_listen(port_t port, uint8_t backlog_size) { void send_message(node_handle_t peer, message_handle_t message) { assert(peer && message); + logI("Sending message.") + int out_sock; address_t peer_address = node_get_addr(peer); // Creates the socket out_sock = socket(PF_INET, SOCK_STREAM, 0); if (out_sock < 0) { - perror("Couldn't create the socket."); + logE("Couldn't create the socket."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -175,10 +191,13 @@ node_id_t accept_connection(int sock, address_t *peer_name, fd_set *active_fd_se int *listens_on) { assert(peer_name && active_fd_set && listens_on); + logI("Accepting new connection."); + 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."); + logE("Couldn't accept the connection."); + logI("Exiting..."); // TODO maye be remove this? exit(EXIT_FAILURE); } @@ -198,6 +217,8 @@ uint16_t checkAddNode(node_handle_t **neighbors, uint16_t num_neighbors , address_t peer_name, node_id_t node_id) { assert(neighbors); + logI("Adding new node."); + bool node_exists = false; for (int i = 0; i < num_neighbors; ++i) { @@ -211,7 +232,8 @@ uint16_t checkAddNode(node_handle_t **neighbors, uint16_t num_neighbors , (num_neighbors + 1) * sizeof(node_handle_t)); if (!r_neighbors) { free(r_neighbors); - perror("Unable to reallocate memory for neighbor IP."); + logE("Unable to reallocate memory for neighbor IP."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -227,9 +249,12 @@ uint16_t checkAddNode(node_handle_t **neighbors, uint16_t num_neighbors , void write_to_peer(int file_desc, const char *message) { assert(message); + logI("Writing to peer."); + int num_bytes = write(file_desc, message, strlen(message) + 1); if (num_bytes < 0) { - perror("Couldn't write to peer."); + logE("Couldn't write to peer."); + logI("Exiting..."); // TODO maye be remove this? exit(EXIT_FAILURE); } @@ -237,12 +262,15 @@ void write_to_peer(int file_desc, const char *message) { int read_from_peer(int file_des, uint16_t max_line, cbuf_handle_t *message_buffer, node_handle_t **neighbors, uint16_t num_neighbors) { + logI("Reading from peer."); + 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."); + logE("Couldn't read from peer."); + logI("Exiting..."); // TODO maye be remove this? exit(EXIT_FAILURE); } else if (num_bytes == 0) { @@ -269,25 +297,30 @@ int read_from_peer(int file_des, uint16_t max_line, cbuf_handle_t *message_buffe uint16_t fread_neighbors(char *AEM_file, node_handle_t **neighbors, port_t port) { assert(AEM_file && neighbors); + + logI("Reading peers from file."); + uint16_t num_neighbors = 0; // Reads the ARP file checking for connected devices FILE *aems_file = fopen(AEM_file, "r"); if (!aems_file) { - perror("Neighbors file: Failed to open file containing the AEMs."); + logE("Neighbors file: Failed to open file containing the AEMs."); + logI("Exiting..."); exit(EXIT_FAILURE); } // Extracts IP addresses found in the file char ip_addr[AEM_BUFFER_LEN]; - char **neighbors_ips; + char **neighbors_ips = NULL; while (1 == fscanf(aems_file, AEM_LINE_FORMAT, ip_addr)) { ++num_neighbors; char **r_neighbors_ips = realloc(neighbors_ips, num_neighbors * sizeof(char *)); if (!r_neighbors_ips) { free(r_neighbors_ips); - perror("Unable to reallocate memory for neighbor IP."); + logE("Unable to reallocate memory for neighbor IP."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -300,16 +333,16 @@ uint16_t fread_neighbors(char *AEM_file, node_handle_t **neighbors, port_t port) // Allocates memory for the new neighbors structs (*neighbors) = (node_handle_t *) malloc(num_neighbors * sizeof(node_handle_t)); if (!neighbors_ips) { - perror("Unable to allocate memory for nodes."); + logE("Unable to allocate memory for nodes."); + logI("Exiting..."); exit(EXIT_FAILURE); } // Creates the neighbors structs for (uint8_t i = 0; i < num_neighbors; ++i) { address_t peer_name; - init_sockaddr(&peer_name, neighbors_ips[i], port); - (*neighbors)[num_neighbors++] = node_init(peer_name, - extract_id_from_ip(get_ip_from_sockaddr(peer_name))); + init_sockaddr(&peer_name, build_ip_from_id(neighbors_ips[i]), port); + (*neighbors)[i] = node_init(peer_name, atoi(neighbors_ips[i])); } fclose(aems_file); @@ -322,7 +355,6 @@ uint16_t fread_neighbors(char *AEM_file, node_handle_t **neighbors, port_t port) * https://www.gnu.org/software/libc/manual/html_node/Inet-Example.html#Inet-Example */ void init_sockaddr(address_t *peer_name, const ipv4_t hostname, port_t port) { - assert(peer_name && hostname); struct hostent *hostinfo; peer_name->sin_family = AF_INET; @@ -335,3 +367,32 @@ void init_sockaddr(address_t *peer_name, const ipv4_t hostname, port_t port) { peer_name->sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; } + +char *build_ip_from_id(char *id) { + static char ip[11]; + node_id_t id_int = atoi(id); + + snprintf(ip, 11, "10.0.%2d.%2d", id_int / 100, id_int % 100); + + return ip; +} + +void _zlog(LOG_LEVEL level, char *message, char *file, int line) { + switch(level) { + case DEBUG: + printf(CYAN_BOLD "debug: %s:%d - %s\n" COLOR_RESET, file, line, message); + break; + case INFO: + printf(BLUE_BOLD "info: %s:%d - %s\n" COLOR_RESET, file, line, message); + break; + case WARN: + printf(YELLOW_BOLD "warn: %s:%d - %s\n" COLOR_RESET, file, line, message); + break; + case ERROR: + printf(RED_BOLD "error: %s:%d - %s\n" COLOR_RESET, file, line, message); + break; + default: + printf("%s:%d - %s\n", file, line, message); + break; + } +} diff --git a/lib/helpers.h b/lib/helpers.h index a6635e0..f36d75b 100644 --- a/lib/helpers.h +++ b/lib/helpers.h @@ -10,6 +10,19 @@ #include "message.h" #include "circ_buff.h" +// Macros for logging +#ifdef RELEASE //This is a release build +#define logD(msg) do{ _zlog(DEBUG, msg, __FILE__, __LINE__) } while( false ) +#define logI(msg) do{ _zlog(INFO, msg, __FILE__, __LINE__) } while( false ) +#define logW(msg) do{ _zlog(WARN, msg, __FILE__, __LINE__) } while( false ) +#define logE(msg) do{ _zlog(ERROR, msg, __FILE__, __LINE__) } while( false ) +#else +#define logD(msg) +#define logW(msg) +#define logI(msg) +#define logE(msg) +#endif + // Macros to turn a numeric macro into a string literal #define xstr(s) str(s) #define str(s) #s @@ -20,6 +33,19 @@ // Format for fscanf() to read the AEM numbers #define AEM_LINE_FORMAT "%" xstr(AEM_ID_LEN) "s\n" +// Colors for console output +#define RED "[0;31m " +#define RED_BOLD "[1;31m " +#define YELLOW "[0;33m " +#define YELLOW_BOLD "[01;33m " +#define BLUE "[0;34m " +#define BLUE_BOLD "[1;34m " +#define MAGENTA "[0;35m " +#define MAGENTA_BOLD "[1;35m " +#define CYAN "[0;36m " +#define CYAN_BOLD "[1;36m " +#define COLOR_RESET "[0m" + node_id_t extract_id_from_ip(const ipv4_t ip); void set_timer_and_handler(void (*handler)(int), long int timer_interval); @@ -48,4 +74,8 @@ uint16_t fread_neighbors(char *AEM_file, node_handle_t **neighbors, void init_sockaddr(address_t *peer_name, const ipv4_t hostname, port_t port); +char *build_ip_from_id(char *id); + +void _zlog(LOG_LEVEL level, char *message, char *file, int line); + #endif //HELPERS_H_ diff --git a/lib/types.h b/lib/types.h index d63ed8b..32e9792 100644 --- a/lib/types.h +++ b/lib/types.h @@ -1,6 +1,7 @@ #ifndef CUSTOM_TYPES_H_ #define CUSTOM_TYPES_H_ +typedef enum LOG_LEVEL {DEBUG, INFO, WARN, ERROR} LOG_LEVEL; typedef uint16_t node_id_t; typedef struct sockaddr_in address_t; typedef uint64_t timestamp_t; diff --git a/src/zaqar.c b/src/zaqar.c index 166b224..1bc7a86 100644 --- a/src/zaqar.c +++ b/src/zaqar.c @@ -17,6 +17,7 @@ volatile sig_atomic_t sigalrm_flag = false; int main(int argc, char **argv) { + logI("Initializing..."); check_args(argc, argv); // Socket communication variables @@ -37,7 +38,7 @@ int main(int argc, char **argv) { message_buffer = circ_buf_init(buffer, MESSAGE_BUFFER_SIZE); // Reads neighbors' IPs from file - num_neighbors = fread_neighbors(argv[1], &neighbors, PORT); + num_neighbors = fread_neighbors(argv[2], &neighbors, PORT); // Sets a timer and handler to produce an interrupt and send a message set_timer_and_handler(handle_alarm, MIN_TIMER_VAL + rand() % (MAX_TIMER_VAL - MIN_TIMER_VAL)); @@ -97,7 +98,8 @@ int main(int argc, char **argv) { continue; } - perror("Couldn't initiate synchronous I/O multiplexing."); + logE("Couldn't initiate synchronous I/O multiplexing."); + logI("Exiting..."); exit(EXIT_FAILURE); } @@ -134,6 +136,7 @@ int main(int argc, char **argv) { } } + logI("Cleaning up allocated memory and exiting."); //Frees memory for (uint i = 0; i < circ_buf_size(message_buffer); ++i) { message_handle_t current_message; @@ -154,6 +157,7 @@ void check_args(int argc, char **argv) { if (argc != 3) { printf("Correct usage is:\n"); printf("\t%s \n", argv[0]); + logI("Exiting..."); exit(EXIT_FAILURE); } } diff --git a/src/zaqar.h b/src/zaqar.h index bb62fc5..f78d979 100644 --- a/src/zaqar.h +++ b/src/zaqar.h @@ -1,8 +1,8 @@ #ifndef ZAQAR_H_ #define ZAQAR_H_ -#define MIN_TIMER_VAL 60 -#define MAX_TIMER_VAL 300 +#define MIN_TIMER_VAL 2 +#define MAX_TIMER_VAL 4 #define PORT 5000 #define BACKLOG_SIZE 2 #define MESSAGE_BUFFER_SIZE 2000 diff --git a/zaqar.service b/zaqar.service new file mode 100644 index 0000000..22e1fcb --- /dev/null +++ b/zaqar.service @@ -0,0 +1,11 @@ +[Unit] +Description=Zaqar +After=multi-user.target + +[Service] +Type=idle +ExecStart=/bin/bash -c "/root/zaqar.out 8261 /root/aems &" +ExecStart=/root/zaqar.out + +[Install] +WantedBy=multi-user.target \ No newline at end of file