/* * vowelizer_server.cpp * * Author: Jett Penner * Date Created: February 15, 2022 * * Purpose: Created for CPSC441 W2022 Assignment 2 * */ #include #include #include #include #include #include #define LISTEN_NUM 5 #define MAX_MESSAGE_LENGTH 400 #define NEXT_PORT 1 // Will host the UDP server on a port +1 higher than the input port number // Menu Selections #define ALLDONE 0 #define SIMPLE_SPLIT 1 #define ADVANCED_SPLIT 2 #define BONUS_SPLIT 3 #define SUPER_BONUS_SPLIT 4 #define SIMPLE_MERGE 5 #define ADVANCED_MERGE 6 #define BONUS_MERGE 7 #define SUPER_BONUS_MERGE 8 #define MENU 9 #define ACK "ACK" int childsockfd; // Function for graceful exit void catcher(int sig) { close(childsockfd); exit(0); } // Function to determine if a character is a vowel bool isVowel(char c) { return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U'; } bool isUppercaseVowel(char c) { return c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U'; } // Main Program int main(int argc, char *argv[]) { // Declare variables for TCP port setup int port_tcp, port_udp, parentsockfd, pid; struct sockaddr_in tcp_server; static struct sigaction act; char message_in[MAX_MESSAGE_LENGTH], message_out[MAX_MESSAGE_LENGTH]; char *p; // Declare variables for UDP port setup struct sockaddr_in si_server, si_client; struct sockaddr *udp_server, *client; int s; unsigned int length = sizeof(si_server); char messagein[MAX_MESSAGE_LENGTH]; char messageout[MAX_MESSAGE_LENGTH]; int readBytes; // Handle the command line, set the port numbers if (argc < 2) { printf("No port specified. Please specify a port.\n"); exit(-1); } port_tcp = strtol(argv[1], &p, 0); port_udp = port_tcp + NEXT_PORT; printf("TCP port: %d\n", port_tcp); printf("UDP port: %d\n", port_udp); // Create signal handler for termination conditions act.sa_handler = catcher; sigfillset(&(act.sa_mask)); sigaction(SIGPIPE, &act, NULL); // Initialize TCP server structure memset(&tcp_server, 0, sizeof(tcp_server)); tcp_server.sin_family = AF_INET; tcp_server.sin_port = htons(port_tcp); tcp_server.sin_addr.s_addr = htonl(INADDR_ANY); // Set up TCP endpoint if ((parentsockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "socket() call failed when trying to create the TCP parent socket\n"); exit(1); } // Bind to TCP address if (bind(parentsockfd, (struct sockaddr*) &tcp_server, sizeof(struct sockaddr_in)) == -1) { fprintf(stderr, "bind() call failed for TCP parent socket\n"); exit(1); } // Set up UDP endpoint if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { printf("socket() call failed when trying to create UDP socket\n"); return 1; } memset((char*) &si_server, 0, sizeof(si_server)); si_server.sin_family = AF_INET; si_server.sin_port = htons(port_udp); si_server.sin_addr.s_addr = htonl(INADDR_ANY); udp_server = (struct sockaddr*) &si_server; client = (struct sockaddr*) &si_client; // Bind to UDP address if (bind(s, udp_server, sizeof(si_server)) == -1) { printf("bind() call failed for UDP socket\n", port_udp); return 1; } // Listen for TCP clients if (listen(parentsockfd, LISTEN_NUM) == -1) { fprintf(stderr, "listen() call failed\n"); exit(1); } // Initialize message strengths to be null bzero(message_in, MAX_MESSAGE_LENGTH); bzero(message_out, MAX_MESSAGE_LENGTH); // Main listening loop while (1) { // Accept a connection if ((childsockfd = accept(parentsockfd, NULL, NULL)) == -1) { fprintf(stderr, "accept() call failed for parent socket\n"); exit(1); } // Create child process pid = fork(); if (pid < 0) { fprintf(stderr, "fork() call failed for parent process\n"); exit(1); } else if (pid == 0) { close(parentsockfd); // Declare variables to be used by a child process int choice, len, count, cons_index, vowel_index, i, char_value; char menu[MAX_MESSAGE_LENGTH], message_vowels[MAX_MESSAGE_LENGTH], message_consonants[MAX_MESSAGE_LENGTH], merged_message[MAX_MESSAGE_LENGTH], message_vowels_advanced[MAX_MESSAGE_LENGTH]; bool vowel_loop; // Create the menu bzero(menu, MAX_MESSAGE_LENGTH); strcat(menu, "\n Choose from the following:\n"); strcat(menu, " 8 - Super bonus merge a word\n"); strcat(menu, " 7 - Bonus merge a word\n"); strcat(menu, " 6 - Advanced merge a word\n"); strcat(menu, " 5 - Simple merge a word\n"); strcat(menu, " 4 - Super bonus split a word\n"); strcat(menu, " 3 - Bonus split a word\n"); strcat(menu, " 2 - Advanced split a word\n"); strcat(menu, " 1 - Simple split a word\n"); strcat(menu, " 0 - Exit program\n"); strcat(menu, "Your desired menu selection? "); // Clear message bzero(message_in, MAX_MESSAGE_LENGTH); bzero(message_out, MAX_MESSAGE_LENGTH); bzero(messagein, MAX_MESSAGE_LENGTH); bzero(messageout, MAX_MESSAGE_LENGTH); // Establish initial UDP connection if ((readBytes = recvfrom(s, messagein, MAX_MESSAGE_LENGTH, 0, client, &length)) < 0) { printf("recvfrom() failed to receive from client\n"); return -1; } printf("UDP socket received the message: %s\n", messagein); strcpy(messageout, ACK); printf("UDP socket sending the message: %s\n", messageout); sendto(s, messageout, strlen(messageout), 0, client, length); // Recieving loop while (1) { if (recv(childsockfd, message_in, MAX_MESSAGE_LENGTH, 0) > 0) { choice = (int) message_in[0] - 48; printf("Choice: %d\n", choice); if (choice == MENU) { // Send the menu strcpy(message_out, menu); } else if (choice == SIMPLE_SPLIT) { // Perform a simple split strcpy(message_out, "Please insert a phrase for a simple split: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_in, MAX_MESSAGE_LENGTH); bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(messageout, MAX_MESSAGE_LENGTH); // Split the message into consonants and vowels if (recv(childsockfd, message_in, MAX_MESSAGE_LENGTH, 0) > 0) { printf("Performing simple split on: %s\n", message_in); len = 0; for (char c : message_in) { if (c == '\0') { message_vowels[len] = '\0'; message_vowels[len] = '\0'; break; } if (isVowel(c)) { message_vowels[len] = c; message_consonants[len] = ' '; } else { message_vowels[len] = ' '; message_consonants[len] = c; } len++; } // Copy consonants to send over TCP strcpy(message_out, message_consonants); // Copy vowels, send over UDP strcpy(messageout, message_vowels); printf("UDP socket sending the message: %s\n", messageout); sendto(s, messageout, strlen(messageout), 0, client, length); } } else if (choice == ADVANCED_SPLIT) { // Perform an advanced split strcpy(message_out, "Please insert a phrase for an advanced split: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_in, MAX_MESSAGE_LENGTH); bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(messageout, MAX_MESSAGE_LENGTH); // Split the message into consonants and vowels if (recv(childsockfd, message_in, MAX_MESSAGE_LENGTH, 0) > 0) { printf("Performing advanced split on: %s\n", message_in); cons_index = vowel_index = count = 0; for (char c : message_in) { if (c == '\0') break; if (isVowel(c)) { message_vowels[vowel_index] = (char) count + 48; message_vowels[vowel_index + 1] = c; vowel_index += 2; count = 0; } else { message_consonants[cons_index] = c; cons_index++; count++; } } // Copy consonants to send over TCP strcpy(message_out, message_consonants); // Copy vowels, send over UDP strcpy(messageout, message_vowels); printf("UDP socket sending the message: %s\n", messageout); sendto(s, messageout, strlen(messageout), 0, client, length); } } else if (choice == BONUS_SPLIT) { // Perform the bonus mark split strcpy(message_out, "Please insert a phrase for the bonus split: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_in, MAX_MESSAGE_LENGTH); bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(messageout, MAX_MESSAGE_LENGTH); // Split the message into consonants and vowels if (recv(childsockfd, message_in, MAX_MESSAGE_LENGTH, 0) > 0) { printf("Performing bonus split on: %s\n", message_in); cons_index = vowel_index = count = 0; for (char c : message_in) { if (c == '\0') break; if (isVowel(c)) { if (count != 0) { message_vowels[vowel_index] = (char) count + 48; message_vowels[vowel_index + 1] = c; vowel_index += 2; count = 0; } else { message_vowels[vowel_index] = c; vowel_index++; } } else { message_consonants[cons_index] = c; cons_index++; count++; } } // Copy consonants to send over TCP strcpy(message_out, message_consonants); // Copy vowels, send over UDP strcpy(messageout, message_vowels); printf("UDP socket sending the message: %s\n", messageout); sendto(s, messageout, strlen(messageout), 0, client, length); } } else if (choice == SUPER_BONUS_SPLIT) { // Perform the super bonus mark split strcpy(message_out, "Please insert a phrase for the super bonus split: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_in, MAX_MESSAGE_LENGTH); bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(messageout, MAX_MESSAGE_LENGTH); bzero(message_vowels_advanced, MAX_MESSAGE_LENGTH); // Split the message into consonants and vowels if (recv(childsockfd, message_in, MAX_MESSAGE_LENGTH, 0) > 0) { printf("Performing super bonus split on: %s\n", message_in); cons_index = vowel_index = count = 0; for (char c : message_in) { if (c == '\0') break; if (isVowel(c)) { message_vowels[vowel_index] = (char) count + 48; message_vowels[vowel_index + 1] = c; vowel_index += 2; count = 0; } else { message_consonants[cons_index] = c; cons_index++; count++; } } // Shrink the vowel message vowel_index = count = 0; vowel_loop = false; for (char c : message_vowels) { if (c == '\0') break; if (vowel_loop) { if (isUppercaseVowel(c)) { message_vowels_advanced[vowel_index] = ' '; c += 32; vowel_index++; } switch (c) { case 'a': // a is 33 - 42 ( '!' to '*' ) message_vowels_advanced[vowel_index] = (char) (count + 33); break; case 'e': // e is 43 - 52 ( '+' to '4' ) message_vowels_advanced[vowel_index] = (char) (count + 43); break; case 'i': // i is 53 - 62 ( '5' to '>' ) message_vowels_advanced[vowel_index] = (char) (count + 53); break; case 'o': // o is 63 - 72 ( '?' to 'H' ) message_vowels_advanced[vowel_index] = (char) (count + 63); break; case 'u': // u is 73 - 82 ( 'I' to 'R' ) message_vowels_advanced[vowel_index] = (char) (count + 73); break; default: fprintf(stderr, "Super bonus split: %c is not a vowel.\n", c); exit(1); } vowel_index++; } else { count = (int) c - 48; if (count > 9 || count < 0) { fprintf(stderr, "Found an invalid count in bonus split: %d\n", count); exit(1); } } vowel_loop = !vowel_loop; } strcpy(message_vowels, message_vowels_advanced); // Copy consonants to send over TCP strcpy(message_out, message_consonants); // Copy vowels, send over UDP strcpy(messageout, message_vowels); printf("UDP socket sending the message: %s\n", messageout); sendto(s, messageout, strlen(messageout), 0, client, length); } } else if (choice == SIMPLE_MERGE) { // Perform the merge strcpy(message_out, "Please insert the consonants to merge: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(merged_message, MAX_MESSAGE_LENGTH); bzero(message_in, MAX_MESSAGE_LENGTH); bzero(messagein, MAX_MESSAGE_LENGTH); // Receive vowels via UDP if ((readBytes = recvfrom(s, messagein, MAX_MESSAGE_LENGTH, 0, client, &length)) < 0) { printf( "recvfrom() error reading vowels from client\n"); return -1; } printf("UDP socket received the message: %s\n", messagein); strcpy(message_vowels, messagein); // Receive consonants via TCP len = 0; if (recv(childsockfd, message_consonants, MAX_MESSAGE_LENGTH, 0) > 0) { for (char c : message_consonants) { if (c == '\0') break; if (message_consonants[len] == ' ' && message_vowels[len] != ' ') merged_message[len] = message_vowels[len]; else merged_message[len] = message_consonants[len]; len++; } } strcpy(message_out, merged_message); } else if (choice == ADVANCED_MERGE) { // Perform the merge strcpy(message_out, "Please insert the consonants to merge: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(merged_message, MAX_MESSAGE_LENGTH); bzero(messagein, MAX_MESSAGE_LENGTH); // Receive vowels via UDP if ((readBytes = recvfrom(s, messagein, MAX_MESSAGE_LENGTH, 0, client, &length)) < 0) { printf( "recvfrom() error reading vowels from client\n"); return -1; } printf("UDP socket received the message: %s\n", messagein); strcpy(message_vowels, messagein); // Receive consonants via TCP len = 0; if (recv(childsockfd, message_consonants, MAX_MESSAGE_LENGTH, 0) > 0) { cons_index = vowel_index = 0; vowel_loop = false; for (char c : message_vowels) { if (c == '\0') break; if (vowel_loop) { merged_message[len] = message_vowels[vowel_index]; len++; vowel_index++; } else { count = ((int) c) - 48; for (i = 0; i < count; i++) { merged_message[len] = message_consonants[cons_index]; len++; cons_index++; } vowel_index++; } vowel_loop = !vowel_loop; } while (message_consonants[cons_index] != '\0') { merged_message[len] = message_consonants[cons_index]; len++; cons_index++; } } strcpy(message_out, merged_message); } else if (choice == BONUS_MERGE) { // Perform the bonus mark merge strcpy(message_out, "Please insert the consonants to merge: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(merged_message, MAX_MESSAGE_LENGTH); bzero(messagein, MAX_MESSAGE_LENGTH); // Receive vowels via UDP if ((readBytes = recvfrom(s, messagein, MAX_MESSAGE_LENGTH, 0, client, &length)) < 0) { printf( "recvfrom() error reading vowels from client\n"); return -1; } printf("UDP socket received the message: %s\n", messagein); strcpy(message_vowels, messagein); // Receive consonants via TCP len = 0; char_value = 0; if (recv(childsockfd, message_consonants, MAX_MESSAGE_LENGTH, 0) > 0) { cons_index = vowel_index = 0; vowel_loop = false; for (char c : message_vowels) { if (c == '\0') break; char_value = (int) c - 48; if (char_value > 0 && char_value < 10) vowel_loop = false; else vowel_loop = true; if (vowel_loop) { merged_message[len] = message_vowels[vowel_index]; len++; vowel_index++; } else { count = ((int) c) - 48; for (i = 0; i < count; i++) { merged_message[len] = message_consonants[cons_index]; len++; cons_index++; } vowel_index++; } } while (message_consonants[cons_index] != '\0') { merged_message[len] = message_consonants[cons_index]; len++; cons_index++; } } strcpy(message_out, merged_message); } else if (choice == SUPER_BONUS_MERGE) { // Perform the merge strcpy(message_out, "Please insert the consonants to merge: "); // Send the message printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_out, MAX_MESSAGE_LENGTH); bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(message_consonants, MAX_MESSAGE_LENGTH); bzero(merged_message, MAX_MESSAGE_LENGTH); bzero(messagein, MAX_MESSAGE_LENGTH); bzero(message_vowels_advanced, MAX_MESSAGE_LENGTH); // Receive vowels via UDP if ((readBytes = recvfrom(s, messagein, MAX_MESSAGE_LENGTH, 0, client, &length)) < 0) { printf( "recvfrom() error reading vowels from client\n"); return -1; } printf("UDP socket received the message: %s\n", messagein); strcpy(message_vowels, messagein); // Convert vowels to readable format vowel_loop = false; len = 0; printf("vowels: %s\n", message_vowels); for (char c : message_vowels) { if (c == '\0') break; if (c == ' ') { vowel_loop = true; continue; } else if (c >= 33 && c <= 42) { message_vowels_advanced[len] = 15 + c; message_vowels_advanced[len + 1] = 'a'; } else if (c >= 43 && c <= 52) { message_vowels_advanced[len] = 5 + c; message_vowels_advanced[len + 1] = 'e'; } else if (c >= 53 && c <= 62) { message_vowels_advanced[len] = c - 5; message_vowels_advanced[len + 1] = 'i'; } else if (c >= 63 && c <= 72) { message_vowels_advanced[len] = c - 15; message_vowels_advanced[len + 1] = 'o'; } else if (c >= 73 && c <= 82) { message_vowels_advanced[len] = c - 25; message_vowels_advanced[len + 1] = 'u'; } else { fprintf(stderr, "Super bonus split found a count out of range: %d\n", c); exit(1); } if (vowel_loop) { vowel_loop = false; message_vowels_advanced[len + 1] -= 32; } len += 2; } bzero(message_vowels, MAX_MESSAGE_LENGTH); bzero(merged_message, MAX_MESSAGE_LENGTH); strcpy(message_vowels, message_vowels_advanced); // Receive consonants via TCP if (recv(childsockfd, message_consonants, MAX_MESSAGE_LENGTH, 0) > 0) { // Merge consonants and vowels cons_index = vowel_index = 0; vowel_loop = false; len = 0; for (char c : message_vowels) { if (c == '\0') break; if (vowel_loop) { merged_message[len] = message_vowels[vowel_index]; len++; vowel_index++; } else { count = ((int) c) - 48; for (i = 0; i < count; i++) { merged_message[len] = message_consonants[cons_index]; len++; cons_index++; } vowel_index++; } vowel_loop = !vowel_loop; } while (message_consonants[cons_index] != '\0') { merged_message[len] = message_consonants[cons_index]; len++; cons_index++; } } strcpy(message_out, merged_message); } else strcpy(message_out, "Error reading"); // Send the corresponding message over TCP printf("Sending the message: %s\n", message_out); if (send(childsockfd, message_out, strlen(message_out), 0) == -1) { fprintf(stderr, "send() call failed for child socket\n"); exit(1); } // Clear message bzero(message_in, MAX_MESSAGE_LENGTH); bzero(message_out, MAX_MESSAGE_LENGTH); } } close(childsockfd); exit(0); } else { close(childsockfd); } } }