Xinghang Sun 1 year ago
parent
commit
f1d020856e
6 changed files with 460 additions and 13 deletions
  1. 3 6
      boggle4/Makefile
  2. BIN
      boggle4/boggle
  3. BIN
      boggle4/user_data
  4. 75 5
      game_server.c
  5. 366 0
      game_server2.c
  6. 16 2
      players.c

+ 3 - 6
boggle4/Makefile

@@ -2,9 +2,6 @@ CC = gcc
 CFLAGS = -Wall -std=gnu99
 all: boggle
 
-socket.o: socket.c utils.h
-	$(CC) $(CFLAGS) -c socket.c
-
 game.o: game.c utils.h
 	$(CC) $(CFLAGS) -c game.c
 
@@ -17,9 +14,9 @@ users.o: users.c utils.h
 dictionary.o: dictionary.c
 	$(CC) $(CFLAGS) -c dictionary.c
 
-boggle: game.o words.o users.o dictionary.o socket.o
-	$(CC) $(CFLAGS) -o boggle socket.o game.o words.o users.o dictionary.o
+boggle: game.o words.o users.o dictionary.o
+	$(CC) $(CFLAGS) -o boggle game.o words.o users.o dictionary.o
 
 clean: 
-	rm game.o words.o users.o socket.o
+	rm game.o words.o users.o 
 

BIN
boggle4/boggle


BIN
boggle4/user_data


+ 75 - 5
game_server.c

@@ -1,5 +1,9 @@
 #define _GNU_SOURCE 
 #include "game_server.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "boggle4/game.c"
 
 Player *player_list = NULL;
 
@@ -30,7 +34,40 @@ int main(int argc, char* argv[]) {
 
 	//TODO: implement select()
     	while(1){
-		
+		fd_set fds_to_read;
+    		FD_ZERO(&fds_to_read);
+    		int max_num_fd = 0;
+    		FD_SET(listenfd, &fds_to_read); 
+    		int fd_max = listenfd + 1;
+    		Client* current_client = client_list; 
+    		while (current_client != NULL) {
+    			FD_SET(current_client->fd, &fds_to_read);
+    			if (current_client->fd + 1 > fd_max) {
+    				fd_max = current_client->fd + 1;
+    			}
+    		}
+    		
+    		int select_return_value;
+    		if ((select_return_value = select(fd_max, &fds_to_read, NULL, NULL, &select_wait_length)) < 0) { 
+    			perror("select");
+    			exit(1);
+    		} else if (select_return_value == 0) {
+    			fprintf(stderr, "Select() Timed Out\n");
+    		} else { 
+    			current_client = client_list;
+    			while (current_client != NULL) {
+    				if (FD_ISSET(current_client->fd, &fds_to_read)) {
+    					p = current_client;
+    					receiveclient(p);
+    				}
+    			}
+    			if (FD_ISSET(listenfd, &fds_to_read)) {
+    				new_connection(listenfd);
+    			}
+    		}
+    		
+    		select_wait_length.tv_sec = TIMER_TICK - 1; 
+    		select_wait_length.tv_usec = 0;
 	}
 	return 0;
 }
@@ -83,7 +120,7 @@ void timer_handler(int sig) {
     }
 	
 	//TODO - generate new game board
-	
+	generate_board();
 	//reset the timer so we get called again in 120 seconds
 	alarm(TIMER_TICK);
 }
@@ -117,7 +154,12 @@ void add_client(int fd, struct in_addr addr){
     p->state = NAME; //needs yet to identify new client by name
     p->inbuf = 0;
     //TODO - add it to the list of clients
-
+    Client * head = client_list;
+    while (head != NULL) {
+        head = head->next;
+    }
+    head = p;
+    p->next = NULL;
     
 	sendclient(p, "What is your player name?\n");
 }
@@ -207,10 +249,31 @@ int do_command(struct client * p, int cmd_argc, char **cmd_argv) {
         return -1;
     } else if (strcmp(cmd_argv[0], "all_players") == 0 && cmd_argc == 1) {
 		//TODO produce list of all players and their stats in nice text format and sendclient
-        
+        Client * head = client_list;
+        char * message = (char *)malloc(sizeof(char) * 256);
+        while (head != NULL){
+            strcat(message, head->name);
+            strcat(message, head->state);
+            head = head->next;
+        }
+        sendclient(p, message);
     } else if (strcmp(cmd_argv[0], "top_3") == 0 && cmd_argc == 1) {
 		//TODO produce list of top 3 players with their total score and sentclient as a text
-       
+      		Player * head = player_list;
+		Player * ct = player_list;
+		int count = 0;
+		while (ct != NULL) {
+			ct = ct->next;
+			count ++;
+		}
+        	qsort(head, count, sizeof(Player), sort_player_by_score);
+		int number = 0;
+		char * message = (char *)malloc(sizeof(char) * 256);
+		while (head != NULL) {
+            		strcat(message, head->name);
+            		strcat(message, head->total_score);
+		}
+        	sendclient(p, message);
     } else if (strcmp(cmd_argv[0], "add_score") == 0 && cmd_argc == 2) {
         char str [BUFFER_SIZE - 10];
         int score =atoi(cmd_argv[1]);
@@ -223,6 +286,13 @@ int do_command(struct client * p, int cmd_argc, char **cmd_argv) {
         sendclient(p, str);
     } else if (strcmp(cmd_argv[0], "new_game") == 0 && cmd_argc == 1) {
         //TODO -- transmit current board to be presented as a 2D array of chars
+        for (int i = 0; i < 16; ++i) {
+                for (int j = 0; j < 6; ++j) {
+                    printf(dice[i][j]);
+                    printf(" ");
+                }
+                printf("\n");
+        }
     }else {
         sendclient(p, "Incorrect syntax\r\n");
     }

+ 366 - 0
game_server2.c

@@ -0,0 +1,366 @@
+#define _GNU_SOURCE 
+#include "game_server.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+Player *player_list = NULL;
+
+Client *client_list = NULL;
+
+short port = -1;
+
+
+char dice[16][6] = {
+        {'R', 'I', 'F', 'O', 'B', 'X'},
+        {'I', 'F', 'E', 'H', 'E', 'Y'},
+        {'D', 'E', 'N', 'O', 'W', 'S'},
+        {'U', 'T', 'O', 'K', 'N', 'D'},
+        {'H', 'M', 'S', 'R', 'A', 'O'},
+        {'L', 'U', 'P', 'E', 'T', 'S'},
+        {'A', 'C', 'I', 'T', 'O', 'A'},
+        {'Y', 'L', 'G', 'K', 'U', 'E'},
+        {'Q', 'B', 'M', 'J', 'O', 'A'},
+        {'E', 'H', 'I', 'S', 'P', 'N'},
+        {'V', 'E', 'T', 'I', 'G', 'N'},
+        {'B', 'A', 'L', 'I', 'Y', 'T'},
+        {'E', 'Z', 'A', 'V', 'N', 'D'},
+        {'R', 'A', 'L', 'E', 'S', 'C'},
+        {'U', 'W', 'I', 'L', 'R', 'G'},
+        {'P', 'A', 'C', 'E', 'M', 'D'}
+};
+int board[16];
+void swap(int* i, int* j) {
+    int temp = *i;
+    *i = *j;
+    *j = temp;
+}
+void generate_board() {
+    srand(time(0));
+    int order[16];
+    int i;
+    for (i = 0; i < 16; i++) {
+        order[i] = i;
+    }
+    for (i = 0; i < 16; i++) {
+        swap(order + i, order + (rand() % (16-i)) + i);
+    }
+    for (i = 0; i < 16; i++) {
+        board[i] = dice[order[i]][rand() % 6];
+    }
+}
+int main(int argc, char* argv[]) {
+    struct client *p;
+    if (argc > 1)
+        port = (short)(atoi(argv[1]));
+    else
+        port = PORT;
+
+    int listenfd = setup();
+
+    struct sigaction alarm_handler;
+    alarm_handler.sa_handler = timer_handler;
+    sigemptyset(&alarm_handler.sa_mask);
+    alarm_handler.sa_flags = 0;
+    sigaction(SIGALRM, &alarm_handler, NULL);
+    struct timeval select_wait_length;
+    select_wait_length.tv_sec = TIMER_TICK - 1;
+    select_wait_length.tv_usec = 0;
+    alarm(TIMER_TICK);
+while(1){
+        fd_set fds_to_read;
+        FD_ZERO(&fds_to_read);
+        int max_num_fd = 0;
+        FD_SET(listenfd, &fds_to_read);
+        int fd_max = listenfd + 1;
+        Client* current_client = client_list;
+        while (current_client != NULL) {
+            FD_SET(current_client->fd, &fds_to_read);
+            if (current_client->fd + 1 > fd_max) {
+                fd_max = current_client->fd + 1;
+            }
+        }
+
+        int select_return_value;
+        if ((select_return_value = select(fd_max, &fds_to_read, NULL, NULL, &select_wait_length)) < 0) {
+            perror("select");
+            exit(1);
+        } else if (select_return_value == 0) {
+            fprintf(stderr, "Select() Timed Out\n");
+        } else {
+            current_client = client_list;
+            while (current_client != NULL) {
+                if (FD_ISSET(current_client->fd, &fds_to_read)) {
+                    p = current_client;
+                    receiveclient(p);
+                }
+            }
+            if (FD_ISSET(listenfd, &fds_to_read)) {
+                new_connection(listenfd);
+            }
+        }
+
+        select_wait_length.tv_sec = TIMER_TICK - 1;
+        select_wait_length.tv_usec = 0;
+    }
+    return 0;
+}
+
+void timer_handler(int sig) {
+    Client *curr;
+    for (curr = client_list; curr!=NULL; curr = curr->next) {
+        sendclient(curr, "Game over\r\n");
+    }
+
+    generate_board(); 
+}
+
+int setup (void) {
+	int on = 1, status;
+	struct sockaddr_in self;
+	int listenfd;
+	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+		perror("socket");
+		exit(1);
+	}
+
+	status = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
+                      (const char *) &on, sizeof(on));
+	if(status == -1) {
+		perror("setsockopt -- REUSEADDR");
+	}
+
+	memset(&self, '\0', sizeof(self));
+	self.sin_family = AF_INET;
+	self.sin_addr.s_addr = INADDR_ANY;
+	self.sin_port = htons(port);
+	printf("Listening on %d\n", port);
+	if (bind(listenfd, (struct sockaddr *)&self, sizeof(self)) == -1) {
+		perror("bind"); // probably means port is in use
+		exit(1);
+	}
+
+	if (listen(listenfd, 5) == -1) {
+		perror("listen");
+		exit(1);
+	}
+  
+	return listenfd;
+}
+
+void add_client(int fd, struct in_addr addr){
+    struct client *p = malloc(sizeof(struct client));
+    if (!p) {
+        perror("malloc failure");
+        exit(1);
+    }
+    printf("Adding client %s\n", inet_ntoa(addr));
+    fflush(stdout);
+    p->fd = fd;
+    p->state = NAME; 
+    p->inbuf = 0;
+    Client * head = client_list;
+    while (head != NULL) {
+        head = head->next;
+    }
+    head = p;
+    p->next = NULL;
+
+    sendclient(p, "What is your player name?\n");
+}
+void new_connection (int listenfd)  {
+    int fd;
+    struct sockaddr_in r;
+    socklen_t socklen = sizeof(r);
+
+    if ((fd = accept(listenfd, (struct sockaddr *)&r, &socklen)) < 0) {
+        perror("accept");
+        return;
+    } 
+    
+    printf("connection from %s\n", inet_ntoa(r.sin_addr));
+    add_client(fd, r.sin_addr);    
+}
+void remove_client(int fd) {}
+
+
+void receiveclient(struct client *p) {
+    char *after = p->buf + p->inbuf;
+    int room = BUFFER_SIZE - p->inbuf;
+    int nbytes;
+    if ((nbytes = read(p->fd, after, room)) > 0) {
+        p->inbuf += nbytes;
+        int where = find_network_newline(p->buf, p->inbuf);
+        if (where >= 0) {
+            p->buf[where] = '\0';
+            p->buf[where+1] = '\0';
+           
+            interpret_message(p);
+            where+=2; 
+            p->inbuf -= where;
+            memmove(p->buf, p->buf + where, p->inbuf);
+        }
+        room = sizeof(p->buf) - p->inbuf;
+        after = p->buf + p->inbuf;
+    } else {
+        remove_client(p->fd);
+    }
+}
+
+int create_player(const char * name, Player ** list) {
+    return 0;
+}
+
+void interpret_message(Client *p) {
+    char *buf;
+    if (p->state == NAME) {
+        strcpy(p->name, p->buf);
+        switch (create_player(p->name, &player_list)) {
+            case 1:
+                sendclient(p, "Welcome back.\r\n");
+                break;
+            case 2: 
+                asprintf(&buf, "Username too long, truncated to %d chars.\r\n", (MAX_NAME-1));
+                sendclient(p, buf);                
+                break;
+            case 0: 
+                sendclient(p, "Welcome, new player\r\n");
+                break;
+        }
+        printf("Added %s to the client list\n",p->name);
+        p->state = COMMAND;
+        sendclient(p, "Go ahead and enter player commands>\r\n");
+    } else if (!strcmp(p->buf, "q")) {
+        remove_client(p->fd);
+    } else {
+        parse_line(p);
+    }
+}
+
+int parse_line(Client *p) {
+	char * input = p->buf;
+    char *cmd_argv[INPUT_ARG_MAX_NUM];
+    int cmd_argc;
+    char *next_token = strtok(input, DELIM);
+    cmd_argc = 0;
+    while (next_token != NULL) {        
+        cmd_argv[cmd_argc] = next_token;
+        cmd_argc++;
+        next_token = strtok(NULL, DELIM);
+    }
+	
+    return (cmd_argc > 0 && do_command(p, cmd_argc, cmd_argv));
+}
+
+int sort_player_by_score(Player * p1, Player * p2){
+    if (p1->total_score < p2->total_score) {
+        return -1;
+    } else if (p1->total_score > p2->total_score){
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+char * int2str(int n) {
+    char * str = (char*)malloc(sizeof(char) * 256);
+    char buf[10] = "";
+    int i = 0;
+    int len = 0;
+    int temp = n < 0 ? -n : n;
+    if (str == NULL) {
+        return NULL;
+    }
+    
+    while (temp) {
+        buf[i++] = (temp % 10) + '0';
+        temp = temp / 10;
+    }
+    len = n < 0 ? ++i : i;
+    str[i] = 0;
+    while (1) {
+        i--;
+        if (buf[len - i - 1] == 0) {
+            break;
+        }
+        str[i] = buf[len - i - 1];
+    }
+    if (i == 0) {
+        str[i] = '-';
+    }
+    return str;
+}
+
+Player* find_player(const char * name, const Player * head){
+    Player * p = (Player*)malloc(sizeof(Player));
+    return p;
+}
+
+int do_command(struct client * p, int cmd_argc, char **cmd_argv) {
+   
+    if (cmd_argc <= 0) {
+        return 0;
+    } else if (strcmp(cmd_argv[0], "q") == 0 && cmd_argc == 1) {
+        return -1;
+    } else if (strcmp(cmd_argv[0], "all_players") == 0 && cmd_argc == 1) {
+        Client * head = client_list;
+        char * message = (char *)malloc(sizeof(char) * 256);
+        while (head != NULL){
+            strcat(message, head->name);
+            strcat(message, int2str(head->state));
+            head = head->next;
+        }
+        sendclient(p, message);
+
+    }else if (strcmp(cmd_argv[0], "top_3") == 0 && cmd_argc == 1) {
+		Player * head = player_list;
+		Player * ct = player_list;
+		int count = 0;
+		while (ct != NULL) {
+		    ct = ct->next;
+		    count ++;
+		}
+        qsort(head, count, sizeof(Player), sort_player_by_score);
+		int number = 0;
+		char * message = (char *)malloc(sizeof(char) * 256);
+	while (head != NULL) {
+            strcat(message, head->name);
+            strcat(message, int2str(head->total_score));
+		}
+        sendclient(p, message);
+    } else if (strcmp(cmd_argv[0], "add_score") == 0 && cmd_argc == 2) {
+        char str [BUFFER_SIZE - 10];
+        int score =atoi(cmd_argv[1]);
+        Player *player = find_player(p->name, player_list);
+        
+        player->total_score+=score;
+        if (score > player->max_score)
+            player->max_score = score;               
+        sprintf (str, "added score %d for player %s\r\n", score, p->name);
+        sendclient(p, str);
+    } else if (strcmp(cmd_argv[0], "new_game") == 0 && cmd_argc == 1) {
+        for (int i = 0; i < 16; ++i) {
+            for (int j = 0; j < 6; ++j) {
+                printf("%s\n", int2str(dice[i][j]));
+                printf(" ");
+            }
+            printf("\n");
+        }
+    }else {
+        sendclient(p, "Incorrect syntax\r\n");
+    }
+    return 0;
+}
+
+void sendclient(struct client *p, char *msg) {
+    write(p->fd, msg, strlen(msg));
+}
+int find_network_newline(char *buf, int inbuf) {
+	int i;
+	for (i = 0; i < inbuf - 1; i++)
+		if ((buf[i] == '\r') && (buf[i + 1] == '\n'))
+			return i;
+	return -1;
+}

+ 16 - 2
players.c

@@ -1,6 +1,7 @@
 #define _GNU_SOURCE 
 #include "game_server.h"
-
+#include <stdlib.h>
+#include <string.h>
 
 //TODO - implement this
 /*
@@ -8,7 +9,14 @@
  * of players whose head is pointed to by *player_ptr_add.
  */
 int create_player(const char *name, Player **player_ptr_add) {
-   return 0;
+    Player * p = (Player *)malloc(sizeof(Player));
+    p->name = name;
+    while (*player_ptr_add != NULL){
+        *player_ptr_add = *player_ptr_add->next;
+    }
+    *player_ptr_add = p;
+    p->next = NULL;
+    return 0;
 }
 
 //TODO - implement this
@@ -17,6 +25,12 @@ int create_player(const char *name, Player **player_ptr_add) {
  * the list starting with head. Return NULL if no such player exists. 
  */
 Player *find_player(const char *name, const Player *head) {    
+    while (head != NULL) {
+        if(strcmp(head->name, name) == 0) {
+            return head;
+        }
+        head = head->next;
+    }
     return NULL;
 }