Final assignment for the course "Real Time and Embedded Systems" of THMMY in AUTH university.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.8 KiB

#include "helpers.h"
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(void) {
// 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];
int count = 0;
while (1 == fscanf(arpCache, ARP_LINE_FORMAT, ipAddr)) {
printf("%03d: [%s]\n", ++count, ipAddr);
}
fclose(arpCache);
}
/*
* 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(const char *ipv4, uint16_t port, const char *message) {
int out_sock;
struct sockaddr_in peer_name;
// 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
init_sockaddr(&peer_name, ipv4, port);
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];
}