From 9ec8bae94edd0752e2644d8d10053a0f57ab38e5 Mon Sep 17 00:00:00 2001 From: weijiel6 <weijiel6@student.unimelb.edu.au> Date: Mon, 29 Apr 2019 22:08:12 +1000 Subject: [PATCH] final submit one --- http-server.c | 254 ++++++-------------------- weijiel6_comp30023_2019_project-1.rar | Bin 4197 -> 4084 bytes 2 files changed, 57 insertions(+), 197 deletions(-) diff --git a/http-server.c b/http-server.c index 18f5c49..ad22a69 100644 --- a/http-server.c +++ b/http-server.c @@ -23,7 +23,9 @@ #include <unistd.h> // used to check whether the game is finished -bool check_end(int sockfd, char* word_putin); +bool check_end(int sockfd, char* word_putin); + +bool make_file(int sockfd, char *filepath); // constants static char const * const HTTP_200_FORMAT = "HTTP/1.1 200 OK\r\n\ @@ -122,31 +124,9 @@ static bool handle_http_request(int sockfd) // assume the only valid request URI is "/" but it can be modified to accept more files if (*curr == ' ') if (method == GET) - { - // get the size of the file - struct stat st; - stat("1_intro.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("1_intro.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); + { + // send the intro html + make_file(sockfd , "1_intro.html"); } else if (method == POST) { @@ -161,30 +141,8 @@ static bool handle_http_request(int sockfd) player2_r = false; quit_game = true; } - // get the size of the file - struct stat st; - stat("7_gameover.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("7_gameover.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); + // send the game over html + make_file(sockfd , "7_gameover.html"); } else if (strstr(buff, "user=") != NULL) { // locate the username, it is safe to do so in this sample code, but usually the result is expected to be @@ -249,36 +207,14 @@ static bool handle_http_request(int sockfd) else if (*curr == '?') { if (method == GET) { - // change the players state + // change the players active state if (sockfd == player1_s) { player1_r = true; } else if (sockfd == player2_s) { player2_r = true; } - // get the size of the file - struct stat st; - stat("3_first_turn.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("3_first_turn.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); + // send the first turn in html + make_file(sockfd , "3_first_turn.html"); } else if (method == POST) { @@ -293,30 +229,8 @@ static bool handle_http_request(int sockfd) player2_r = false; quit_game = true; } - // get the size of the file - struct stat st; - stat("7_gameover.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("7_gameover.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); + // send the game over html + make_file(sockfd , "7_gameover.html"); } else if (strstr(buff, "guess=") != NULL) { @@ -325,30 +239,9 @@ static bool handle_http_request(int sockfd) // if the quit game flag is true would quit the game if (quit_game) { - // get the size of the file - struct stat st; - stat("7_gameover.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("7_gameover.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); + + // send the game over html + make_file(sockfd , "7_gameover.html"); } // if the end game flag is ture would end the game @@ -362,30 +255,8 @@ static bool handle_http_request(int sockfd) player2_r = false; player2_w_len = 0; } - // get the size of the file - struct stat st; - stat("6_endgame.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("6_endgame.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); + // send the end game html + make_file(sockfd , "6_endgame.html"); } // if both players are ready, would send accepted file @@ -404,32 +275,12 @@ static bool handle_http_request(int sockfd) player2_r = false; player2_w_len = 0; } - // get the size of the file - struct stat st; - stat("6_endgame.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("6_endgame.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); + // send the end game html + make_file(sockfd , "6_endgame.html"); } else { - // keep put ward in and guess + // keep put ward in and guess + + // get the size of the file struct stat st; stat("4_accepted.html", &st); @@ -457,31 +308,9 @@ static bool handle_http_request(int sockfd) } } else { // not both players active so send discarded file - // get the size of the file - struct stat st; - stat("5_discarded.html", &st); - n = sprintf(buff, HTTP_200_FORMAT, st.st_size); - // send the header first - if (write(sockfd, buff, n) < 0) - { - perror("write"); - return false; - } - // send the file - int filefd = open("5_discarded.html", O_RDONLY); - do - { - n = sendfile(sockfd, filefd, NULL, 2048); - } - while (n > 0); - if (n < 0) - { - perror("sendfile"); - close(filefd); - return false; - } - close(filefd); - } + // send the end game html + make_file(sockfd , "5_discarded.html"); + } } else // never used, just for completeness @@ -498,6 +327,37 @@ static bool handle_http_request(int sockfd) return true; } +bool make_file(int sockfd, char *filepath) { + char buff[2049]; + int n; + // get the size of the file + struct stat st; + stat(filepath, &st); + n = sprintf(buff, HTTP_200_FORMAT, st.st_size); + // send the header first + if (write(sockfd, buff, n) < 0) + { + perror("write"); + return false; + } + // send the file + int filefd = open(filepath, O_RDONLY); + do + { + n = sendfile(sockfd, filefd, NULL, 2048); + } + while (n > 0); + if (n < 0) + { + perror("sendfile"); + close(filefd); + return false; + } + close(filefd); + return true; +} + + // check the word list and change the end game flag and put the word into list bool check_end(int sockfd, char* word_putin) { if (sockfd == player1_s) { diff --git a/weijiel6_comp30023_2019_project-1.rar b/weijiel6_comp30023_2019_project-1.rar index a3d20b8f7b40a677582cbfddfd68fd927e91a74a..974e53336e7283cd98909f3bd11b5b1ae922ea8c 100644 GIT binary patch delta 3861 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 V@sD}0n{wIL|2$$_&EUY!006p|ef|Id delta 3955 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 OU)Yb>Rx>!TGXMZ`5~EiD -- GitLab