From 72e7559c68c78345c0d59d1207f40b569bfbd3b9 Mon Sep 17 00:00:00 2001 From: sotech117 Date: Sun, 24 Sep 2023 00:11:53 +0000 Subject: pass all control tests! --- client.c | 182 +++++++++++++++++++++++++++---------------------------- protocol.c | 33 +++++++++- server.c | 2 +- snowcast_control | Bin 18552 -> 18672 bytes snowcast_server | Bin 28720 -> 28792 bytes 5 files changed, 122 insertions(+), 95 deletions(-) diff --git a/client.c b/client.c index f39f839..06adbb1 100644 --- a/client.c +++ b/client.c @@ -1,8 +1,3 @@ - -/* -** client.c -- a stream socket client demo -*/ - #include #include #include @@ -24,7 +19,9 @@ #define MAX_READ_SIZE 1024 #define LINE_MAX 1024 -void *reply_thread_routine(void *args); +void *command_line_routine(void *args); + +int station_is_set = 0; // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa) @@ -45,7 +42,7 @@ int main(int argc, char *argv[]) char s[INET6_ADDRSTRLEN]; if (argc != 4) { - fprintf(stderr, "usage: \n"); + fprintf(stderr," \n"); exit(1); } @@ -89,17 +86,7 @@ int main(int argc, char *argv[]) freeaddrinfo(servinfo); // all done with this structure - pthread_t reply_thread; - pthread_create(&reply_thread, NULL, reply_thread_routine, (void*)sockfd); - - usleep(100); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = TIMEOUT; - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - perror("setsockopt"); - } + apply_timeout(sockfd); struct Hello hello; hello.commandType = 0; @@ -111,123 +98,95 @@ int main(int argc, char *argv[]) exit(1); } - // CONSIDER: could recieve the welcome message here + // recv the first byte of the message to get it's type + uint8_t reply_type = -1; + // print size of utin8 + if (recv(sockfd, &reply_type, 1, 0) == -1) { + perror("recv"); + exit(1); + } + // recv the message, check for errors too + int16_t num_stations = -1; + int bytes_to_read = sizeof(uint16_t); + if (recv_all(sockfd, &num_stations, &bytes_to_read) == -1) { + perror("recv_all"); + exit(1); + } - char input[LINE_MAX]; - while (1) { - char *line = fgets(input, LINE_MAX, stdin); + remove_timeout(sockfd); - if (line == NULL) { - continue; - } else if (strncmp("q\n", input, LINE_MAX) == 0) { - // end code if type in q - printf("Exiting.\n"); - break; - } else { - // convert input to an int - int inputInt = atoi(input); - // printf("Changing to station %d.\n", inputInt); + num_stations = ntohs(num_stations); + fflush(stdout); + printf("Welcome to Snowcast! The server has %d stations.\n", num_stations); + fflush(stdout); + + pthread_t command_line_thread; + pthread_create(&command_line_thread, NULL, command_line_routine, (void*)sockfd); - // send the command to change the station - tv.tv_sec = 0; - tv.tv_usec = TIMEOUT; - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - perror("setsockopt"); - } - struct SetStation setStation; - setStation.commandType = 1; - setStation.stationNumber = htons(inputInt); - int bytes_to_send = sizeof(struct SetStation); - if (send_all(sockfd, &setStation, &bytes_to_send) == -1) { - perror("send_all"); - exit(1); - } - } - } - return 0; -} -void *reply_thread_routine(void* args) { - int sockfd = (int)args; + // CONSIDER: could recieve the welcome message here // int recvbytes; while (1) { // recv the first byte of the message to get it's type - int reply_type; + uint8_t reply_type = -1; // print size of utin8 if (recv(sockfd, &reply_type, 1, 0) == -1) { perror("recv"); exit(1); } - - fprintf(stderr, "reply_type: %d\n", reply_type); if (reply_type == 2) { // we have a welcome message - // recv the message, check for errors too - uint16_t buf_num_stations; - int bytes_to_read = sizeof(uint16_t); - if (recv_all(sockfd, &buf_num_stations, &bytes_to_read) == -1) { - perror("recv_all"); - exit(1); - } - uint16_t num_stations = ntohs(buf_num_stations); - fprintf(stdout, "Welcome to Snowcast! The server has %u stations.\n", num_stations); - fprintf(stderr, "Welcome to Snowcast! The server has %u stations.\n", num_stations); - // printf("Click q to end stream.\n"); - - struct timeval no_tv; - no_tv.tv_sec = 0; - no_tv.tv_usec = 0; - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &no_tv, sizeof(no_tv)) < 0) { - perror("setsockopt"); - } - continue; + close(sockfd); + exit(1); } if (reply_type == 3) { // we have an announce message + if (!station_is_set) { + fprintf(stderr, "ANNOUNCE received whem station not set."); + close(sockfd); + exit(1); + } + // get the string size - int string_size; - if (recv(sockfd, &string_size, 1, 0) == -1) - { + u_int8_t string_size = -1; + if (recv(sockfd, &string_size, 1, 0) == -1) { perror("recv"); exit(1); } - char *song_name = malloc(string_size); if(song_name == NULL) { perror("malloc in song name"); } - if (recv_all(sockfd, song_name, &string_size) == -1) { + int bytes_to_read = string_size; + if (recv_all(sockfd, song_name, &bytes_to_read) == -1) { perror("recv_all"); exit(1); } + remove_timeout(sockfd); + // remove_timeout(sockfd); + fflush(stdout); printf("New song announced: %s\n", song_name); + fflush(stdout); free(song_name); continue; } else if (reply_type == 4) { // we have an invalid command message // get the string size - int string_size; + u_int8_t string_size = -1; if (recv(sockfd, &string_size, 1, 0) == -1) { perror("recv"); exit(1); } - - printf("string size: %d\n", string_size); - char *message = malloc(string_size); if(message == NULL) { perror("malloc in message"); } - if (recv_all(sockfd, message, &string_size) == -1) { + int bytes_to_read = string_size; + if (recv_all(sockfd, message, &bytes_to_read) == -1) { perror("recv_all"); exit(1); } - struct timeval no_tv; - no_tv.tv_sec = 0; - no_tv.tv_usec = 0; - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &no_tv, sizeof(no_tv)) < 0) { - perror("setsockopt"); - } + fflush(stdout); printf("Invalid protocol: %s. Exiting.\n", message); - fprintf(stderr, "Invalid protocol: %s. Exiting.\n", message); + fflush(stdout); free(message); close(sockfd); exit(1); @@ -237,4 +196,45 @@ void *reply_thread_routine(void* args) { close(sockfd); exit(1); } + return 0; +} + +void *command_line_routine(void* args) { + int sockfd = (int) args; + + char input[LINE_MAX]; + printf("Enter a number to change to it's station. Click q to end stream.\n"); + while (1) { + char *line = fgets(input, LINE_MAX, stdin); + + if (line == NULL) { + continue; + } else if (strncmp("q\n", input, LINE_MAX) == 0) { + // end code if type in q + printf("Exiting.\n"); + close(sockfd); + exit(0); + } else { + // convert input to an int + int inputInt = atoi(input); + // printf("Changing to station %d.\n", inputInt); + + // send the command to change the station + apply_timeout(sockfd); + struct SetStation setStation; + setStation.commandType = 1; + setStation.stationNumber = htons(inputInt); + int bytes_to_send = sizeof(struct SetStation); + // apply_timeout(sockfd); + if (send_all(sockfd, &setStation, &bytes_to_send) == -1) { + perror("send_all"); + exit(1); + } + if (!station_is_set) { + station_is_set = 1; + } + } + } + + return (NULL); } \ No newline at end of file diff --git a/protocol.c b/protocol.c index d350221..5c8127f 100644 --- a/protocol.c +++ b/protocol.c @@ -3,13 +3,13 @@ #include "protocol.h" -#define TIMEOUT 100000 // 100ms in microseconds +#define TCP_TIMEOUT 100000 // 100ms in microseconds int send_all(int sock, char *buf, int *len) { struct timeval timeout; timeout.tv_sec = 0; - timeout.tv_usec = 100000; + timeout.tv_usec = TCP_TIMEOUT; // if (setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, // sizeof timeout) < 0) // perror("setsockopt failed\n"); @@ -35,7 +35,7 @@ int recv_all(int sock, char *buf, int *len) // setup the timeout on the socket struct timeval timeout; timeout.tv_sec = 0; - timeout.tv_usec = TIMEOUT; + timeout.tv_usec = TCP_TIMEOUT; if (setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout) < 0) perror("setsockopt failed\n"); @@ -64,3 +64,30 @@ int recv_all(int sock, char *buf, int *len) return n==-1?-1:0; // return -1 on failure, 0 on success } + +int apply_timeout(int fd) { + // handle handshake + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = TCP_TIMEOUT; + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + perror("setsockopt (in apply_timeout)"); + return -1; + } + + return 1; +} + +int remove_timeout(int fd) +{ + // handle handshake + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + perror("setsockopt (in remove_timeout)"); + return -1; + } + + return 1; +} \ No newline at end of file diff --git a/server.c b/server.c index aed8904..ccde0bb 100644 --- a/server.c +++ b/server.c @@ -570,7 +570,7 @@ void *select_routine(void *arg) { } else { struct timeval tv; tv.tv_sec = 0; - tv.tv_usec = TIMEOUT; + tv.tv_usec = TCP_TIMEOUT; if (setsockopt(newfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { perror("setsockopt"); } diff --git a/snowcast_control b/snowcast_control index 21e448c..f1c54f0 100755 Binary files a/snowcast_control and b/snowcast_control differ diff --git a/snowcast_server b/snowcast_server index 7516d88..d383b01 100755 Binary files a/snowcast_server and b/snowcast_server differ -- cgit v1.2.3-70-g09d2