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