Apostolos Fanakis
6 years ago
8 changed files with 244 additions and 173 deletions
@ -1,56 +1,179 @@ |
|||||
#include "helpers.h" |
#include "helpers.h" |
||||
|
|
||||
int create_socket(uint16_t port) { |
void set_timer_and_handler(void (*handler)(int), long int timer_interval) { |
||||
int sock; |
struct itimerval interval_timer; |
||||
struct sockaddr_in socket_name; |
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
|
// Creates the socket
|
||||
sock = socket (PF_INET, SOCK_STREAM, 0); //TODO: check if PF_INET is the right one
|
in_sock = socket(PF_INET, SOCK_STREAM, 0); |
||||
if (sock < 0) { |
if (in_sock < 0) { |
||||
perror("Couldn't create the socket."); |
perror("Couldn't create the socket."); |
||||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||||
} |
} |
||||
|
|
||||
// Gives the socket a name
|
// Gives the socket a name
|
||||
socket_name.sin_family = AF_INET; |
own_name.sin_family = AF_INET; |
||||
socket_name.sin_port = htons(port); |
own_name.sin_port = htons(port); |
||||
socket_name.sin_addr.s_addr = htonl(INADDR_ANY); |
own_name.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
|
||||
// Binds own address structure to socket
|
// Binds own address structure to socket
|
||||
if (bind(sock, (struct sockaddr *) &socket_name, sizeof(socket_name)) < 0) { |
if (bind(in_sock, (struct sockaddr *) &own_name, sizeof(own_name)) < 0) { |
||||
perror("Couldn't bind the address structure to the socket."); |
perror("Couldn't bind the address structure to the socket."); |
||||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||||
} |
} |
||||
|
|
||||
return sock; |
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_client(int file_des, uint16_t max_line) { |
int read_from_peer(int file_des, uint16_t max_line) { |
||||
char buffer[max_line]; |
char buffer[max_line]; |
||||
int nbytes; |
int num_bytes; |
||||
|
|
||||
nbytes = read(file_des, buffer, sizeof(buffer)); |
num_bytes = read(file_des, buffer, sizeof(buffer)); |
||||
if (nbytes < 0) { |
if (num_bytes < 0) { |
||||
perror("Couldn't read from client."); |
perror("Couldn't read from peer."); |
||||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||||
} else if (nbytes == 0) |
} else if (num_bytes == 0) |
||||
// End-of-file
|
// End-of-file
|
||||
return -1; |
return -1; |
||||
else { |
else { |
||||
fprintf(stderr, "Server: got message: `%s'\n", buffer); |
fprintf(stderr, "Got message: `%s'\n", buffer); |
||||
return 0; |
return 0; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
void init_sockaddr(struct sockaddr_in *name, const char *hostname, uint16_t port) { |
/*
|
||||
|
* 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; |
struct hostent *hostinfo; |
||||
|
|
||||
name->sin_family = AF_INET; |
peer_name->sin_family = AF_INET; |
||||
name->sin_port = htons(port); |
peer_name->sin_port = htons(port); |
||||
hostinfo = gethostbyname(hostname); |
hostinfo = gethostbyname(ipv4); |
||||
if (hostinfo == NULL) { |
if (hostinfo == NULL) { |
||||
fprintf(stderr, "Unknown host %s.\n", hostname); |
fprintf(stderr, "Unknown host %s.\n", ipv4); |
||||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||||
} |
} |
||||
name->sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; |
peer_name->sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; |
||||
} |
} |
||||
|
Loading…
Reference in new issue