ttsrv.c (3893B)
1 #include "tt.h" 2 #include <json.h> 3 #include <netinet/in.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <sys/socket.h> 8 #include <unistd.h> 9 10 int change_quote( 11 int quote_idx, 12 struct json_object *quotes, 13 struct state states[FD_SETSIZE], 14 int sockfd, 15 fd_set set) 16 { 17 json_object *quote = json_object_array_get_idx(quotes, quote_idx); 18 json_object_object_get_ex(quote, "text", "e); 19 const char *str_quote = json_object_get_string(quote); 20 short length = strlen(str_quote); 21 for (int i = 0; i < FD_SETSIZE; i++) { 22 states[i].pos = 0; 23 if (!(i != 0 && i != sockfd && FD_ISSET(i, &set))) { 24 continue; 25 } 26 send(i, "\x00", 1, 0); 27 send(i, &length, sizeof length, 0); 28 send(i, str_quote, length, 0); 29 } 30 } 31 32 int main(int argc, const char *argv[]) 33 { 34 if (argc != 3) { 35 fprintf(stderr, "Usage: %s <port> <quotes.json>\n", argv[0]); 36 return 1; 37 } 38 39 char *endptr; 40 long port = strtol(argv[1], &endptr, 10); 41 if (!(*argv[1] != '\0' && *endptr == '\0' && port < 65536)) { 42 fprintf(stderr, "ERROR: '%s' is not a valid port.\n", argv[1]); 43 return 1; 44 } 45 46 struct json_object *root = json_object_from_file(argv[2]); 47 if (!root) { 48 fprintf(stderr, "Failed to parse JSON file.\n"); 49 return 1; 50 } 51 struct json_object *quotes; 52 json_object_object_get_ex(root, "quotes", "es); 53 int num_quotes = json_object_array_length(quotes); 54 55 int sockfd = socket(AF_INET, SOCK_STREAM, 0); 56 if (sockfd == -1) { 57 perror("socket"); 58 return 1; 59 } 60 61 struct sockaddr_in address = { 62 .sin_family = AF_INET, 63 .sin_port = htons(port), 64 .sin_addr.s_addr = INADDR_ANY}; 65 if (bind(sockfd, (struct sockaddr *)&address, sizeof address) == -1) { 66 perror("bind"); 67 return 1; 68 } 69 if (listen(sockfd, 5) == -1) { 70 perror("listen"); 71 return 1; 72 } 73 74 fd_set set; 75 FD_ZERO(&set); 76 FD_SET(0, &set); 77 FD_SET(sockfd, &set); 78 79 struct state states[FD_SETSIZE]; 80 81 while (1) { 82 fd_set readfds = set; 83 if (select(FD_SETSIZE, &readfds, NULL, NULL, NULL) == -1) { 84 perror("select"); 85 return 1; 86 } 87 88 if (FD_ISSET(0, &readfds)) { 89 char buffer[4096]; 90 read(0, buffer, 4096); 91 long quote_idx = strtol(buffer, &endptr, 10); 92 if (!((*buffer != '\n' && *buffer != '\0') && 93 (*endptr == '\0' || *endptr == '\n'))) { 94 fprintf(stderr, "Error parsing quote index.\n"); 95 } else if (!(0 <= quote_idx && 96 quote_idx < num_quotes)) { 97 fprintf(stderr, 98 "0 <= quote_index < %d.\n", 99 num_quotes); 100 } else { 101 change_quote( 102 quote_idx, quotes, states, sockfd, set); 103 } 104 } 105 106 if (FD_ISSET(sockfd, &readfds)) { 107 int fd = accept(sockfd, NULL, NULL); 108 FD_SET(fd, &set); 109 states[fd].pos = 0; 110 printf("player %d connected\n", fd); 111 } 112 113 for (int fd = 0; fd < FD_SETSIZE; fd++) { 114 if (!(fd != 0 && fd != sockfd && 115 FD_ISSET(fd, &readfds))) { 116 continue; 117 } 118 119 struct { 120 char type; 121 unsigned int number; 122 } message; 123 124 int length = recv(fd, &message, 1 + sizeof(int), 0); 125 126 if (length == 0) { 127 states[fd].pos = 0; 128 printf("Disconnected\n"); 129 FD_CLR(fd, &set); 130 continue; 131 } 132 133 if (message.type == 0) { 134 states[fd].pos = message.number; 135 for (int dest = 0; dest < FD_SETSIZE; dest++) { 136 if (!(dest != 0 && dest != fd && 137 dest != sockfd && 138 FD_ISSET(dest, &set))) { 139 continue; 140 } 141 struct state buffer[FD_SETSIZE]; 142 unsigned short buffer_size = 0; 143 for (int i = 0; i < FD_SETSIZE; i++) { 144 if (!(i != 0 && i != dest && 145 i != sockfd && 146 FD_ISSET(i, &set))) { 147 continue; 148 } 149 buffer[buffer_size++] = 150 states[i]; 151 } 152 buffer_size *= sizeof(struct state); 153 154 send(dest, "\x01", 1, 0); 155 send(dest, &buffer_size, 2, 0); 156 send(dest, buffer, buffer_size, 0); 157 } 158 } 159 160 if (message.type == 1) { 161 int quote_idx = message.number; 162 change_quote( 163 quote_idx, quotes, states, sockfd, set); 164 } 165 } 166 } 167 return 0; 168 }