diff options
author | sotech117 <michael_foiani@brown.edu> | 2023-09-24 00:24:01 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2023-09-24 00:24:01 -0400 |
commit | b578b114fd919d72948b051c036b34cb60976389 (patch) | |
tree | e100258c4af1068013aab7ef521513278c133bf0 | |
parent | 9625efcaf8e7d7f57c8d2678b4d68b85dae91980 (diff) |
simplify into functions and add log output
-rw-r--r-- | server.c | 313 | ||||
-rwxr-xr-x | snowcast_server | bin | 54332 -> 54572 bytes |
2 files changed, 161 insertions, 152 deletions
@@ -91,10 +91,14 @@ void *print_user_data(int sockfd); void destroy_user(int sockfd); void send_announce_reply(int fd, int station_num); -void send_invalid_command_reply(int fd, size_t message_size, char* message); -void *send_stations_info_reply(void *arg); +void send_invalid_reply(int fd, size_t message_size, char* message); +void *send_stationsinfo_reply(void *arg); +int send_welcome_reply(int fd); +void handle_setstation_command(int fd); -// void *load_file(void* arg); +uint16_t handle_handshake(int newfd); + +int l = 1; main(int argc, char *argv[]) { @@ -179,6 +183,9 @@ main(int argc, char *argv[]) print_user_data(i); } } + else if (!strcmp(command, "log")) { + l= !l; + } } return 0; @@ -462,27 +469,15 @@ void *send_announce_routine(void *arg) { } } -// void *sync_routine(void *arg) { -// int c = 0; -// while (1) -// { -// start_threads = 1; -// pthread_cond_broadcast(&cond); -// usleep(2000); - -// start_threads = 0; -// usleep(1000000-2000); -// } -// } +fd_set master; // master file descriptor list void *select_routine(void *arg) { - fd_set master; // master file descriptor list fd_set read_fds; // temp file descriptor list for select() - int fdmax; // maximum file descriptor number int listener; // listening socket descriptor int newfd; // newly accept()ed socket descriptor + int fdmax; // maximum file descriptor number struct sockaddr_storage remoteaddr; // client address socklen_t addrlen; @@ -569,62 +564,28 @@ void *select_routine(void *arg) { if (newfd == -1) { perror("accept"); } else { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = TCP_TIMEOUT; - if (setsockopt(newfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - perror("setsockopt"); - } - - uint8_t command_type = -1; - if ((nbytes = recv(newfd, &command_type, 1, 0)) <= 0) - { - // got error or connection closed by client - if (nbytes == 0) { - // connection closed - // printf("selectserver: socket %d hung up\n", i); - } else { - perror("recv"); - } - // remove user from data structures - close(newfd); - // destroy_user(i); - continue; - } - - if (command_type != 0) { - char * message = "must send a Hello message first"; - send_invalid_command_reply(newfd, strlen(message), message); - close(newfd); - continue; - } - - // get the udp port - uint16_t udp_port = -1; - int bytes_to_read = sizeof(uint16_t); - if (recv_all(newfd, &udp_port, &bytes_to_read) == -1) { - perror("recv_all"); + // new user, we need to do the handshake + uint16_t udp_port = handle_handshake(newfd); + if (udp_port == 0) { + // drop connection upon error close(newfd); - // destroy_user(i); continue; } - udp_port = ntohs(udp_port); + // add the user to the set FD_SET(newfd, &master); // add to master set if (newfd > fdmax) { // keep track of the max fdmax = newfd; - } + } + + // TODO: thread or combine into one function + // init the user init_user(newfd); + // update the udp port update_user_udpPort(newfd, udp_port); - // send the welcome message to client - struct Welcome welcome; - welcome.replyType = 2; - welcome.numStations = htons(num_stations); - int bytes_to_send = sizeof(struct Welcome); - if (send_all(newfd, &welcome, &bytes_to_send) == -1) - perror("send_all"); - } + send_welcome_reply(newfd); + } } else { // handle data from a client uint8_t command_type = -1; @@ -633,105 +594,43 @@ void *select_routine(void *arg) { // got error or connection closed by client if (nbytes == 0) { // connection closed - // printf("selectserver: socket %d hung up\n", i); + if (l) printf("socket %d HUNGUP. lost connection.\n", newfd); } else { perror("recv"); } - close(i); // bye! - FD_CLR(i, &master); // remove from master set - // remove user from data structures destroy_user(i); } - else + else // we got some data from a client { - // we got some data from a client - if (command_type == 0) { // we got a Hello commmand - - // get the udp port - uint16_t udp_port = -1; - int bytes_to_read = sizeof(uint16_t); - if (recv_all(i, &udp_port, &bytes_to_read) == -1) { - perror("recv_all"); - close(i); - FD_CLR(i, &master); - destroy_user(i); - continue; - } - + if (command_type == 0) { // we got a HELLO commmand + // send back in invalid command if user already sent a hello if (user_data[sockfd_to_user[i]].udpPort != -1) { - // send back in invalid command + if (l) printf("received an extraneous HELLO from socket %d. sending INVALID reply.\n", i); char * message = "must not sent more than one Hello message"; - send_invalid_command_reply(i, strlen(message), message); - // drop connection upon invalid command - close(i); - FD_CLR(i, &master); + send_invalid_reply(i, strlen(message), message); destroy_user(i); - continue; } } - else if (command_type == 1) { // we got a SetStation command - // get the station number - - uint16_t station_number = -1; - int bytes_to_read = sizeof(uint16_t); - if (recv_all(i, &station_number, &bytes_to_read) == -1) { - perror("recv_all"); - close(i); - FD_CLR(i, &master); - destroy_user(i); - continue; - } - station_number = ntohs(station_number); - - // check if user has a udpPort to stream to - if (user_data[sockfd_to_user[i]].udpPort == -1) { - // send back in invalid command - char * message = "must send Hello message first"; - send_invalid_command_reply(i, strlen(message), message); - // drop connection upon invalid command - close(i); - FD_CLR(i, &master); - destroy_user(i); - continue; - } - - // check if station num is in range - if (station_number >= num_stations || station_number < 0) { - // send back in invalid command - char * message = "station number out of range"; - send_invalid_command_reply(i, strlen(message), message); - // drop connection upon invalid command - close(i); - FD_CLR(i, &master); - destroy_user(i); - continue; - } - // printf("setting station to %d\n", ntohs(command.number)); - // update station of user - update_user_station(i, station_number); - send_announce_reply(i, station_number); + else if (command_type == 1) { // we got a SETSTATION command + handle_setstation_command(i); } else if (command_type == 5) { // we got a ListStations command + if (l) printf("received a LISTSTATIONS from socket %d\n", i); pthread_t t; - pthread_create(&t, NULL, send_stations_info_reply, i); + pthread_create(&t, NULL, send_stationsinfo_reply, i); } else { - // send back in invalid command - char * message = "invalid command"; - send_invalid_command_reply(i, strlen(message), message); - - // drop connection upon invalid command - close(i); - FD_CLR(i, &master); + if (l) printf("received unknown command type %d from socket %d. sending INVALID reply.\n", command_type, i); + char *message = "invalid command type"; + send_invalid_reply(i, strlen(message), message); destroy_user(i); } } - } // END handle data from client - } // END got new incoming connection - } // END looping through file descriptors - - } // END for(;;)--and you thought it would never end! + } + } + } + } } void *init_user(int sockfd) { @@ -766,7 +665,10 @@ void *init_user(int sockfd) { sockfd_to_user[sockfd] = running_index; // free(user_stream_threads); pthread_mutex_unlock(&mutex_user_data); + + return (NULL); } + void *update_user_udpPort(int sockfd, int udpPort) { pthread_mutex_lock(&mutex_user_data); // get the user @@ -776,6 +678,8 @@ void *update_user_udpPort(int sockfd, int udpPort) { // start the stream thread, now that we have the udpPort // pthread_create(&user->streamThread, NULL, send_udp_packet_routine, (void *)sockfd_to_user[sockfd]); pthread_mutex_unlock(&mutex_user_data); + + return (NULL); } void *update_user_station(int sockfd, int stationNum) { pthread_mutex_lock(&mutex_user_data); @@ -788,13 +692,11 @@ void *print_user_data(int index) { } void destroy_user(int sockfd) { + close(sockfd); // bye! + FD_CLR(sockfd, &master); // remove from master set + + // remove user from data structures pthread_mutex_lock(&mutex_user_data); - // stop the thread streaming to the user - // pthread_t thread = user_data[sockfd_to_user[sockfd]].streamThread; - // if (thread != -1) { - // pthread_cancel(thread); - // } - // "remove" the user from the list of user data user_data[sockfd_to_user[sockfd]] = (user_t) {-1, -1, -1}; // map sockfd to -1 sockfd_to_user[sockfd] = -1; @@ -813,6 +715,9 @@ void *get_in_addr(struct sockaddr *sa) } void send_announce_reply(int fd, int station_num) { + if (l) printf("sending ANNNOUNCE reply to socket %d\n", fd); + + char* file_path = stations[station_num].filePath; int len_file_path = strlen(file_path); @@ -833,7 +738,7 @@ void send_announce_reply(int fd, int station_num) { free(send_buffer); } -void send_invalid_command_reply(int fd, size_t message_size, char* message) { +void send_invalid_reply(int fd, size_t message_size, char* message) { char *send_buffer = malloc(message_size+2); if (!send_buffer) { perror("malloc in send invalid command"); @@ -853,11 +758,14 @@ void send_invalid_command_reply(int fd, size_t message_size, char* message) { free(send_buffer); } -void *send_stations_info_reply(void * arg) { +void *send_stationsinfo_reply(void * arg) { int fd = (int) arg; + if (l) printf("sending STATIONSINFO reply to socket %d\n", fd); + uint8_t reply_size = 0; - for (int i = 0; i < num_stations; i++) reply_size += snprintf(NULL, 0, "%d,%s\n", i, stations[i].filePath); + for (int i = 0; i < num_stations; i++) + reply_size += snprintf(NULL, 0, "%d,%s\n", i, stations[i].filePath); reply_size--; // don't want final \n // send type @@ -892,4 +800,105 @@ int parse(char buffer[LINE_MAX], char *tokens[LINE_MAX / 2]) { } return 1; -}
\ No newline at end of file +} + +uint16_t handle_handshake(int newfd) +{ + if (l) printf("waiting for HELLO command. new connection on socket %d\n", newfd); + + // apply timeout to socket + apply_timeout(newfd); + + uint8_t command_type = -1; + size_t nbytes; + if (nbytes = recv(newfd, &command_type, 1, 0) <= 0) + { + // got error or connection closed by client + if (nbytes == 0) { + // connection closed + if (l) printf("socket %d HUNGUP. lost connection.\n", newfd); + } + else + { + perror("recv in handle handshake"); + } + // remove user from data structures + close(newfd); + return 0; + } + + if (command_type != 0) { + char * message = "must send a Hello message first"; + send_invalid_reply(newfd, strlen(message), message); + close(newfd); + return 0; + } + + // get the udp port + uint16_t udp_port = -1; + int bytes_to_read = sizeof(uint16_t); + if (recv_all(newfd, &udp_port, &bytes_to_read) == -1) { + perror("recv_all"); + close(newfd); + return 0; + } + // remove timeout, after reading data + remove_timeout(newfd); + + if(l) printf("received HELLO from socket %d with udp port %u\n", newfd, ntohs(udp_port)); + + return ntohs(udp_port); +} + + +int send_welcome_reply(int fd) { + if(l) printf("sending WELCOME reply to socket %d\n", fd); + + struct Welcome welcome; + welcome.replyType = 2; + welcome.numStations = htons(num_stations); + int bytes_to_send = sizeof(struct Welcome); + if (send_all(fd, &welcome, &bytes_to_send) == -1) { + perror("send_all (in init_user_routine)"); + return -1; + } + + return 1; +} + +void handle_setstation_command(int sockfd) { + // get the station number + uint16_t station_number = -1; + int bytes_to_read = sizeof(uint16_t); + if (recv_all(sockfd, &station_number, &bytes_to_read) == -1) { + perror("recv_all"); + destroy_user(sockfd); + } + station_number = ntohs(station_number); + + // check if user has a udpPort to stream to + if (user_data[sockfd_to_user[sockfd]].udpPort == -1) { + if (l) printf("received a SETSTATION from socket %d before HELLO command. sending INVALID reply.\n", sockfd); + // send back in invalid command and drop user + char * message = "must send Hello message first"; + send_invalid_reply(sockfd, strlen(message), message); + destroy_user(sockfd); + return; + } + + if (l) printf("received a SETSTATION from socket %d with station_number %u\n", sockfd, station_number); + + // check if station num is in range + if (station_number >= num_stations || station_number < 0) { + if (l) printf("station number invalid from socket %d. sending INVALID reply.\n", sockfd); + + // send back in invalid command and drop user + char * message = "station number out of range"; + send_invalid_reply(sockfd, strlen(message), message); + destroy_user(sockfd); + return; + } + + update_user_station(sockfd, station_number); + send_announce_reply(sockfd, station_number); +} diff --git a/snowcast_server b/snowcast_server Binary files differindex 2587920..76e7ac8 100755 --- a/snowcast_server +++ b/snowcast_server |